forked from external-repos/LifeTrinket
Compare commits
90 Commits
0.5.4
...
Remove-MUI
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78aee362ce | ||
|
|
0bfd3f2dd6 | ||
|
|
e4e996619f | ||
|
|
28dec3fc22 | ||
|
|
63aace2b07 | ||
|
|
ba9ca354fc | ||
|
|
e79c728e6a | ||
|
|
97f9bb75e5 | ||
|
|
341cb3cde0 | ||
|
|
ce9c9ca997 | ||
|
|
ad485f059d | ||
|
|
92f954130f | ||
|
|
112023bdd5 | ||
|
|
4e6dc56d99 | ||
|
|
e427bfd0cf | ||
|
|
ed10edc6d2 | ||
|
|
7696b357b4 | ||
|
|
a7b78b8e7a | ||
|
|
fa95d171b7 | ||
|
|
00a556be0e | ||
|
|
3276dc81fc | ||
|
|
28c2ff536f | ||
|
|
6beddf06e2 | ||
|
|
2a885f9a43 | ||
|
|
9c27f34261 | ||
|
|
fa5829b402 | ||
|
|
71f26d0dc5 | ||
|
|
3a568fc3ab | ||
|
|
355f4bd4cd | ||
|
|
17e174bfe1 | ||
|
|
e1e8da858b | ||
|
|
e02f071415 | ||
|
|
e04f31bb67 | ||
|
|
e5386d08a4 | ||
|
|
d6cd678e9f | ||
|
|
334b46db6e | ||
|
|
e03ecc6f51 | ||
|
|
d4dc44076d | ||
|
|
a1b5cfd871 | ||
|
|
f11eea5e53 | ||
|
|
905912a7fd | ||
|
|
a90dd7c9ea | ||
|
|
ef1310d674 | ||
|
|
fe3bb6c78c | ||
|
|
6d2b3b6a6f | ||
|
|
0f86928cb3 | ||
|
|
efbfb7719c | ||
|
|
71e5614f52 | ||
|
|
677fd79bee | ||
|
|
1bff41bc10 | ||
|
|
7852520f8e | ||
|
|
04c3d60967 | ||
|
|
664e2e5688 | ||
|
|
6eb7ac9f50 | ||
|
|
ef06e0d125 | ||
|
|
ae9f5707b2 | ||
|
|
a18c253624 | ||
|
|
3f319c4f3c | ||
|
|
8b33a2a38a | ||
|
|
cc915dff36 | ||
|
|
db80e563f2 | ||
|
|
573af42b75 | ||
|
|
89e1eaff4e | ||
|
|
0f4e896342 | ||
|
|
dc1d5fe01d | ||
|
|
41e73d2c0c | ||
|
|
724dcf086c | ||
|
|
51f9c4d20e | ||
|
|
354c0dbbb2 | ||
|
|
3770d13beb | ||
|
|
13733242a2 | ||
|
|
81f3891b20 | ||
|
|
e153de9093 | ||
|
|
07775f85d2 | ||
|
|
10039175a1 | ||
|
|
bcf2a0a840 | ||
|
|
d25da5d97b | ||
|
|
f5a80e573e | ||
|
|
1f36264e39 | ||
|
|
d615cfd3ba | ||
|
|
4453b12ce6 | ||
|
|
d601a820f8 | ||
|
|
0455f43794 | ||
|
|
f94103fe51 | ||
|
|
c36668b933 | ||
|
|
f9d0346300 | ||
|
|
2f3ee74c74 | ||
|
|
f8f0788b97 | ||
|
|
bfe25eacb7 | ||
|
|
7b0965c0dd |
@@ -1,8 +1,12 @@
|
||||
robots.txt,1693082171694,391d14b3c2f8c9143a27a28c7399585142228d4d1bdbe2c87ac946de411fa9a2
|
||||
manifest.json,1693082171694,91ce94afb71f33a477f5d8d48c3f98bd7de422279c74f17b6500eec72003ac1a
|
||||
assets/index-5265c558.css,1693082171837,08c4451946bbdf520fe337edb365417a8bbf91914c018b83866723ef52d57b43
|
||||
index.html,1693082171837,09e1919fbaaa3a0bf08f43eb46c29136d62a7747b41f8b5d0f4a7ed23337c344
|
||||
logo192.png,1693082171693,4309255bccbdbb341b5ab88708677e3d43b9e171d2666528ff932295a8257e4e
|
||||
favicon.ico,1693082171692,48d8c1b9714dbc9bcb012d9c9f04112d229f20e6c889bda588ac159f973e6a8d
|
||||
logo512.png,1693082171694,92c7c05dc98170596d04f48e5e60eaae9535f409bcaeff129fd98fef8aba9f4e
|
||||
assets/index-5023e89e.js,1693082171838,8a6177168e95e1ca90e5ad8774252a8a02a9a78765bd329b7deae729c01aedf3
|
||||
index.html,1711905710499,4b604b23faec8d63a58e07b96d724a1aea56a7c86d57c9af791832ce87a552e7
|
||||
manifest.webmanifest,1711905710499,f2bf253209f6e292a6b0dbfa06fb4ac188eb5f2dba568c3ad5511b9ed52c1f51
|
||||
manifest.json,1711905710294,7ff5111aa04a42adff3b38924ec467b6f345ed0309dba1486dc9b783b60c2a9d
|
||||
sw.js,1711905711506,1ef2f4f40ec8dca15cc42d547462ade1e84314ea9722276f5994ccee7bbdf80f
|
||||
robots.txt,1711905710294,391d14b3c2f8c9143a27a28c7399585142228d4d1bdbe2c87ac946de411fa9a2
|
||||
registerSW.js,1711905710499,5b6445b5215737c53ef0d379c151d57de165a056de2d1c5812ed614f158ebcbd
|
||||
workbox-3e911b1d.js,1711905711507,d5dbc868a5c07af633d29de7ba3ffe37542aaaabdf33713b4298df31f92f11ff
|
||||
assets/index-7m_Zw4yH.css,1711905710499,37997d06b32b3d0c724c054913e3c0583b86f786358121cb1615e6646ff46b56
|
||||
favicon.ico,1711905710294,8cefe5adbf00d337d8633fb744b9f2c4914f769b319be4bb7e184b7a4aa17160
|
||||
logo192.png,1711905710294,3d1e2e6f064d4fd325828f21bb6493ff0dbf2390b0e7d2aba9f2b6def4829799
|
||||
logo512.png,1711905710294,892a4da1cc5434929a83a71fcbcb0d0d80aa82f44e3c21e9b20ffe9267197133
|
||||
assets/index-CLJVONOc.js,1711905710499,22f3835412f82bb3f8a62e74a7f4602a9c43b447224790365dbcc6cbffb4e665
|
||||
|
||||
3
.github/workflows/firebase-release.yml
vendored
3
.github/workflows/firebase-release.yml
vendored
@@ -7,7 +7,8 @@ jobs:
|
||||
build_and_deploy:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
REPO_READ_ACCESS_TOKEN: ${{ secrets.REPO_READ_ACCESS_TOKEN }}
|
||||
VITE_REPO_READ_ACCESS_TOKEN: ${{ secrets.REPO_READ_ACCESS_TOKEN }}
|
||||
VITE_FIREBASE_ANALYTICS_API_KEY: ${{ secrets.FIREBASE_ANALYTICS_API_KEY }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
43
package.json
43
package.json
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "life-trinket",
|
||||
"private": true,
|
||||
"version": "0.5.4",
|
||||
"version": "0.9.7",
|
||||
"type": "commonjs",
|
||||
"engines": {
|
||||
"node": ">=18",
|
||||
"npm": "please use bun or yarn :) "
|
||||
"yarn": "use pnpm",
|
||||
"npm": "please use pnpm"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -13,38 +14,40 @@
|
||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview",
|
||||
"generate-icons": "npx @svgr/cli src/Icons/svgs",
|
||||
"deploy": "bun build && firebase deploy --only hosting"
|
||||
"deploy": "bun run build && firebase deploy --only hosting"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mui/material": "^5.13.6",
|
||||
"firebase": "^10.3.0",
|
||||
"ga-4-react": "^0.1.281",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-screen-wake-lock": "^3.0.2",
|
||||
"react-swipeable": "^7.0.1",
|
||||
"react-twc": "^1.3.0",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@savvywombat/tailwindcss-grid-areas": "^3.1.0",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@savvywombat/tailwindcss-grid-areas": "^4.0.0",
|
||||
"@svgr/cli": "^8.1.0",
|
||||
"@types/react": "^18.2.15",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"@types/react": "^18.3.1",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.8.0",
|
||||
"@typescript-eslint/parser": "^7.8.0",
|
||||
"@vitejs/plugin-react-swc": "^3.6.0",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"eslint": "^8.45.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.3",
|
||||
"firebase-tools": "^12.5.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-refresh": "^0.4.6",
|
||||
"firebase-tools": "^13.7.5",
|
||||
"install": "^0.13.0",
|
||||
"postcss": "^8.4.32",
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "2.8.8",
|
||||
"tailwindcss": "^3.4.0",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.4.5"
|
||||
"prop-types": "^15.8.1",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.2.10",
|
||||
"vite-plugin-pwa": "^0.20.0"
|
||||
}
|
||||
}
|
||||
|
||||
9373
pnpm-lock.yaml
generated
Normal file
9373
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
src/App.tsx
14
src/App.tsx
@@ -1,18 +1,14 @@
|
||||
import { ThemeProvider } from '@mui/material';
|
||||
import { LifeTrinket } from './Components/LifeTrinket';
|
||||
import { theme } from './Data/theme';
|
||||
import { GlobalSettingsProvider } from './Providers/GlobalSettingsProvider';
|
||||
import { PlayersProvider } from './Providers/PlayersProvider';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<PlayersProvider>
|
||||
<GlobalSettingsProvider>
|
||||
<LifeTrinket />
|
||||
</GlobalSettingsProvider>
|
||||
</PlayersProvider>
|
||||
</ThemeProvider>
|
||||
<PlayersProvider>
|
||||
<GlobalSettingsProvider>
|
||||
<LifeTrinket />
|
||||
</GlobalSettingsProvider>
|
||||
</PlayersProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ export type RotationButtonProps = TwcComponentProps<'button'> & {
|
||||
$rotation?: number;
|
||||
};
|
||||
|
||||
export const MAX_TAP_MOVE_DISTANCE = 20;
|
||||
|
||||
const CommanderDamageContainer = twc.div<RotationDivProps>((props) => [
|
||||
'flex flex-grow',
|
||||
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||
@@ -38,7 +40,7 @@ const CommanderDamageTextContainer = twc.div<RotationDivProps>((props) => [
|
||||
: '',
|
||||
]);
|
||||
|
||||
const PartnerDamageSeperator = twc.div<RotationDivProps>((props) => [
|
||||
const PartnerDamageSeparator = twc.div<RotationDivProps>((props) => [
|
||||
'bg-black',
|
||||
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||
? 'w-full h-px'
|
||||
@@ -54,6 +56,7 @@ type CommanderDamageButtonComponentProps = {
|
||||
type InputProps = {
|
||||
opponentIndex: number;
|
||||
isPartner: boolean;
|
||||
event: React.PointerEvent<HTMLButtonElement>;
|
||||
};
|
||||
|
||||
export const CommanderDamage = ({
|
||||
@@ -63,12 +66,8 @@ export const CommanderDamage = ({
|
||||
}: CommanderDamageButtonComponentProps) => {
|
||||
const { updatePlayer } = usePlayers();
|
||||
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||
const [timeoutFinished, setTimeoutFinished] = useState(false);
|
||||
const [hasPressedDown, setHasPressedDown] = useState(false);
|
||||
|
||||
const isSide =
|
||||
player.settings.rotation === Rotation.Side ||
|
||||
player.settings.rotation === Rotation.SideFlipped;
|
||||
const [downLongPressed, setDownLongPressed] = useState(false);
|
||||
const downPositionRef = useRef({ x: 0, y: 0 });
|
||||
|
||||
const handleCommanderDamageChange = (
|
||||
index: number,
|
||||
@@ -107,34 +106,47 @@ export const CommanderDamage = ({
|
||||
handleLifeChange(player.lifeTotal - increment);
|
||||
};
|
||||
|
||||
const handleDownInput = ({ opponentIndex, isPartner }: InputProps) => {
|
||||
setTimeoutFinished(false);
|
||||
setHasPressedDown(true);
|
||||
const handleDownInput = ({ opponentIndex, isPartner, event }: InputProps) => {
|
||||
downPositionRef.current = { x: event.clientX, y: event.clientY };
|
||||
setDownLongPressed(false);
|
||||
|
||||
timeoutRef.current = setTimeout(() => {
|
||||
setTimeoutFinished(true);
|
||||
setDownLongPressed(true);
|
||||
handleCommanderDamageChange(opponentIndex, -1, isPartner);
|
||||
}, decrementTimeoutMs);
|
||||
};
|
||||
|
||||
const handleUpInput = ({ opponentIndex, isPartner }: InputProps) => {
|
||||
if (!(hasPressedDown && !timeoutFinished)) {
|
||||
const handleUpInput = ({ opponentIndex, isPartner, event }: InputProps) => {
|
||||
if (downLongPressed) {
|
||||
return;
|
||||
}
|
||||
|
||||
const upPosition = { x: event.clientX, y: event.clientY };
|
||||
|
||||
const hasMoved =
|
||||
Math.abs(upPosition.x - downPositionRef.current.x) >
|
||||
MAX_TAP_MOVE_DISTANCE ||
|
||||
Math.abs(upPosition.y - downPositionRef.current.y) >
|
||||
MAX_TAP_MOVE_DISTANCE;
|
||||
|
||||
if (hasMoved) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(timeoutRef.current);
|
||||
|
||||
handleCommanderDamageChange(opponentIndex, 1, isPartner);
|
||||
setHasPressedDown(false);
|
||||
};
|
||||
|
||||
const handleLeaveInput = () => {
|
||||
setTimeoutFinished(true);
|
||||
setDownLongPressed(true);
|
||||
clearTimeout(timeoutRef.current);
|
||||
setHasPressedDown(false);
|
||||
};
|
||||
|
||||
const opponentIndex = opponent.index;
|
||||
const fontSize = isSide ? '4vmax' : '7vmin';
|
||||
const fontSize = player.isSide ? '4vmax' : '7vmin';
|
||||
const fontWeight = 'bold';
|
||||
const strokeWidth = isSide ? '0.4vmax' : '0.7vmin';
|
||||
const strokeWidth = player.isSide ? '0.4vmax' : '0.7vmin';
|
||||
|
||||
return (
|
||||
<CommanderDamageContainer
|
||||
@@ -145,10 +157,12 @@ export const CommanderDamage = ({
|
||||
<CommanderDamageButton
|
||||
key={opponentIndex}
|
||||
$rotation={player.settings.rotation}
|
||||
onPointerDown={() =>
|
||||
handleDownInput({ opponentIndex, isPartner: false })
|
||||
onPointerDown={(e) =>
|
||||
handleDownInput({ opponentIndex, isPartner: false, event: e })
|
||||
}
|
||||
onPointerUp={(e) =>
|
||||
handleUpInput({ opponentIndex, isPartner: false, event: e })
|
||||
}
|
||||
onPointerUp={() => handleUpInput({ opponentIndex, isPartner: false })}
|
||||
onPointerLeave={handleLeaveInput}
|
||||
onContextMenu={(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||
e.preventDefault();
|
||||
@@ -171,15 +185,15 @@ export const CommanderDamage = ({
|
||||
|
||||
{opponent.settings.usePartner && (
|
||||
<>
|
||||
<PartnerDamageSeperator $rotation={player.settings.rotation} />
|
||||
<PartnerDamageSeparator $rotation={player.settings.rotation} />
|
||||
<CommanderDamageButton
|
||||
key={opponentIndex}
|
||||
$rotation={player.settings.rotation}
|
||||
onPointerDown={() =>
|
||||
handleDownInput({ opponentIndex, isPartner: true })
|
||||
onPointerDown={(e) =>
|
||||
handleDownInput({ opponentIndex, isPartner: true, event: e })
|
||||
}
|
||||
onPointerUp={() =>
|
||||
handleUpInput({ opponentIndex, isPartner: true })
|
||||
onPointerUp={(e) =>
|
||||
handleUpInput({ opponentIndex, isPartner: true, event: e })
|
||||
}
|
||||
onPointerLeave={handleLeaveInput}
|
||||
onContextMenu={(
|
||||
|
||||
@@ -3,7 +3,7 @@ import { twc } from 'react-twc';
|
||||
import { decrementTimeoutMs } from '../../Data/constants';
|
||||
import { CounterType, Rotation } from '../../Types/Player';
|
||||
import { OutlinedText } from '../Misc/OutlinedText';
|
||||
import { RotationDivProps } from './CommanderDamage';
|
||||
import { MAX_TAP_MOVE_DISTANCE, RotationDivProps } from './CommanderDamage';
|
||||
|
||||
const ExtraCounterContainer = twc.div`
|
||||
flex
|
||||
@@ -47,6 +47,7 @@ type ExtraCounterProps = {
|
||||
type: CounterType;
|
||||
setCounterTotal: (updatedCounterTotal: number, type: CounterType) => void;
|
||||
rotation: number;
|
||||
isSide: boolean;
|
||||
playerIndex: number;
|
||||
};
|
||||
|
||||
@@ -56,14 +57,13 @@ const ExtraCounter = ({
|
||||
setCounterTotal,
|
||||
type,
|
||||
rotation,
|
||||
isSide,
|
||||
playerIndex,
|
||||
}: ExtraCounterProps) => {
|
||||
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||
const [timeoutFinished, setTimeoutFinished] = useState(false);
|
||||
const [hasPressedDown, setHasPressedDown] = useState(false);
|
||||
|
||||
const isSide =
|
||||
rotation === Rotation.Side || rotation === Rotation.SideFlipped;
|
||||
const downPositionRef = useRef({ x: 0, y: 0 });
|
||||
|
||||
const handleCountChange = (increment: number) => {
|
||||
if (!counterTotal) {
|
||||
@@ -73,7 +73,8 @@ const ExtraCounter = ({
|
||||
setCounterTotal(counterTotal + increment, type);
|
||||
};
|
||||
|
||||
const handleDownInput = () => {
|
||||
const handleDownInput = (event: React.PointerEvent<HTMLButtonElement>) => {
|
||||
downPositionRef.current = { x: event.clientX, y: event.clientY };
|
||||
setTimeoutFinished(false);
|
||||
setHasPressedDown(true);
|
||||
timeoutRef.current = setTimeout(() => {
|
||||
@@ -82,10 +83,23 @@ const ExtraCounter = ({
|
||||
}, decrementTimeoutMs);
|
||||
};
|
||||
|
||||
const handleUpInput = () => {
|
||||
const handleUpInput = (event: React.PointerEvent<HTMLButtonElement>) => {
|
||||
if (!(hasPressedDown && !timeoutFinished)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const upPosition = { x: event.clientX, y: event.clientY };
|
||||
|
||||
const hasMoved =
|
||||
Math.abs(upPosition.x - downPositionRef.current.x) >
|
||||
MAX_TAP_MOVE_DISTANCE ||
|
||||
Math.abs(upPosition.y - downPositionRef.current.y) >
|
||||
MAX_TAP_MOVE_DISTANCE;
|
||||
|
||||
if (hasMoved) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(timeoutRef.current);
|
||||
handleCountChange(1);
|
||||
setHasPressedDown(false);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { useRef, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { TwcComponentProps, twc } from 'react-twc';
|
||||
import { lifeLongPressMultiplier } from '../../Data/constants';
|
||||
import { Rotation } from '../../Types/Player';
|
||||
import { Player, Rotation } from '../../Types/Player';
|
||||
import { MAX_TAP_MOVE_DISTANCE } from './CommanderDamage';
|
||||
import { checkContrast } from '../../Utils/checkContrast';
|
||||
|
||||
type RotationButtonProps = TwcComponentProps<'div'> & {
|
||||
$align?: string;
|
||||
@@ -12,7 +14,6 @@ const LifeCounterButtonTwc = twc.button`
|
||||
h-full
|
||||
w-full
|
||||
flex
|
||||
text-lifeCounter-text
|
||||
font-semibold
|
||||
bg-transparent
|
||||
border-none
|
||||
@@ -39,29 +40,41 @@ const TextContainer = twc.div<RotationButtonProps>((props) => [
|
||||
]);
|
||||
|
||||
type LifeCounterButtonProps = {
|
||||
lifeTotal: number;
|
||||
player: Player;
|
||||
setLifeTotal: (lifeTotal: number) => void;
|
||||
rotation: number;
|
||||
operation: 'add' | 'subtract';
|
||||
increment: number;
|
||||
};
|
||||
|
||||
const LifeCounterButton = ({
|
||||
lifeTotal,
|
||||
player,
|
||||
setLifeTotal,
|
||||
rotation,
|
||||
operation,
|
||||
increment,
|
||||
}: LifeCounterButtonProps) => {
|
||||
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||
const [timeoutFinished, setTimeoutFinished] = useState(false);
|
||||
const [hasPressedDown, setHasPressedDown] = useState(false);
|
||||
const downPositionRef = useRef({ x: 0, y: 0 });
|
||||
|
||||
const [iconColor, setIconColor] = useState<'dark' | 'light'>('dark');
|
||||
|
||||
useEffect(() => {
|
||||
const contrast = checkContrast(player.color, '#00000080');
|
||||
|
||||
if (contrast === 'Fail') {
|
||||
setIconColor('light');
|
||||
} else {
|
||||
setIconColor('dark');
|
||||
}
|
||||
}, [player.color]);
|
||||
|
||||
const handleLifeChange = (increment: number) => {
|
||||
setLifeTotal(lifeTotal + increment);
|
||||
setLifeTotal(player.lifeTotal + increment);
|
||||
};
|
||||
|
||||
const handleDownInput = () => {
|
||||
const handleDownInput = (event: React.PointerEvent<HTMLButtonElement>) => {
|
||||
downPositionRef.current = { x: event.clientX, y: event.clientY };
|
||||
setTimeoutFinished(false);
|
||||
setHasPressedDown(true);
|
||||
timeoutRef.current = setTimeout(() => {
|
||||
@@ -70,10 +83,23 @@ const LifeCounterButton = ({
|
||||
}, 500);
|
||||
};
|
||||
|
||||
const handleUpInput = () => {
|
||||
const handleUpInput = (event: React.PointerEvent<HTMLButtonElement>) => {
|
||||
if (!(hasPressedDown && !timeoutFinished)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const upPosition = { x: event.clientX, y: event.clientY };
|
||||
|
||||
const hasMoved =
|
||||
Math.abs(upPosition.x - downPositionRef.current.x) >
|
||||
MAX_TAP_MOVE_DISTANCE ||
|
||||
Math.abs(upPosition.y - downPositionRef.current.y) >
|
||||
MAX_TAP_MOVE_DISTANCE;
|
||||
|
||||
if (hasMoved) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(timeoutRef.current);
|
||||
handleLifeChange(operation === 'add' ? 1 : -1);
|
||||
setHasPressedDown(false);
|
||||
@@ -86,7 +112,8 @@ const LifeCounterButton = ({
|
||||
};
|
||||
|
||||
const fontSize =
|
||||
rotation === Rotation.SideFlipped || rotation === Rotation.Side
|
||||
player.settings.rotation === Rotation.SideFlipped ||
|
||||
player.settings.rotation === Rotation.Side
|
||||
? '8vmax'
|
||||
: '12vmin';
|
||||
|
||||
@@ -102,8 +129,11 @@ const LifeCounterButton = ({
|
||||
aria-label={`${operation === 'add' ? 'Add' : 'Subtract'} life`}
|
||||
>
|
||||
<TextContainer
|
||||
$rotation={rotation}
|
||||
$rotation={player.settings.rotation}
|
||||
$align={operation === 'add' ? 'right' : 'left'}
|
||||
data-contrast={iconColor}
|
||||
className="data-[contrast=dark]:text-icons-dark
|
||||
data-[contrast=light]:text-icons-light"
|
||||
>
|
||||
{operation === 'add' ? '\u002B' : '\u2212'}
|
||||
</TextContainer>
|
||||
|
||||
@@ -4,13 +4,11 @@ import { Rotation } from '../../Types/Player';
|
||||
import { RotationDivProps } from './CommanderDamage';
|
||||
|
||||
const LoseButton = twc.div<RotationDivProps>((props) => [
|
||||
'absolute flex-grow border-none outline-none cursor-pointer bg-interface-loseButton-background rounded-lg select-none z-[1] webkit-user-select-none',
|
||||
'absolute flex-grow border-none outline-none cursor-pointer bg-interface-loseButton-background rounded-lg select-none z-[1] webkit-user-select-none py-2 px-4 ',
|
||||
|
||||
props.$rotation === Rotation.SideFlipped
|
||||
? `right-auto top-[15%] left-[27%]`
|
||||
: props.$rotation === Rotation.Side
|
||||
? `right-auto top-[15%] left-[27%]`
|
||||
: 'right-[15%] top-1/4',
|
||||
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||
? `left-[21%]`
|
||||
: 'top-[21%]',
|
||||
]);
|
||||
|
||||
type LoseButtonProps = {
|
||||
@@ -24,6 +22,8 @@ export const LoseGameButton = ({ rotation, onClick }: LoseButtonProps) => {
|
||||
? rotation
|
||||
: rotation === Rotation.Side
|
||||
? rotation - 180
|
||||
: rotation === Rotation.Flipped
|
||||
? rotation - 180
|
||||
: rotation;
|
||||
|
||||
return (
|
||||
@@ -33,7 +33,7 @@ export const LoseGameButton = ({ rotation, onClick }: LoseButtonProps) => {
|
||||
aria-label={`Lose Game`}
|
||||
style={{ rotate: `${calcRotation}deg` }}
|
||||
>
|
||||
<Skull size="5vmin" color="black" opacity={0.5} />
|
||||
<Skull size="8vmin" color="black" opacity={0.5} />
|
||||
</LoseButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import { twc } from 'react-twc';
|
||||
import { Cog } from '../../Icons/generated';
|
||||
import { Rotation } from '../../Types/Player';
|
||||
import { RotationButtonProps } from './CommanderDamage';
|
||||
|
||||
const SettingsButtonTwc = twc.button<RotationButtonProps>((props) => [
|
||||
'absolute flex-grow border-none outline-none cursor-pointer bg-transparent z-[1] select-none webkit-user-select-none',
|
||||
props.$rotation === Rotation.Side || props.$rotation === Rotation.SideFlipped
|
||||
? `right-auto top-[1vmax] left-[27%]`
|
||||
: 'top-1/4 right-[1vmax]',
|
||||
]);
|
||||
|
||||
type SettingsButtonProps = {
|
||||
onClick: () => void;
|
||||
rotation: Rotation;
|
||||
};
|
||||
|
||||
const SettingsButton = ({ onClick, rotation }: SettingsButtonProps) => {
|
||||
return (
|
||||
<SettingsButtonTwc
|
||||
onClick={onClick}
|
||||
$rotation={rotation}
|
||||
aria-label={`Settings`}
|
||||
>
|
||||
<Cog size="5vmin" color="black" opacity="0.3" />
|
||||
</SettingsButtonTwc>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingsButton;
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
import { CounterType, Player, Rotation } from '../../Types/Player';
|
||||
import { RotationDivProps } from '../Buttons/CommanderDamage';
|
||||
import ExtraCounter from '../Buttons/ExtraCounter';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { checkContrast } from '../../Utils/checkContrast';
|
||||
|
||||
const Container = twc.div<RotationDivProps>((props) => [
|
||||
'flex',
|
||||
@@ -19,9 +21,9 @@ const Container = twc.div<RotationDivProps>((props) => [
|
||||
]);
|
||||
|
||||
export const ExtraCountersGrid = twc.div<RotationDivProps>((props) => [
|
||||
'flex absolute flex-row flex-grow pointer-events-none',
|
||||
'flex absolute flex-row flex-grow pointer-events-none overflow-x-scroll overflow-y-hidden',
|
||||
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||
? 'flex-col-reverse h-full w-auto bottom-auto'
|
||||
? 'flex-col-reverse h-full w-auto bottom-auto right-0'
|
||||
: 'w-full bottom-0',
|
||||
]);
|
||||
|
||||
@@ -31,6 +33,17 @@ type ExtraCountersBarProps = {
|
||||
|
||||
const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
||||
const { updatePlayer } = usePlayers();
|
||||
const [iconColor, setIconColor] = useState<'dark' | 'light'>('dark');
|
||||
|
||||
useEffect(() => {
|
||||
const contrast = checkContrast(player.color, '#00000080');
|
||||
|
||||
if (contrast === 'Fail') {
|
||||
setIconColor('light');
|
||||
} else {
|
||||
setIconColor('dark');
|
||||
}
|
||||
}, [player.color]);
|
||||
|
||||
const handleCounterChange = (
|
||||
updatedCounterTotal: number,
|
||||
@@ -93,13 +106,20 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
||||
{useCommanderDamage && (
|
||||
<ExtraCounter
|
||||
rotation={player.settings.rotation}
|
||||
Icon={<CommanderTax size={iconSize} opacity="0.5" color="black" />}
|
||||
Icon={
|
||||
<CommanderTax
|
||||
size={iconSize}
|
||||
data-contrast={iconColor}
|
||||
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
|
||||
/>
|
||||
}
|
||||
type={CounterType.CommanderTax}
|
||||
counterTotal={
|
||||
player.extraCounters?.find(
|
||||
(counter) => counter.type === 'commanderTax'
|
||||
)?.value
|
||||
}
|
||||
isSide={player.isSide}
|
||||
setCounterTotal={handleCounterChange}
|
||||
playerIndex={player.index}
|
||||
/>
|
||||
@@ -107,13 +127,20 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
||||
{Boolean(useCommanderDamage && usePartner) && (
|
||||
<ExtraCounter
|
||||
rotation={player.settings.rotation}
|
||||
Icon={<PartnerTax size={iconSize} opacity="0.5" color="black" />}
|
||||
Icon={
|
||||
<PartnerTax
|
||||
size={iconSize}
|
||||
data-contrast={iconColor}
|
||||
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
|
||||
/>
|
||||
}
|
||||
type={CounterType.PartnerTax}
|
||||
counterTotal={
|
||||
player.extraCounters?.find(
|
||||
(counter) => counter.type === 'partnerTax'
|
||||
)?.value
|
||||
}
|
||||
isSide={player.isSide}
|
||||
setCounterTotal={handleCounterChange}
|
||||
playerIndex={player.index}
|
||||
/>
|
||||
@@ -121,12 +148,19 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
||||
{usePoison && (
|
||||
<ExtraCounter
|
||||
rotation={player.settings.rotation}
|
||||
Icon={<Poison size={iconSize} opacity="0.5" color="black" />}
|
||||
Icon={
|
||||
<Poison
|
||||
size={iconSize}
|
||||
data-contrast={iconColor}
|
||||
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
|
||||
/>
|
||||
}
|
||||
type={CounterType.Poison}
|
||||
counterTotal={
|
||||
player.extraCounters?.find((counter) => counter.type === 'poison')
|
||||
?.value
|
||||
}
|
||||
isSide={player.isSide}
|
||||
setCounterTotal={handleCounterChange}
|
||||
playerIndex={player.index}
|
||||
/>
|
||||
@@ -134,12 +168,19 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
||||
{useEnergy && (
|
||||
<ExtraCounter
|
||||
rotation={player.settings.rotation}
|
||||
Icon={<Energy size={iconSize} opacity="0.5" color="black" />}
|
||||
Icon={
|
||||
<Energy
|
||||
size={iconSize}
|
||||
data-contrast={iconColor}
|
||||
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
|
||||
/>
|
||||
}
|
||||
type={CounterType.Energy}
|
||||
counterTotal={
|
||||
player.extraCounters?.find((counter) => counter.type === 'energy')
|
||||
?.value
|
||||
}
|
||||
isSide={player.isSide}
|
||||
setCounterTotal={handleCounterChange}
|
||||
playerIndex={player.index}
|
||||
/>
|
||||
@@ -147,13 +188,20 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
||||
{useExperience && (
|
||||
<ExtraCounter
|
||||
rotation={player.settings.rotation}
|
||||
Icon={<Experience size={iconSize} opacity="0.5" color="black" />}
|
||||
Icon={
|
||||
<Experience
|
||||
size={iconSize}
|
||||
data-contrast={iconColor}
|
||||
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
|
||||
/>
|
||||
}
|
||||
type={CounterType.Experience}
|
||||
counterTotal={
|
||||
player.extraCounters?.find(
|
||||
(counter) => counter.type === 'experience'
|
||||
)?.value
|
||||
}
|
||||
isSide={player.isSide}
|
||||
setCounterTotal={handleCounterChange}
|
||||
playerIndex={player.index}
|
||||
/>
|
||||
|
||||
62
src/Components/Dialogs/Dialog.tsx
Normal file
62
src/Components/Dialogs/Dialog.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import { useEffect } from 'react';
|
||||
import { Cross } from '../../Icons/generated';
|
||||
import { useAnalytics } from '../../Hooks/useAnalytics';
|
||||
import { Separator } from '../Misc/Separator';
|
||||
|
||||
export const Dialog: React.FC<{
|
||||
id: string;
|
||||
title?: string;
|
||||
children: React.ReactNode;
|
||||
dialogRef: React.MutableRefObject<HTMLDialogElement | null>;
|
||||
}> = ({ id, title, children, dialogRef }) => {
|
||||
const analytics = useAnalytics();
|
||||
|
||||
useEffect(() => {
|
||||
if (!dialogRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
dialogRef.current.addEventListener('click', (e) => {
|
||||
const dialogDimensions = dialogRef.current!.getBoundingClientRect();
|
||||
if (
|
||||
(e.clientX < dialogDimensions.left ||
|
||||
e.clientX > dialogDimensions.right ||
|
||||
e.clientY < dialogDimensions.top ||
|
||||
e.clientY > dialogDimensions.bottom) &&
|
||||
dialogRef.current?.open
|
||||
) {
|
||||
analytics.trackEvent(`${id}_outside_clicked`);
|
||||
dialogRef.current?.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<dialog
|
||||
id={id}
|
||||
ref={dialogRef}
|
||||
className="backdrop:bg-background-backdrop border-none backdrop:backdrop-blur-[1px] open:visible invisible bg-transparent overflow-visible m-0 justify-self-center top-[10%]"
|
||||
>
|
||||
<button
|
||||
onClick={() => {
|
||||
analytics.trackEvent(`${id}_cross_clicked`);
|
||||
dialogRef.current?.close();
|
||||
}}
|
||||
className="flex absolute -top-2 right-2 z-10 w-10 h-10 bg-primary-main items-center justify-center rounded-full border-solid border-primary-dark border-2"
|
||||
>
|
||||
<Cross size="16px" className="text-text-primary" />
|
||||
</button>
|
||||
|
||||
<div className="h-[95%] bg-background-default rounded-2xl max-w-[548px] max-h-[80vh] flex flex-col">
|
||||
<div className="text-2xl text-center text-text-primary px-8 pt-4">
|
||||
<h2 className="">{title}</h2>
|
||||
<Separator height="1px" />
|
||||
</div>
|
||||
|
||||
<div className="h-full overflow-auto text-text-primary show-scrollbar px-8 pb-8">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
);
|
||||
};
|
||||
91
src/Components/Dialogs/InfoDialog.tsx
Normal file
91
src/Components/Dialogs/InfoDialog.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import { useAnalytics } from '../../Hooks/useAnalytics';
|
||||
import { BuyMeCoffee } from '../../Icons/generated/Support';
|
||||
import { Paragraph } from '../Misc/TextComponents';
|
||||
import { Dialog } from './Dialog';
|
||||
|
||||
export const InfoDialog = ({
|
||||
dialogRef,
|
||||
}: {
|
||||
dialogRef: React.MutableRefObject<HTMLDialogElement | null>;
|
||||
}) => {
|
||||
const analytics = useAnalytics();
|
||||
return (
|
||||
<Dialog id="info" title="📋 Usage Guide" dialogRef={dialogRef}>
|
||||
<div className="text-text-primary">
|
||||
<Paragraph className="my-4">
|
||||
There are some controls that you might not know about, so here's a
|
||||
short list of them.
|
||||
</Paragraph>
|
||||
<h3 className="text-lg font-bold mb-2">Life counter</h3>
|
||||
<ul className="list-disc ml-6 mb-4">
|
||||
<li>
|
||||
<strong>Tap</strong> on a player's + or - button to add or subtract{' '}
|
||||
<strong>1 life</strong>.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Long press</strong> on a player's + or - button to add or
|
||||
subtract <strong>10 life</strong>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-lg font-bold mb-2">
|
||||
Commander damage and other counters
|
||||
</h3>
|
||||
<ul className="list-disc ml-6 mb-4">
|
||||
<li>
|
||||
<strong>Tap</strong> on the counter to add{' '}
|
||||
<strong>1 counter</strong>.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Long press</strong> on the counter to subtract{' '}
|
||||
<strong>1 counter</strong>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="text-lg font-bold mb-2">Other functionality</h3>
|
||||
<ul className="list-disc ml-6">
|
||||
<li>
|
||||
<Paragraph className="mb-1">
|
||||
When a player is <strong>at or below 0 life</strong>, has taken{' '}
|
||||
<strong>21 or more Commander Damage</strong> or has{' '}
|
||||
<strong>10 or more poison counters</strong>, a button with a skull
|
||||
will appear on that player's card. Tapping it will dim the
|
||||
player's card.
|
||||
</Paragraph>
|
||||
</li>
|
||||
<li>
|
||||
<Paragraph className="mb-4">
|
||||
Swiping <strong>down</strong> on a player's card will show that
|
||||
player's settings menu.
|
||||
</Paragraph>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="text-center mt-4 text-text-primary">
|
||||
Visit my{' '}
|
||||
<a
|
||||
href="https://github.com/Vikeo/LifeTrinket"
|
||||
target="_blank"
|
||||
className="text-text-secondary underline"
|
||||
>
|
||||
GitHub
|
||||
</a>{' '}
|
||||
for more info about this web app.
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center mt-4">
|
||||
<a
|
||||
className="flex flex-row items-center self-center border-none cursor-pointer bg-primary-main rounded-md mx-4 pr-4 pl-3 py-2 transition-colors duration-200 ease-in-out shadow-[1px_2px_4px_0px_rgba(0,0,0,0.3)] hover:bg-primary-dark"
|
||||
onClick={() => {
|
||||
analytics.trackEvent('click_bmc');
|
||||
}}
|
||||
href="https://www.buymeacoffee.com/vikeo"
|
||||
target="_blank"
|
||||
>
|
||||
<BuyMeCoffee height="1.5rem" width="1.5rem" className="mr-2" />
|
||||
<Paragraph className="text-xs">Buy me a tea</Paragraph>
|
||||
</a>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
257
src/Components/Dialogs/SettingsDialog.tsx
Normal file
257
src/Components/Dialogs/SettingsDialog.tsx
Normal file
@@ -0,0 +1,257 @@
|
||||
import { twc } from 'react-twc';
|
||||
import { useAnalytics } from '../../Hooks/useAnalytics';
|
||||
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
|
||||
import { PreStartMode } from '../../Types/Settings';
|
||||
import { Separator } from '../Misc/Separator';
|
||||
import { Paragraph } from '../Misc/TextComponents';
|
||||
import { ToggleButton } from '../Misc/ToggleButton';
|
||||
import { Dialog } from './Dialog';
|
||||
|
||||
const SettingContainer = twc.div`w-full flex flex-col mb-2`;
|
||||
|
||||
const ToggleContainer = twc.div`flex flex-row justify-between items-center -mb-1`;
|
||||
|
||||
const Description = twc.p`mr-16 text-xs text-left text-text-secondary`;
|
||||
|
||||
const baseGithubReleasesUrl =
|
||||
'https://github.com/Vikeo/LifeTrinket/releases/tag/';
|
||||
|
||||
export const SettingsDialog = ({
|
||||
dialogRef,
|
||||
}: {
|
||||
dialogRef: React.MutableRefObject<HTMLDialogElement | null>;
|
||||
}) => {
|
||||
const { settings, setSettings, isPWA, version } = useGlobalSettings();
|
||||
const analytics = useAnalytics();
|
||||
|
||||
return (
|
||||
<Dialog id="settings" title="⚙️ Settings ⚙️" dialogRef={dialogRef}>
|
||||
<div className="flex flex-col mb-2 w-full">
|
||||
<div className="text-text-primary flex items-center gap-2">
|
||||
Current version: {version.installedVersion}{' '}
|
||||
{version.isLatest && (
|
||||
<span className="text-sm text-text-secondary">(latest)</span>
|
||||
)}
|
||||
<div className="text-xs text-text-primary opacity-75">
|
||||
(
|
||||
<a
|
||||
href={baseGithubReleasesUrl + version.installedVersion}
|
||||
target="_blank"
|
||||
className="underline"
|
||||
onClick={() => {
|
||||
analytics.trackEvent(
|
||||
`current_change_log_clicked_v${version.installedVersion}`
|
||||
);
|
||||
}}
|
||||
>
|
||||
Release notes
|
||||
</a>
|
||||
)
|
||||
</div>
|
||||
</div>
|
||||
{!version.isLatest && version.remoteVersion && (
|
||||
<>
|
||||
<div className="flex gap-2 items-center mt-2">
|
||||
<Paragraph className="text-text-secondary">
|
||||
{version.remoteVersion} available!
|
||||
</Paragraph>
|
||||
<div className="text-xs text-text-primary opacity-75">
|
||||
(
|
||||
<a
|
||||
href={baseGithubReleasesUrl + version.remoteVersion}
|
||||
target="_blank"
|
||||
className="underline"
|
||||
onClick={() => {
|
||||
analytics.trackEvent(
|
||||
`new_change_log_clicked_v${version.remoteVersion}`
|
||||
);
|
||||
}}
|
||||
>
|
||||
Release notes
|
||||
</a>
|
||||
)
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="flex justify-center items-center self-start mt-2 bg-primary-main px-3 py-1 rounded-md"
|
||||
onClick={() => {
|
||||
{
|
||||
analytics.trackEvent(`pressed_update`, {
|
||||
toVersion: version.remoteVersion,
|
||||
fromVersion: version.installedVersion,
|
||||
});
|
||||
window?.location?.reload();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span className="text-sm">Update</span>
|
||||
<span className="text-xs"> (reload app)</span>
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<Separator height="1px" />
|
||||
|
||||
<SettingContainer>
|
||||
<ToggleContainer>
|
||||
<label>Show Player Menu Cog</label>
|
||||
<ToggleButton
|
||||
checked={settings.showPlayerMenuCog}
|
||||
onChange={() => {
|
||||
setSettings({
|
||||
...settings,
|
||||
showPlayerMenuCog: !settings.showPlayerMenuCog,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</ToggleContainer>
|
||||
<Description>
|
||||
A cog on the top right of each player's card will be shown if this is
|
||||
enabled.
|
||||
</Description>
|
||||
</SettingContainer>
|
||||
<SettingContainer>
|
||||
<ToggleContainer>
|
||||
<label>Show Start Player</label>
|
||||
<ToggleButton
|
||||
checked={settings.showStartingPlayer}
|
||||
onChange={() => {
|
||||
setSettings({
|
||||
...settings,
|
||||
showStartingPlayer: !settings.showStartingPlayer,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</ToggleContainer>
|
||||
<Description>
|
||||
On start or reset of game, will pick a random starting player,
|
||||
according to the <b>Pre-Start mode</b>
|
||||
</Description>
|
||||
</SettingContainer>
|
||||
<SettingContainer>
|
||||
<div className="flex flex-row justify-between items-center mb-1">
|
||||
<label htmlFor="pre-start-modes">Player selection style</label>
|
||||
<select
|
||||
name="pre-start-modes"
|
||||
id="pre-start-modes"
|
||||
value={settings.preStartMode}
|
||||
className="bg-primary-main border-none outline-none text-text-primary rounded-md p-1 text-xs disabled:bg-primary-dark"
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
...settings,
|
||||
preStartMode: e.target.value as PreStartMode,
|
||||
});
|
||||
}}
|
||||
disabled={!settings.showStartingPlayer}
|
||||
>
|
||||
<option value={PreStartMode.None}>Instant</option>
|
||||
<option value={PreStartMode.RandomKing}>Royal Shuffle</option>
|
||||
<option value={PreStartMode.FingerGame}>Touch Roulette</option>
|
||||
<option value={PreStartMode.Trivia}>Group Trivia</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="text-xs text-left text-text-secondary">
|
||||
Different ways to determine the starting player before the game
|
||||
starts.
|
||||
</div>
|
||||
|
||||
{settings.preStartMode === PreStartMode.None && (
|
||||
<div className="text-xs text-left text-text-secondary mt-1">
|
||||
<span className="text-text-primary">Instant:</span> A random
|
||||
starting player will simply be shown on start.
|
||||
</div>
|
||||
)}
|
||||
{settings.preStartMode === PreStartMode.RandomKing && (
|
||||
<div className="text-xs text-left text-text-secondary mt-1">
|
||||
<span className="text-text-primary">Royal Shuffle:</span> Randomly
|
||||
pass a crown between all players, press the screen to stop it. The
|
||||
player who has the crown when it stops gets to start.
|
||||
</div>
|
||||
)}
|
||||
{settings.preStartMode === PreStartMode.FingerGame && (
|
||||
<div className="text-xs text-left text-text-secondary mt-1">
|
||||
<span className="text-text-primary">Touch Roulette:</span> All
|
||||
players put a finger on the screen, one will be chosen at random.
|
||||
</div>
|
||||
)}
|
||||
|
||||
{settings.preStartMode === PreStartMode.Trivia && (
|
||||
<div className="text-xs text-left text-text-secondary mt-1">
|
||||
<span className="text-text-primary">Group Trivia:</span> A random
|
||||
"who is the most ..." type question will be shown, the group decides
|
||||
which player fits the question best.
|
||||
</div>
|
||||
)}
|
||||
</SettingContainer>
|
||||
<SettingContainer>
|
||||
<ToggleContainer>
|
||||
<label>Keep Awake</label>
|
||||
<ToggleButton
|
||||
checked={settings.keepAwake}
|
||||
onChange={() => {
|
||||
setSettings({
|
||||
...settings,
|
||||
keepAwake: !settings.keepAwake,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</ToggleContainer>
|
||||
<Description>
|
||||
Will prevent device from going to sleep while this app is open if this
|
||||
is enabled.
|
||||
</Description>
|
||||
</SettingContainer>
|
||||
<SettingContainer>
|
||||
<ToggleContainer>
|
||||
<label>
|
||||
Fullscreen on start <span className="text-xs">(Android only)</span>
|
||||
</label>
|
||||
<ToggleButton
|
||||
checked={settings.goFullscreenOnStart}
|
||||
onChange={() => {
|
||||
setSettings({
|
||||
...settings,
|
||||
goFullscreenOnStart: !settings.goFullscreenOnStart,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</ToggleContainer>
|
||||
<Description>
|
||||
Will enter fullscreen mode when starting a game if this is enabled.
|
||||
</Description>
|
||||
</SettingContainer>
|
||||
<Separator height="1px" />
|
||||
<div className="flex w-full justify-center">
|
||||
<button
|
||||
className="mt-1 mb-1 bg-primary-main px-3 py-1 rounded-md duration-200 ease-in-out shadow-[1px_2px_4px_0px_rgba(0,0,0,0.3)] hover:bg-primary-dark"
|
||||
onClick={() => {
|
||||
analytics.trackEvent('settings_save_clicked');
|
||||
dialogRef.current?.close();
|
||||
}}
|
||||
>
|
||||
<span className="text-sm">Save and Close</span>
|
||||
</button>
|
||||
</div>
|
||||
{!isPWA && (
|
||||
<>
|
||||
<Separator height="1px" />
|
||||
<SettingContainer>
|
||||
<ToggleContainer>
|
||||
<Paragraph>
|
||||
<b>Tip:</b> You can{' '}
|
||||
<b>add this webapp to your home page on iOS</b> or{' '}
|
||||
<b>install it on Android</b> to have it act just like a normal
|
||||
app!
|
||||
</Paragraph>
|
||||
</ToggleContainer>
|
||||
<Description className="mt-1">
|
||||
If you do, this app will work offline and the toolbar will be
|
||||
automatically hidden.
|
||||
</Description>
|
||||
</SettingContainer>
|
||||
</>
|
||||
)}
|
||||
<Separator height="1px" />
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import LifeCounterButton from '../Buttons/LifeCounterButton';
|
||||
import { OutlinedText } from '../Misc/OutlinedText';
|
||||
|
||||
const LifeCountainer = twc.div<RotationDivProps>((props) => [
|
||||
const LifeContainer = twc.div<RotationDivProps>((props) => [
|
||||
'flex flex-grow relative w-full h-full justify-between items-center',
|
||||
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||
? 'flex-col-reverse'
|
||||
@@ -49,28 +49,13 @@ type HealthProps = {
|
||||
|
||||
const Health = ({
|
||||
player,
|
||||
rotation,
|
||||
handleLifeChange,
|
||||
differenceKey,
|
||||
recentDifference,
|
||||
}: HealthProps) => {
|
||||
const [showStartingPlayer, setShowStartingPlayer] = useState(
|
||||
localStorage.getItem('playing') === 'true'
|
||||
);
|
||||
const [fontSize, setFontSize] = useState(16);
|
||||
const textContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!showStartingPlayer) {
|
||||
const playingTimer = setTimeout(() => {
|
||||
localStorage.setItem('playing', 'true');
|
||||
setShowStartingPlayer(localStorage.getItem('playing') === 'true');
|
||||
}, 3_000);
|
||||
|
||||
return () => clearTimeout(playingTimer);
|
||||
}
|
||||
}, [showStartingPlayer]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!textContainerRef.current) {
|
||||
return;
|
||||
@@ -99,12 +84,13 @@ const Health = ({
|
||||
}, [textContainerRef]);
|
||||
|
||||
const calculateFontSize = (container: HTMLDivElement) => {
|
||||
const isSide =
|
||||
rotation === Rotation.SideFlipped || rotation === Rotation.Side;
|
||||
const widthRatio = player.isSide
|
||||
? container.clientHeight
|
||||
: container.clientWidth;
|
||||
|
||||
const widthRatio = isSide ? container.clientHeight : container.clientWidth;
|
||||
|
||||
const heightRatio = isSide ? container.clientWidth : container.clientHeight;
|
||||
const heightRatio = player.isSide
|
||||
? container.clientWidth
|
||||
: container.clientHeight;
|
||||
|
||||
const minRatio = Math.min(widthRatio, heightRatio);
|
||||
|
||||
@@ -116,11 +102,10 @@ const Health = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<LifeCountainer $rotation={player.settings.rotation}>
|
||||
<LifeContainer $rotation={player.settings.rotation}>
|
||||
<LifeCounterButton
|
||||
lifeTotal={player.lifeTotal}
|
||||
player={player}
|
||||
setLifeTotal={handleLifeChange}
|
||||
rotation={player.settings.rotation}
|
||||
operation="subtract"
|
||||
increment={-1}
|
||||
/>
|
||||
@@ -148,13 +133,12 @@ const Health = ({
|
||||
</LifeCounterTextContainer>
|
||||
</TextWrapper>
|
||||
<LifeCounterButton
|
||||
lifeTotal={player.lifeTotal}
|
||||
player={player}
|
||||
setLifeTotal={handleLifeChange}
|
||||
rotation={player.settings.rotation}
|
||||
operation="add"
|
||||
increment={1}
|
||||
/>
|
||||
</LifeCountainer>
|
||||
</LifeContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,16 +1,64 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useSwipeable } from 'react-swipeable';
|
||||
import { twc } from 'react-twc';
|
||||
import { useAnalytics } from '../../Hooks/useAnalytics';
|
||||
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
|
||||
import { usePlayers } from '../../Hooks/usePlayers';
|
||||
import { Cog } from '../../Icons/generated';
|
||||
import { Player, Rotation } from '../../Types/Player';
|
||||
import { RotationDivProps } from '../Buttons/CommanderDamage';
|
||||
import { checkContrast } from '../../Utils/checkContrast';
|
||||
import {
|
||||
RotationButtonProps,
|
||||
RotationDivProps,
|
||||
} from '../Buttons/CommanderDamage';
|
||||
import { LoseGameButton } from '../Buttons/LoseButton';
|
||||
import SettingsButton from '../Buttons/SettingsButton';
|
||||
import CommanderDamageBar from '../Counters/CommanderDamageBar';
|
||||
import ExtraCountersBar from '../Counters/ExtraCountersBar';
|
||||
import PlayerMenu from '../Player/PlayerMenu';
|
||||
import PlayerMenu from '../Players/PlayerMenu';
|
||||
import { StartingPlayerCard } from '../PreStartGame/StartingPlayerCard';
|
||||
import Health from './Health';
|
||||
|
||||
const SettingsButtonTwc = twc.button<RotationButtonProps>((props) => [
|
||||
'absolute flex-grow border-none outline-none cursor-pointer bg-transparent z-[1] select-none webkit-user-select-none',
|
||||
props.$rotation === Rotation.Side || props.$rotation === Rotation.SideFlipped
|
||||
? `right-auto top-[1vmax] left-[27%]`
|
||||
: 'top-1/4 right-[1vmax]',
|
||||
]);
|
||||
|
||||
type SettingsButtonProps = {
|
||||
onClick: () => void;
|
||||
rotation: Rotation;
|
||||
color: string;
|
||||
};
|
||||
|
||||
const SettingsButton = ({ onClick, rotation, color }: SettingsButtonProps) => {
|
||||
const [iconColor, setIconColor] = useState<'dark' | 'light'>('dark');
|
||||
|
||||
useEffect(() => {
|
||||
const contrast = checkContrast(color, '#00000080');
|
||||
|
||||
if (contrast === 'Fail') {
|
||||
setIconColor('light');
|
||||
} else {
|
||||
setIconColor('dark');
|
||||
}
|
||||
}, [color]);
|
||||
|
||||
return (
|
||||
<SettingsButtonTwc
|
||||
onClick={onClick}
|
||||
$rotation={rotation}
|
||||
aria-label={`Settings`}
|
||||
>
|
||||
<Cog
|
||||
size="5vmin"
|
||||
data-contrast={iconColor}
|
||||
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
|
||||
/>
|
||||
</SettingsButtonTwc>
|
||||
);
|
||||
};
|
||||
|
||||
const LifeCounterContentWrapper = twc.div`
|
||||
relative flex flex-grow flex-col items-center w-full h-full overflow-hidden`;
|
||||
|
||||
@@ -21,17 +69,13 @@ const LifeCounterWrapper = twc.div<RotationDivProps>((props) => [
|
||||
: `flex-col`,
|
||||
]);
|
||||
|
||||
const StartingPlayerNoticeWrapper = twc.div`z-[1] flex absolute w-full h-full justify-center items-center pointer-events-none select-none webkit-user-select-none bg-primary-main`;
|
||||
|
||||
const PlayerLostWrapper = twc.div<RotationDivProps>((props) => [
|
||||
'z-[1] flex absolute w-full h-full justify-center items-center pointer-events-none select-none webkit-user-select-none bg-lifeCounter-lostWrapper',
|
||||
'z-[1] flex absolute w-full h-full justify-center items-center pointer-events-none select-none webkit-user-select-none bg-lifeCounter-lostWrapper opacity-75',
|
||||
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||
? `rotate-[${props.$rotation - 90}deg]`
|
||||
: '',
|
||||
]);
|
||||
|
||||
const DynamicText = twc.div`text-[8vmin]`;
|
||||
|
||||
const hasCommanderDamageReached21 = (player: Player) => {
|
||||
const commanderDamageTotals = player.commanderDamage.map(
|
||||
(commanderDamage) => commanderDamage.damageTotal
|
||||
@@ -62,36 +106,81 @@ const playerCanLose = (player: Player) => {
|
||||
type LifeCounterProps = {
|
||||
player: Player;
|
||||
opponents: Player[];
|
||||
isStartingPlayer?: boolean;
|
||||
};
|
||||
|
||||
const RECENT_DIFFERENCE_TTL = 3_000;
|
||||
|
||||
const LifeCounter = ({ player, opponents }: LifeCounterProps) => {
|
||||
const { updatePlayer, updateLifeTotal } = usePlayers();
|
||||
const { settings } = useGlobalSettings();
|
||||
const { settings, playing } = useGlobalSettings();
|
||||
const recentDifferenceTimerRef = useRef<NodeJS.Timeout | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
const [showPlayerMenu, setShowPlayerMenu] = useState(false);
|
||||
const [recentDifference, setRecentDifference] = useState(0);
|
||||
const [differenceKey, setDifferenceKey] = useState(Date.now());
|
||||
const [isLandscape, setIsLandscape] = useState(false);
|
||||
|
||||
const calcRot = player.isSide
|
||||
? player.settings.rotation - 180
|
||||
: player.settings.rotation;
|
||||
|
||||
const rotationAngle = isLandscape ? calcRot : calcRot + 90;
|
||||
|
||||
const handlers = useSwipeable({
|
||||
trackMouse: true,
|
||||
onSwipedDown: (e) => {
|
||||
e.event.stopPropagation();
|
||||
analytics.trackEvent('open_player_menu_swipe');
|
||||
setShowPlayerMenu(true);
|
||||
},
|
||||
onSwipedUp: (e) => {
|
||||
e.event.stopPropagation();
|
||||
analytics.trackEvent('close_player_menu_swipe');
|
||||
setShowPlayerMenu(false);
|
||||
},
|
||||
|
||||
swipeDuration: 500,
|
||||
onSwiping: (e) => e.event.stopPropagation(),
|
||||
rotationAngle,
|
||||
});
|
||||
const analytics = useAnalytics();
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setRecentDifference(0);
|
||||
}, 3_000);
|
||||
if (recentDifference === 0) {
|
||||
clearTimeout(recentDifferenceTimerRef.current);
|
||||
return;
|
||||
}
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
recentDifferenceTimerRef.current = setTimeout(() => {
|
||||
analytics.trackEvent('life_changed', {
|
||||
lifeChangedAmount: recentDifference,
|
||||
});
|
||||
setRecentDifference(0);
|
||||
}, RECENT_DIFFERENCE_TTL);
|
||||
|
||||
return () => {
|
||||
clearTimeout(recentDifferenceTimerRef.current);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [recentDifference]);
|
||||
|
||||
useEffect(() => {
|
||||
if (player.showStartingPlayer) {
|
||||
const playingTimer = setTimeout(() => {
|
||||
localStorage.setItem('playing', 'true');
|
||||
player.showStartingPlayer = false;
|
||||
updatePlayer(player);
|
||||
}, 3_000);
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
if (document.body.clientWidth > document.body.clientHeight)
|
||||
setIsLandscape(true);
|
||||
else setIsLandscape(false);
|
||||
return () => {
|
||||
// Cleanup: disconnect the ResizeObserver when the component unmounts.
|
||||
resizeObserver.disconnect();
|
||||
};
|
||||
});
|
||||
|
||||
return () => clearTimeout(playingTimer);
|
||||
}
|
||||
resizeObserver.observe(document.body);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [player.showStartingPlayer]);
|
||||
}, [document.body.clientHeight, document.body.clientWidth]);
|
||||
|
||||
player.settings.rotation === Rotation.SideFlipped ||
|
||||
player.settings.rotation === Rotation.Side;
|
||||
@@ -113,45 +202,40 @@ const LifeCounter = ({ player, opponents }: LifeCounterProps) => {
|
||||
? player.settings.rotation - 90
|
||||
: player.settings.rotation;
|
||||
|
||||
const calcTextRotation =
|
||||
player.settings.rotation === Rotation.SideFlipped ||
|
||||
player.settings.rotation === Rotation.Side
|
||||
? player.settings.rotation - 180
|
||||
: player.settings.rotation;
|
||||
const amountOfPlayers = opponents.length + 1;
|
||||
|
||||
return (
|
||||
<LifeCounterContentWrapper style={{ background: player.color }}>
|
||||
<LifeCounterWrapper
|
||||
$rotation={player.settings.rotation}
|
||||
style={{ rotate: `${calcRotation}deg` }}
|
||||
{...handlers}
|
||||
>
|
||||
{settings.showStartingPlayer &&
|
||||
player.isStartingPlayer &&
|
||||
player.showStartingPlayer && (
|
||||
<StartingPlayerNoticeWrapper
|
||||
style={{ rotate: `${calcRotation}deg` }}
|
||||
>
|
||||
<DynamicText style={{ rotate: `${calcTextRotation}deg` }}>
|
||||
You start!
|
||||
</DynamicText>
|
||||
</StartingPlayerNoticeWrapper>
|
||||
)}
|
||||
{amountOfPlayers > 1 &&
|
||||
!playing &&
|
||||
settings.showStartingPlayer &&
|
||||
player.isStartingPlayer && <StartingPlayerCard player={player} />}
|
||||
|
||||
{player.hasLost && (
|
||||
<PlayerLostWrapper $rotation={player.settings.rotation} />
|
||||
)}
|
||||
|
||||
<CommanderDamageBar
|
||||
opponents={opponents}
|
||||
player={player}
|
||||
key={player.index}
|
||||
handleLifeChange={handleLifeChange}
|
||||
/>
|
||||
<SettingsButton
|
||||
onClick={() => {
|
||||
setShowPlayerMenu(!showPlayerMenu);
|
||||
}}
|
||||
rotation={player.settings.rotation}
|
||||
/>
|
||||
{settings.showPlayerMenuCog && (
|
||||
<SettingsButton
|
||||
onClick={() => {
|
||||
analytics.trackEvent('open_player_menu_button');
|
||||
setShowPlayerMenu(!showPlayerMenu);
|
||||
}}
|
||||
rotation={player.settings.rotation}
|
||||
color={player.color}
|
||||
/>
|
||||
)}
|
||||
{playerCanLose(player) && (
|
||||
<LoseGameButton
|
||||
rotation={player.settings.rotation}
|
||||
@@ -166,9 +250,12 @@ const LifeCounter = ({ player, opponents }: LifeCounterProps) => {
|
||||
handleLifeChange={handleLifeChange}
|
||||
/>
|
||||
<ExtraCountersBar player={player} />
|
||||
{showPlayerMenu && (
|
||||
<PlayerMenu player={player} setShowPlayerMenu={setShowPlayerMenu} />
|
||||
)}
|
||||
|
||||
<PlayerMenu
|
||||
isShown={showPlayerMenu}
|
||||
player={player}
|
||||
setShowPlayerMenu={setShowPlayerMenu}
|
||||
/>
|
||||
</LifeCounterWrapper>
|
||||
</LifeCounterContentWrapper>
|
||||
);
|
||||
|
||||
31
src/Components/Misc/IconCheckbox.tsx
Normal file
31
src/Components/Misc/IconCheckbox.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
export const IconCheckbox = ({
|
||||
name,
|
||||
icon,
|
||||
checkedIcon,
|
||||
checked,
|
||||
onChange,
|
||||
className,
|
||||
}: {
|
||||
name: string;
|
||||
icon: JSX.Element;
|
||||
checkedIcon: JSX.Element;
|
||||
checked: boolean;
|
||||
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
className?: string;
|
||||
}) => {
|
||||
return (
|
||||
<div className={className}>
|
||||
<label>
|
||||
<input
|
||||
name={name}
|
||||
type="checkbox"
|
||||
checked={checked}
|
||||
onChange={onChange}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="peer-checked:hidden block">{icon}</div>
|
||||
<div className="peer-checked:block hidden">{checkedIcon}</div>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,83 +0,0 @@
|
||||
import { Modal } from '@mui/material';
|
||||
import { theme } from '../../Data/theme';
|
||||
import { twc } from 'react-twc';
|
||||
|
||||
export const ModalWrapper = twc.div`absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[80vw] h-[85vh] bg-background-default p-4 overflow-scroll rounded-2xl border-none text-text-primary`;
|
||||
|
||||
type InfoModalProps = {
|
||||
isOpen: boolean;
|
||||
closeModal: () => void;
|
||||
};
|
||||
|
||||
export const InfoModal = ({ isOpen, closeModal }: InfoModalProps) => {
|
||||
return (
|
||||
<Modal open={isOpen} onClose={closeModal}>
|
||||
<ModalWrapper>
|
||||
<div>
|
||||
<h2 style={{ textAlign: 'center' }}>📋 Usage Guide</h2>
|
||||
<p>
|
||||
There are some controls that you might not know about, so here's a
|
||||
short list of them.
|
||||
</p>
|
||||
|
||||
<h3>Life counter</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Tap</strong> on a player's + or - button to add or
|
||||
subtract <strong>1 life</strong>.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Long press</strong> on a player's + or - button to add or
|
||||
subtract <strong>10 life</strong>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Commander damage and other counters</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Tap</strong> on the counter to add{' '}
|
||||
<strong>1 counter</strong>.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Long press</strong> on the counter to subtract{' '}
|
||||
<strong>1 counter</strong>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Other</h3>
|
||||
<p>
|
||||
When a player is <strong>at or below 0 life</strong>, has taken{' '}
|
||||
<strong>21 or more Commander Damage</strong> or has{' '}
|
||||
<strong>10 or more poison counters</strong>, a button with a skull
|
||||
will appear on that player's card.
|
||||
</p>
|
||||
<p>
|
||||
Tap on the button to mark that player as lost, dimming their player
|
||||
card.
|
||||
</p>
|
||||
</div>
|
||||
<br />
|
||||
<div
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
marginTop: '1rem',
|
||||
}}
|
||||
>
|
||||
Visit my
|
||||
<a
|
||||
href="https://github.com/Vikeo/LifeTrinket"
|
||||
target="_blank"
|
||||
style={{
|
||||
textDecoration: 'none',
|
||||
color: theme.palette.primary.light,
|
||||
}}
|
||||
>
|
||||
{' '}
|
||||
GitHub{' '}
|
||||
</a>
|
||||
for more info about this web app.
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
@@ -7,7 +7,7 @@ export const Separator = ({
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={`bg-common-black bg-opacity-30 rounded-full mt-2 mb-2`}
|
||||
className={`bg-common-white bg-opacity-30 rounded-full mt-2 mb-2`}
|
||||
style={{ width, height }}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
import { Button, FormLabel, Modal, Switch } from '@mui/material';
|
||||
import { twc } from 'react-twc';
|
||||
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
|
||||
import { ModalWrapper } from './InfoModal';
|
||||
import { Separator } from './Separator';
|
||||
import { Paragraph } from './TextComponents';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
const SettingContainer = twc.div`w-full flex flex-col`;
|
||||
|
||||
const ToggleContainer = twc.div`flex flex-row justify-between items-center`;
|
||||
|
||||
const Container = twc.div`flex flex-col items-center w-full`;
|
||||
|
||||
const Description = twc.p`mr-16 text-xs text-left text-text-secondary`;
|
||||
|
||||
type SettingsModalProps = {
|
||||
isOpen: boolean;
|
||||
closeModal: () => void;
|
||||
};
|
||||
|
||||
export const SettingsModal = ({ isOpen, closeModal }: SettingsModalProps) => {
|
||||
const { settings, setSettings, isPWA } = useGlobalSettings();
|
||||
const [isLatestVersion, setIsLatestVersion] = useState(false);
|
||||
const newVersion = useRef<string | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
return;
|
||||
}
|
||||
async function checkIfLatestVersion() {
|
||||
try {
|
||||
const result = await fetch(
|
||||
'https://api.github.com/repos/Vikeo/LifeTrinket/releases/latest',
|
||||
{
|
||||
headers: {
|
||||
/* @ts-expect-error is defined in vite.config.ts*/
|
||||
Authorization: `Bearer ${REPO_READ_ACCESS_TOKEN}`,
|
||||
Accept: 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version': '2022-11-28',
|
||||
},
|
||||
}
|
||||
);
|
||||
const data = await result.json();
|
||||
|
||||
if (!data.name) {
|
||||
setIsLatestVersion(false);
|
||||
newVersion.current = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
/* @ts-expect-error is defined in vite.config.ts*/
|
||||
if (data.name === APP_VERSION) {
|
||||
newVersion.current = data.name;
|
||||
setIsLatestVersion(true);
|
||||
return;
|
||||
}
|
||||
setIsLatestVersion(false);
|
||||
} catch (error) {
|
||||
console.error('error getting latest version string', error);
|
||||
}
|
||||
}
|
||||
checkIfLatestVersion();
|
||||
}, [isOpen]);
|
||||
|
||||
return (
|
||||
<Modal open={isOpen} onClose={closeModal}>
|
||||
<ModalWrapper>
|
||||
<Container>
|
||||
<h2 style={{ textAlign: 'center' }}>⚙️ Settings ⚙️</h2>
|
||||
<SettingContainer>
|
||||
<ToggleContainer>
|
||||
<FormLabel>Show Start Player</FormLabel>
|
||||
<Switch
|
||||
checked={settings.showStartingPlayer}
|
||||
onChange={() => {
|
||||
setSettings({
|
||||
...settings,
|
||||
showStartingPlayer: !settings.showStartingPlayer,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</ToggleContainer>
|
||||
<Description>
|
||||
On start or reset of game, will pick a random player who will
|
||||
start first if this is enabled.
|
||||
</Description>
|
||||
</SettingContainer>
|
||||
<SettingContainer>
|
||||
<ToggleContainer>
|
||||
<FormLabel>Keep Awake</FormLabel>
|
||||
<Switch
|
||||
checked={settings.keepAwake}
|
||||
onChange={() => {
|
||||
setSettings({ ...settings, keepAwake: !settings.keepAwake });
|
||||
}}
|
||||
/>
|
||||
</ToggleContainer>
|
||||
<Description>
|
||||
Will prevent device from going to sleep while this app is open if
|
||||
this is enabled.
|
||||
</Description>
|
||||
</SettingContainer>
|
||||
<SettingContainer>
|
||||
<ToggleContainer>
|
||||
<FormLabel>Go fullscreen on start (Android only)</FormLabel>
|
||||
<Switch
|
||||
checked={settings.goFullscreenOnStart}
|
||||
onChange={() => {
|
||||
setSettings({
|
||||
...settings,
|
||||
goFullscreenOnStart: !settings.goFullscreenOnStart,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</ToggleContainer>
|
||||
<Description>
|
||||
Will enter fullscreen mode when starting a game if this is
|
||||
enabled.
|
||||
</Description>
|
||||
</SettingContainer>
|
||||
{!isPWA && (
|
||||
<>
|
||||
<Separator height="1px" />
|
||||
<SettingContainer>
|
||||
<ToggleContainer>
|
||||
<Paragraph>
|
||||
<b>Tip:</b> You can{' '}
|
||||
<b>add this webapp to your home page on iOS</b> or{' '}
|
||||
<b>install it on Android</b> to have it act just like a
|
||||
normal app!
|
||||
</Paragraph>
|
||||
</ToggleContainer>
|
||||
<Description className="mt-1">
|
||||
If you do, this app will work offline and the toolbar will be
|
||||
automatically hidden.
|
||||
</Description>
|
||||
</SettingContainer>
|
||||
</>
|
||||
)}
|
||||
<Separator height="1px" />
|
||||
<SettingContainer>
|
||||
<Paragraph>
|
||||
{/* @ts-expect-error is defined in vite.config.ts*/}
|
||||
Current version: {APP_VERSION}{' '}
|
||||
{isLatestVersion && (
|
||||
<span className="text-sm text-text-secondary">(latest)</span>
|
||||
)}
|
||||
</Paragraph>
|
||||
{!isLatestVersion && newVersion.current && (
|
||||
<Paragraph className="text-text-secondary text-lg text-center">
|
||||
New version ({newVersion.current}) is available!{' '}
|
||||
</Paragraph>
|
||||
)}
|
||||
</SettingContainer>
|
||||
{!isLatestVersion && newVersion.current && (
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ marginTop: '0.25rem', marginBottom: '0.25rem' }}
|
||||
onClick={() => window?.location?.reload()}
|
||||
>
|
||||
<span>Update</span>
|
||||
<span className="text-xs"> (reload app)</span>
|
||||
</Button>
|
||||
)}
|
||||
<Separator height="1px" />
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={closeModal}
|
||||
style={{ marginTop: '0.25rem' }}
|
||||
>
|
||||
Save and Close
|
||||
</Button>
|
||||
</Container>
|
||||
</ModalWrapper>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
@@ -1,99 +0,0 @@
|
||||
import { Button, Drawer } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import { BuyMeCoffee, KoFi } from '../../Icons/generated/Support';
|
||||
import { Paragraph } from './TextComponents';
|
||||
import LittleGuy from '../../Icons/generated/LittleGuy';
|
||||
import { useAnalytics } from '../../Hooks/useAnalytics';
|
||||
import { twc } from 'react-twc';
|
||||
|
||||
const SupportContainer = twc.div`flex flex-col items-center justify-center gap-4 mt-4 mb-4`;
|
||||
|
||||
const SupportButton = twc.button`
|
||||
flex
|
||||
flex-row
|
||||
items-center
|
||||
justify-left
|
||||
border-none
|
||||
cursor-pointer
|
||||
bg-primary-main
|
||||
rounded-md
|
||||
w-10/12
|
||||
mx-4
|
||||
px-4
|
||||
py-2
|
||||
transition-colors duration-200 ease-in-out
|
||||
shadow-[1px_2px_4px_0px_rgba(0,0,0,0.3)]
|
||||
hover:bg-primary-dark
|
||||
`;
|
||||
|
||||
export const SupportMe = () => {
|
||||
const analytics = useAnalytics();
|
||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||
|
||||
const handleOpenBuyMeCoffee = () => {
|
||||
analytics.trackEvent('click_bmc');
|
||||
window.open('https://www.buymeacoffee.com/vikeo');
|
||||
};
|
||||
|
||||
const handleOpenKoFi = () => {
|
||||
analytics.trackEvent('click_kofi');
|
||||
window.open('https://ko-fi.com/vikeo');
|
||||
};
|
||||
|
||||
const toggleDrawer =
|
||||
(open: boolean) => (event: React.KeyboardEvent | React.MouseEvent) => {
|
||||
analytics.trackEvent('toggle_support_drawer');
|
||||
|
||||
if (
|
||||
event.type === 'keydown' &&
|
||||
((event as React.KeyboardEvent).key === 'Tab' ||
|
||||
(event as React.KeyboardEvent).key === 'Shift')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsDrawerOpen(open);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
onClick={toggleDrawer(true)}
|
||||
size="small"
|
||||
variant="contained"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '1rem',
|
||||
right: '1rem',
|
||||
fontSize: '0.5rem',
|
||||
}}
|
||||
>
|
||||
Nourish <br /> this guy {'->'}
|
||||
</Button>
|
||||
|
||||
<LittleGuy
|
||||
height={'4rem'}
|
||||
width={'2.5rem'}
|
||||
className="pointer-events-none absolute top-10 right-0 text-text-primary"
|
||||
/>
|
||||
|
||||
<Drawer
|
||||
anchor={'right'}
|
||||
open={isDrawerOpen}
|
||||
onClose={toggleDrawer(false)}
|
||||
variant="temporary"
|
||||
>
|
||||
<SupportContainer>
|
||||
<SupportButton onClick={handleOpenBuyMeCoffee}>
|
||||
<BuyMeCoffee height="1.5rem" width="1.5rem" className="mr-2" />
|
||||
<Paragraph className="text-xs">Buy him a tea</Paragraph>
|
||||
</SupportButton>
|
||||
<SupportButton onClick={handleOpenKoFi}>
|
||||
<KoFi height="1.5rem" width="1.5rem" className="mr-2" />
|
||||
<Paragraph className="text-xs">Buy him a ko-fi</Paragraph>
|
||||
</SupportButton>
|
||||
</SupportContainer>
|
||||
</Drawer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
29
src/Components/Misc/ToggleButton.tsx
Normal file
29
src/Components/Misc/ToggleButton.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { LabelText } from '../Views/StartMenu/StartMenu';
|
||||
|
||||
export const ToggleButton = ({
|
||||
label,
|
||||
checked,
|
||||
onChange,
|
||||
}: {
|
||||
label?: string;
|
||||
checked: boolean;
|
||||
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
}) => {
|
||||
return (
|
||||
<div className="flex flex-col items-center">
|
||||
{label && <LabelText>{label}</LabelText>}
|
||||
|
||||
<label className="inline-flex items-center cursor-pointer relative h-6 w-10">
|
||||
<input
|
||||
type="checkbox"
|
||||
value=""
|
||||
checked={checked}
|
||||
onChange={onChange}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="relative mx-1 w-10 h-[0.875rem] bg-gray-900 rounded-full peer peer-checked:bg-primary-dark" />
|
||||
<div className="absolute peer-checked:translate-x-full rtl:peer-checked:-translate-x-full bg-secondary-main peer-checked:bg-primary-main rounded-full h-5 w-5 transition-all" />
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,402 +0,0 @@
|
||||
import { Button, Checkbox } from '@mui/material';
|
||||
import { useRef } from 'react';
|
||||
import { twc } from 'react-twc';
|
||||
import { theme } from '../../Data/theme';
|
||||
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
|
||||
import { usePlayers } from '../../Hooks/usePlayers';
|
||||
import { useSafeRotate } from '../../Hooks/useSafeRotate';
|
||||
import {
|
||||
Cross,
|
||||
Energy,
|
||||
Exit,
|
||||
Experience,
|
||||
FullscreenOff,
|
||||
FullscreenOn,
|
||||
PartnerTax,
|
||||
Poison,
|
||||
ResetGame,
|
||||
} from '../../Icons/generated';
|
||||
import { Player, Rotation } from '../../Types/Player';
|
||||
import {
|
||||
RotationButtonProps,
|
||||
RotationDivProps,
|
||||
} from '../Buttons/CommanderDamage';
|
||||
|
||||
const CheckboxContainer = twc.div``;
|
||||
|
||||
const PlayerMenuWrapper = twc.div`
|
||||
flex
|
||||
flex-col
|
||||
absolute
|
||||
w-full
|
||||
h-full
|
||||
bg-background-settings
|
||||
items-center
|
||||
justify-center
|
||||
z-[2]
|
||||
webkit-user-select-none
|
||||
`;
|
||||
|
||||
const BetterRowContainer = twc.div`
|
||||
flex
|
||||
flex-col
|
||||
flex-grow
|
||||
w-full
|
||||
h-full
|
||||
justify-end
|
||||
items-stretch
|
||||
`;
|
||||
|
||||
const TogglesSection = twc.div`
|
||||
flex
|
||||
relative
|
||||
flex-row
|
||||
gap-2
|
||||
justify-evenly
|
||||
`;
|
||||
|
||||
const ButtonsSections = twc.div`
|
||||
flex
|
||||
max-w-full
|
||||
gap-4
|
||||
justify-between
|
||||
p-[3%]
|
||||
items-center
|
||||
`;
|
||||
|
||||
const ColorPicker = twc.input`
|
||||
absolute
|
||||
top-[5%]
|
||||
left-[5%]
|
||||
h-[8vmax]
|
||||
w-[8vmax]
|
||||
border-none
|
||||
outline-none
|
||||
cursor-pointer
|
||||
bg-transparent
|
||||
user-select-none
|
||||
text-common-white
|
||||
`;
|
||||
|
||||
const SettingsContainer = twc.div<RotationDivProps>((props) => [
|
||||
'flex flex-wrap h-full w-full',
|
||||
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||
? 'flex-col'
|
||||
: 'flex-row',
|
||||
]);
|
||||
|
||||
const CloseButton = twc.button<RotationButtonProps>((props) => [
|
||||
'absolute border-none outline-none cursor-pointer bg-transparent z-[99]',
|
||||
props.$rotation === Rotation.Side
|
||||
? `top-[5%] right-auto left-[5%]`
|
||||
: props.$rotation === Rotation.SideFlipped
|
||||
? 'top-auto left-auto bottom-[5%] right-[5%]'
|
||||
: 'top-[15%] right-[5%]',
|
||||
]);
|
||||
|
||||
type PlayerMenuProps = {
|
||||
player: Player;
|
||||
setShowPlayerMenu: (showPlayerMenu: boolean) => void;
|
||||
};
|
||||
|
||||
const PlayerMenu = ({ player, setShowPlayerMenu }: PlayerMenuProps) => {
|
||||
const settingsContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const dialogRef = useRef<HTMLDialogElement | null>(null);
|
||||
|
||||
const { isSide } = useSafeRotate({
|
||||
rotation: player.settings.rotation,
|
||||
containerRef: settingsContainerRef,
|
||||
});
|
||||
|
||||
const handleOnClick = () => {
|
||||
setShowPlayerMenu(false);
|
||||
};
|
||||
const { fullscreen, wakeLock, goToStart } = useGlobalSettings();
|
||||
const { updatePlayer, resetCurrentGame } = usePlayers();
|
||||
|
||||
const handleColorChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const updatedPlayer = { ...player, color: event.target.value };
|
||||
updatePlayer(updatedPlayer);
|
||||
};
|
||||
|
||||
const handleSettingsChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { name, checked } = event.target;
|
||||
const updatedSettings = { ...player.settings, [name]: checked };
|
||||
const updatedPlayer = { ...player, settings: updatedSettings };
|
||||
updatePlayer(updatedPlayer);
|
||||
};
|
||||
|
||||
const handleResetGame = () => {
|
||||
resetCurrentGame();
|
||||
setShowPlayerMenu(false);
|
||||
};
|
||||
|
||||
const toggleFullscreen = () => {
|
||||
if (fullscreen.isFullscreen) {
|
||||
fullscreen.disableFullscreen();
|
||||
} else {
|
||||
fullscreen.enableFullscreen();
|
||||
}
|
||||
};
|
||||
|
||||
const buttonFontSize = isSide ? '1.5vmax' : '3vmin';
|
||||
const iconSize = isSide ? '6vmin' : '3vmax';
|
||||
const extraCountersSize = isSide ? '8vmin' : '4vmax';
|
||||
const closeButtonSize = isSide ? '6vmin' : '3vmax';
|
||||
|
||||
const calcRotation =
|
||||
player.settings.rotation === Rotation.Side
|
||||
? `${player.settings.rotation - 180}deg`
|
||||
: player.settings.rotation === Rotation.SideFlipped
|
||||
? `${player.settings.rotation - 180}deg`
|
||||
: '';
|
||||
|
||||
return (
|
||||
<PlayerMenuWrapper
|
||||
//TODO: Fix hacky solution to rotation for SideFlipped
|
||||
style={{
|
||||
rotate:
|
||||
player.settings.rotation === Rotation.SideFlipped ? '180deg' : '',
|
||||
}}
|
||||
>
|
||||
<CloseButton
|
||||
$rotation={player.settings.rotation}
|
||||
style={{
|
||||
rotate:
|
||||
player.settings.rotation === Rotation.Side ||
|
||||
player.settings.rotation === Rotation.SideFlipped
|
||||
? `${player.settings.rotation - 180}deg`
|
||||
: '',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={handleOnClick}
|
||||
style={{
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
height: closeButtonSize,
|
||||
width: closeButtonSize,
|
||||
}}
|
||||
>
|
||||
<Cross size={closeButtonSize} />
|
||||
</Button>
|
||||
</CloseButton>
|
||||
|
||||
<SettingsContainer
|
||||
$rotation={player.settings.rotation}
|
||||
style={{
|
||||
rotate: calcRotation,
|
||||
}}
|
||||
ref={settingsContainerRef}
|
||||
>
|
||||
<ColorPicker
|
||||
type="color"
|
||||
value={player.color}
|
||||
onChange={handleColorChange}
|
||||
role="button"
|
||||
aria-label="Color picker"
|
||||
/>
|
||||
<BetterRowContainer>
|
||||
<TogglesSection>
|
||||
{player.settings.useCommanderDamage && (
|
||||
<CheckboxContainer>
|
||||
<Checkbox
|
||||
name="usePartner"
|
||||
checked={player.settings.usePartner}
|
||||
icon={
|
||||
<PartnerTax
|
||||
size={extraCountersSize}
|
||||
color="black"
|
||||
stroke="white"
|
||||
strokeWidth="30"
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<PartnerTax
|
||||
size={extraCountersSize}
|
||||
color={player.color}
|
||||
stroke="white"
|
||||
strokeWidth="30"
|
||||
/>
|
||||
}
|
||||
onChange={handleSettingsChange}
|
||||
role="checkbox"
|
||||
aria-checked={player.settings.usePartner}
|
||||
aria-label="Partner"
|
||||
/>
|
||||
</CheckboxContainer>
|
||||
)}
|
||||
|
||||
<CheckboxContainer>
|
||||
<Checkbox
|
||||
name="usePoison"
|
||||
checked={player.settings.usePoison}
|
||||
icon={
|
||||
<Poison
|
||||
size={extraCountersSize}
|
||||
color="black"
|
||||
stroke="white"
|
||||
strokeWidth="30"
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<Poison
|
||||
size={extraCountersSize}
|
||||
color={player.color}
|
||||
stroke="white"
|
||||
strokeWidth="30"
|
||||
/>
|
||||
}
|
||||
onChange={handleSettingsChange}
|
||||
role="checkbox"
|
||||
aria-checked={player.settings.usePoison}
|
||||
aria-label="Poison"
|
||||
/>
|
||||
</CheckboxContainer>
|
||||
|
||||
<CheckboxContainer>
|
||||
<Checkbox
|
||||
name="useEnergy"
|
||||
checked={player.settings.useEnergy}
|
||||
icon={
|
||||
<Energy
|
||||
size={extraCountersSize}
|
||||
color="black"
|
||||
stroke="white"
|
||||
strokeWidth="15"
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<Energy
|
||||
size={extraCountersSize}
|
||||
color={player.color}
|
||||
stroke="white"
|
||||
strokeWidth="15"
|
||||
/>
|
||||
}
|
||||
onChange={handleSettingsChange}
|
||||
role="checkbox"
|
||||
aria-checked={player.settings.useEnergy}
|
||||
aria-label="Energy"
|
||||
/>
|
||||
</CheckboxContainer>
|
||||
|
||||
<CheckboxContainer>
|
||||
<Checkbox
|
||||
name="useExperience"
|
||||
checked={player.settings.useExperience}
|
||||
icon={
|
||||
<Experience
|
||||
size={extraCountersSize}
|
||||
color="black"
|
||||
stroke="white"
|
||||
strokeWidth="15"
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<Experience
|
||||
size={extraCountersSize}
|
||||
color={player.color}
|
||||
stroke="white"
|
||||
strokeWidth="15"
|
||||
/>
|
||||
}
|
||||
onChange={handleSettingsChange}
|
||||
role="checkbox"
|
||||
aria-checked={player.settings.useExperience}
|
||||
aria-label="Experience"
|
||||
/>
|
||||
</CheckboxContainer>
|
||||
</TogglesSection>
|
||||
<ButtonsSections className="mt-4">
|
||||
<Button
|
||||
variant="text"
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
userSelect: 'none',
|
||||
}}
|
||||
onClick={goToStart}
|
||||
aria-label="Back to start"
|
||||
>
|
||||
<Exit size={iconSize} style={{ rotate: '180deg' }} />
|
||||
</Button>
|
||||
<CheckboxContainer>
|
||||
<Checkbox
|
||||
name="fullscreen"
|
||||
checked={document.fullscreenElement ? true : false}
|
||||
icon={
|
||||
<FullscreenOff
|
||||
size={iconSize}
|
||||
color={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={<FullscreenOn size={iconSize} />}
|
||||
onChange={toggleFullscreen}
|
||||
role="checkbox"
|
||||
aria-checked={document.fullscreenElement ? true : false}
|
||||
aria-label="Fullscreen"
|
||||
/>
|
||||
</CheckboxContainer>
|
||||
|
||||
<Button
|
||||
variant={wakeLock.active ? 'contained' : 'outlined'}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
userSelect: 'none',
|
||||
fontSize: buttonFontSize,
|
||||
padding: '0 4px 0 4px',
|
||||
}}
|
||||
onClick={wakeLock.toggleWakeLock}
|
||||
role="checkbox"
|
||||
aria-checked={wakeLock.active}
|
||||
aria-label="Keep awake"
|
||||
>
|
||||
Keep Awake
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
userSelect: 'none',
|
||||
fontSize: buttonFontSize,
|
||||
padding: '4px',
|
||||
}}
|
||||
onClick={() => dialogRef.current?.show()}
|
||||
role="checkbox"
|
||||
aria-checked={wakeLock.active}
|
||||
aria-label="Reset Game"
|
||||
>
|
||||
<ResetGame size={iconSize} />
|
||||
</Button>
|
||||
</ButtonsSections>
|
||||
</BetterRowContainer>
|
||||
<dialog
|
||||
ref={dialogRef}
|
||||
className="z-[9999] bg-background-default text-text-primary rounded-2xl border-none absolute top-[10%]"
|
||||
>
|
||||
<h1>Reset Game?</h1>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-evenly' }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => dialogRef.current?.close()}
|
||||
>
|
||||
No
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
handleResetGame();
|
||||
dialogRef.current?.close();
|
||||
}}
|
||||
>
|
||||
Yes
|
||||
</Button>
|
||||
</div>
|
||||
</dialog>
|
||||
</SettingsContainer>
|
||||
</PlayerMenuWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default PlayerMenu;
|
||||
489
src/Components/Players/PlayerMenu.tsx
Normal file
489
src/Components/Players/PlayerMenu.tsx
Normal file
@@ -0,0 +1,489 @@
|
||||
import { useRef } from 'react';
|
||||
import { twc } from 'react-twc';
|
||||
import { useAnalytics } from '../../Hooks/useAnalytics';
|
||||
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
|
||||
import { usePlayers } from '../../Hooks/usePlayers';
|
||||
import { useSafeRotate } from '../../Hooks/useSafeRotate';
|
||||
import {
|
||||
Cross,
|
||||
Energy,
|
||||
Exit,
|
||||
Experience,
|
||||
FullscreenOff,
|
||||
FullscreenOn,
|
||||
PartnerTax,
|
||||
Poison,
|
||||
ResetGame,
|
||||
} from '../../Icons/generated';
|
||||
import { Player, Rotation } from '../../Types/Player';
|
||||
import { PreStartMode } from '../../Types/Settings';
|
||||
import { RotationDivProps } from '../Buttons/CommanderDamage';
|
||||
import { IconCheckbox } from '../Misc/IconCheckbox';
|
||||
|
||||
const PlayerMenuWrapper = twc.div`
|
||||
flex
|
||||
flex-col
|
||||
absolute
|
||||
w-full
|
||||
h-full
|
||||
bg-background-settings
|
||||
backdrop-blur-[3px]
|
||||
items-center
|
||||
justify-center
|
||||
z-[2]
|
||||
webkit-user-select-none
|
||||
transition-all
|
||||
`;
|
||||
|
||||
const BetterRowContainer = twc.div`
|
||||
flex
|
||||
flex-col
|
||||
flex-grow
|
||||
w-full
|
||||
h-full
|
||||
justify-between
|
||||
items-stretch
|
||||
`;
|
||||
|
||||
const TogglesSection = twc.div`
|
||||
flex
|
||||
flex-row
|
||||
flex-wrap
|
||||
relative
|
||||
h-full
|
||||
justify-evenly
|
||||
items-center
|
||||
`;
|
||||
|
||||
const ButtonsSections = twc.div`
|
||||
flex
|
||||
max-w-full
|
||||
justify-evenly
|
||||
items-center
|
||||
flex-wrap
|
||||
mt-0
|
||||
px-2
|
||||
`;
|
||||
|
||||
const ColorPickerButton = twc.div`
|
||||
h-[8vmax]
|
||||
w-[8vmax]
|
||||
relative
|
||||
max-h-12
|
||||
max-w-12
|
||||
rounded-full
|
||||
cursor-pointer
|
||||
overflow-hidden
|
||||
`;
|
||||
|
||||
const SettingsContainer = twc.div<RotationDivProps>((props) => [
|
||||
'flex flex-wrap h-full w-full overflow-y-scroll',
|
||||
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||
? 'flex-col'
|
||||
: 'flex-row',
|
||||
]);
|
||||
|
||||
type PlayerMenuProps = {
|
||||
player: Player;
|
||||
setShowPlayerMenu: (showPlayerMenu: boolean) => void;
|
||||
isShown: boolean;
|
||||
};
|
||||
|
||||
const PlayerMenu = ({
|
||||
player,
|
||||
setShowPlayerMenu,
|
||||
isShown,
|
||||
}: PlayerMenuProps) => {
|
||||
const settingsContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const resetGameDialogRef = useRef<HTMLDialogElement | null>(null);
|
||||
const endGameDialogRef = useRef<HTMLDialogElement | null>(null);
|
||||
|
||||
const { isSide } = useSafeRotate({
|
||||
rotation: player.settings.rotation,
|
||||
containerRef: settingsContainerRef,
|
||||
});
|
||||
|
||||
const {
|
||||
fullscreen,
|
||||
wakeLock,
|
||||
goToStart,
|
||||
settings,
|
||||
setPlaying,
|
||||
setRandomizingPlayer,
|
||||
saveCurrentGame,
|
||||
initialGameSettings,
|
||||
setPreStartCompleted,
|
||||
} = useGlobalSettings();
|
||||
|
||||
const analytics = useAnalytics();
|
||||
|
||||
const { updatePlayer, resetCurrentGame, players } = usePlayers();
|
||||
|
||||
const handleColorChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const updatedPlayer = { ...player, color: event.target.value };
|
||||
updatePlayer(updatedPlayer);
|
||||
};
|
||||
|
||||
const handleSettingsChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { name, checked } = event.target;
|
||||
const updatedSettings = { ...player.settings, [name]: checked };
|
||||
const updatedPlayer = { ...player, settings: updatedSettings };
|
||||
|
||||
updatePlayer(updatedPlayer);
|
||||
};
|
||||
|
||||
const handleResetGame = () => {
|
||||
resetCurrentGame();
|
||||
setShowPlayerMenu(false);
|
||||
|
||||
setPlaying(false);
|
||||
|
||||
if (settings.preStartMode === PreStartMode.RandomKing) {
|
||||
setRandomizingPlayer(true);
|
||||
setPreStartCompleted(false);
|
||||
}
|
||||
|
||||
analytics.trackEvent('reset_game');
|
||||
};
|
||||
|
||||
const handleGoToStart = () => {
|
||||
saveCurrentGame({ players, initialGameSettings });
|
||||
goToStart();
|
||||
setRandomizingPlayer(true);
|
||||
};
|
||||
|
||||
const toggleFullscreen = () => {
|
||||
if (fullscreen.isFullscreen) {
|
||||
fullscreen.disableFullscreen();
|
||||
} else {
|
||||
fullscreen.enableFullscreen();
|
||||
}
|
||||
};
|
||||
|
||||
const buttonFontSize = isSide ? '1.5vmax' : '3vmin';
|
||||
const iconSize = isSide ? '6vmin' : '3vmax';
|
||||
const extraCountersSize = isSide ? '8vmin' : '4vmax';
|
||||
|
||||
const calcRotation =
|
||||
player.settings.rotation === Rotation.Side
|
||||
? `${player.settings.rotation - 180}deg`
|
||||
: player.settings.rotation === Rotation.SideFlipped
|
||||
? `${player.settings.rotation - 180}deg`
|
||||
: '';
|
||||
|
||||
return (
|
||||
<PlayerMenuWrapper
|
||||
//TODO: Fix hacky solution to rotation for SideFlipped
|
||||
style={{
|
||||
rotate:
|
||||
player.settings.rotation === Rotation.SideFlipped ? `180deg` : '',
|
||||
translate: isShown ? '' : player.isSide ? `-100%` : `0 -100%`,
|
||||
}}
|
||||
>
|
||||
<SettingsContainer
|
||||
$rotation={player.settings.rotation}
|
||||
style={{
|
||||
rotate: calcRotation,
|
||||
}}
|
||||
ref={settingsContainerRef}
|
||||
>
|
||||
<button
|
||||
onClick={() => {
|
||||
analytics.trackEvent('close_player_menu_button');
|
||||
setShowPlayerMenu(false);
|
||||
}}
|
||||
className="flex absolute top-0 right-2 z-10 bg-transparent items-center justify-center rounded-full border-solid border-primary-main border-2 p-[0.2rem]"
|
||||
>
|
||||
<Cross size={buttonFontSize} className="text-primary-main " />
|
||||
</button>
|
||||
|
||||
<BetterRowContainer>
|
||||
<TogglesSection>
|
||||
<ColorPickerButton aria-label="Color picker">
|
||||
<input
|
||||
onChange={handleColorChange}
|
||||
type="color"
|
||||
className="size-[200%] absolute -left-2 -top-2"
|
||||
value={player.color}
|
||||
onClick={() => {
|
||||
analytics.trackEvent('color_picker_opened', {
|
||||
player: player.index,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</ColorPickerButton>
|
||||
{player.settings.useCommanderDamage && (
|
||||
<div className="flex flex-col items-center">
|
||||
<IconCheckbox
|
||||
name="usePartner"
|
||||
checked={player.settings.usePartner}
|
||||
icon={
|
||||
<PartnerTax
|
||||
size={extraCountersSize}
|
||||
color="black"
|
||||
stroke="white"
|
||||
strokeWidth="30"
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<PartnerTax
|
||||
size={extraCountersSize}
|
||||
color={player.color}
|
||||
stroke="white"
|
||||
strokeWidth="30"
|
||||
/>
|
||||
}
|
||||
onChange={(e) => {
|
||||
analytics.trackEvent('toggle_partner', {
|
||||
checked: e.target.checked,
|
||||
});
|
||||
handleSettingsChange(e);
|
||||
}}
|
||||
aria-checked={player.settings.usePartner}
|
||||
aria-label="Partner"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<IconCheckbox
|
||||
name="usePoison"
|
||||
checked={player.settings.usePoison}
|
||||
icon={
|
||||
<Poison
|
||||
size={extraCountersSize}
|
||||
color="black"
|
||||
stroke="white"
|
||||
strokeWidth="30"
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<Poison
|
||||
size={extraCountersSize}
|
||||
color={player.color}
|
||||
stroke="white"
|
||||
strokeWidth="30"
|
||||
/>
|
||||
}
|
||||
onChange={(e) => {
|
||||
analytics.trackEvent('toggle_poison', {
|
||||
checked: e.target.checked,
|
||||
});
|
||||
handleSettingsChange(e);
|
||||
}}
|
||||
aria-checked={player.settings.usePoison}
|
||||
aria-label="Poison"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<IconCheckbox
|
||||
name="useEnergy"
|
||||
checked={player.settings.useEnergy}
|
||||
icon={
|
||||
<Energy
|
||||
size={extraCountersSize}
|
||||
color="black"
|
||||
stroke="white"
|
||||
strokeWidth="15"
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<Energy
|
||||
size={extraCountersSize}
|
||||
color={player.color}
|
||||
stroke="white"
|
||||
strokeWidth="15"
|
||||
/>
|
||||
}
|
||||
onChange={(e) => {
|
||||
analytics.trackEvent('toggle_energy', {
|
||||
checked: e.target.checked,
|
||||
});
|
||||
handleSettingsChange(e);
|
||||
}}
|
||||
aria-checked={player.settings.useEnergy}
|
||||
aria-label="Energy"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<IconCheckbox
|
||||
name="useExperience"
|
||||
checked={player.settings.useExperience}
|
||||
icon={
|
||||
<Experience
|
||||
size={extraCountersSize}
|
||||
color="black"
|
||||
stroke="white"
|
||||
strokeWidth="15"
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<Experience
|
||||
size={extraCountersSize}
|
||||
color={player.color}
|
||||
stroke="white"
|
||||
strokeWidth="15"
|
||||
/>
|
||||
}
|
||||
onChange={(e) => {
|
||||
analytics.trackEvent('toggle_experience', {
|
||||
checked: e.target.checked,
|
||||
});
|
||||
handleSettingsChange(e);
|
||||
}}
|
||||
aria-checked={player.settings.useExperience}
|
||||
aria-label="Experience"
|
||||
/>
|
||||
</div>
|
||||
</TogglesSection>
|
||||
<ButtonsSections>
|
||||
<button
|
||||
className="text-primary-main cursor-pointer webkit-user-select-none"
|
||||
onClick={() => endGameDialogRef.current?.show()}
|
||||
aria-label="Back to start"
|
||||
>
|
||||
<Exit size={iconSize} style={{ rotate: '180deg' }} />
|
||||
</button>
|
||||
<div
|
||||
data-fullscreen={document.fullscreenElement ? true : false}
|
||||
className="flex
|
||||
data-[fullscreen=true]:bg-secondary-dark rounded-lg border border-transparent
|
||||
data-[fullscreen=true]:border-primary-main"
|
||||
>
|
||||
<IconCheckbox
|
||||
className="p-1"
|
||||
name="fullscreen"
|
||||
checked={document.fullscreenElement ? true : false}
|
||||
icon={
|
||||
<FullscreenOff
|
||||
size={iconSize}
|
||||
className="text-primary-main"
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<FullscreenOn size={iconSize} className="text-primary-main" />
|
||||
}
|
||||
onChange={toggleFullscreen}
|
||||
aria-checked={document.fullscreenElement ? true : false}
|
||||
aria-label="Fullscreen"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
data-wake-lock-active={settings.keepAwake}
|
||||
style={{
|
||||
fontSize: buttonFontSize,
|
||||
}}
|
||||
className="text-primary-main px-1 webkit-user-select-none cursor-pointer
|
||||
data-[wake-lock-active=true]:bg-secondary-dark rounded-lg border border-transparent
|
||||
data-[wake-lock-active=true]:border-primary-main
|
||||
"
|
||||
onClick={() => {
|
||||
wakeLock.toggleWakeLock();
|
||||
}}
|
||||
role="checkbox"
|
||||
aria-checked={settings.keepAwake}
|
||||
aria-label="Keep awake"
|
||||
>
|
||||
Keep Awake
|
||||
</button>
|
||||
|
||||
<button
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
userSelect: 'none',
|
||||
fontSize: buttonFontSize,
|
||||
padding: '2px',
|
||||
}}
|
||||
className="text-primary-main"
|
||||
onClick={() => resetGameDialogRef.current?.show()}
|
||||
role="checkbox"
|
||||
aria-label="Reset Game"
|
||||
>
|
||||
<ResetGame size={iconSize} />
|
||||
</button>
|
||||
</ButtonsSections>
|
||||
</BetterRowContainer>
|
||||
|
||||
<dialog
|
||||
ref={resetGameDialogRef}
|
||||
className="z-[999] size-full bg-background-settings overflow-y-scroll"
|
||||
onClick={() => resetGameDialogRef.current?.close()}
|
||||
>
|
||||
<div className="flex size-full items-center justify-center">
|
||||
<div className="flex flex-col justify-center p-4 gap-2 bg-background-default rounded-xl border-none">
|
||||
<h1
|
||||
className="text-center text-text-primary"
|
||||
style={{ fontSize: extraCountersSize }}
|
||||
>
|
||||
Reset Game?
|
||||
</h1>
|
||||
<div className="flex justify-evenly gap-2">
|
||||
<button
|
||||
className="bg-primary-main border border-primary-dark text-text-primary rounded-lg flex-grow"
|
||||
style={{ fontSize: iconSize }}
|
||||
onClick={() => resetGameDialogRef.current?.close()}
|
||||
>
|
||||
No
|
||||
</button>
|
||||
<button
|
||||
className="bg-primary-main border border-primary-dark text-text-primary rounded-lg flex-grow"
|
||||
onClick={() => {
|
||||
handleResetGame();
|
||||
resetGameDialogRef.current?.close();
|
||||
}}
|
||||
style={{ fontSize: iconSize }}
|
||||
>
|
||||
Yes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<dialog
|
||||
ref={endGameDialogRef}
|
||||
className="z-[999] size-full bg-background-settings overflow-y-scroll"
|
||||
onClick={() => endGameDialogRef.current?.close()}
|
||||
>
|
||||
<div className="flex size-full items-center justify-center">
|
||||
<div className="flex flex-col justify-center p-4 gap-2 bg-background-default rounded-xl border-none">
|
||||
<h1
|
||||
className="text-center text-text-primary"
|
||||
style={{ fontSize: extraCountersSize }}
|
||||
>
|
||||
Go to start?
|
||||
</h1>
|
||||
<div
|
||||
style={{ fontSize: iconSize }}
|
||||
className="text-center text-text-primary"
|
||||
>
|
||||
(Game will be saved)
|
||||
</div>
|
||||
<div className="flex justify-evenly gap-2">
|
||||
<button
|
||||
className="bg-primary-main border border-primary-dark text-text-primary rounded-lg flex-grow"
|
||||
style={{ fontSize: iconSize }}
|
||||
onClick={() => endGameDialogRef.current?.close()}
|
||||
>
|
||||
No
|
||||
</button>
|
||||
<button
|
||||
className="bg-primary-main border border-primary-dark text-text-primary rounded-lg flex-grow"
|
||||
onClick={() => {
|
||||
handleGoToStart();
|
||||
endGameDialogRef.current?.close();
|
||||
}}
|
||||
style={{ fontSize: iconSize }}
|
||||
>
|
||||
Yes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
</SettingsContainer>
|
||||
</PlayerMenuWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default PlayerMenu;
|
||||
@@ -1,6 +1,8 @@
|
||||
import LifeCounter from '../LifeCounter/LifeCounter';
|
||||
import { Player as PlayerType } from '../../Types/Player';
|
||||
import { twc } from 'react-twc';
|
||||
import { usePlayers } from '../../Hooks/usePlayers';
|
||||
import { Player as PlayerType } from '../../Types/Player';
|
||||
import LifeCounter from '../LifeCounter/LifeCounter';
|
||||
import { GridLayout } from '../Views/Play';
|
||||
|
||||
const getGridArea = (player: PlayerType) => {
|
||||
switch (player.index) {
|
||||
@@ -21,15 +23,16 @@ const getGridArea = (player: PlayerType) => {
|
||||
}
|
||||
};
|
||||
|
||||
const PlayerWrapper = twc.div`w-full h-full bg-black`;
|
||||
const PlayersWrapper = twc.div`w-full h-full bg-black`;
|
||||
|
||||
export const Players = ({ gridLayout }: { gridLayout: GridLayout }) => {
|
||||
const { players } = usePlayers();
|
||||
|
||||
export const Player = (players: PlayerType[], gridClasses: string) => {
|
||||
return (
|
||||
<PlayerWrapper>
|
||||
<div className={`grid w-full h-full gap-1 box-border ${gridClasses} `}>
|
||||
<PlayersWrapper>
|
||||
<div className={`grid w-full h-full gap-1 box-border ${gridLayout} `}>
|
||||
{players.map((player) => {
|
||||
const gridArea = getGridArea(player);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={player.index}
|
||||
@@ -45,6 +48,6 @@ export const Player = (players: PlayerType[], gridClasses: string) => {
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</PlayerWrapper>
|
||||
</PlayersWrapper>
|
||||
);
|
||||
};
|
||||
202
src/Components/PreStartGame/Games/FingerGame.tsx
Normal file
202
src/Components/PreStartGame/Games/FingerGame.tsx
Normal file
@@ -0,0 +1,202 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useGlobalSettings } from '../../../Hooks/useGlobalSettings';
|
||||
import { usePlayers } from '../../../Hooks/usePlayers';
|
||||
|
||||
type TouchPoint = {
|
||||
x: number;
|
||||
y: number;
|
||||
id: number;
|
||||
};
|
||||
|
||||
const getOrientation = () => {
|
||||
return window.matchMedia('(orientation: portrait)').matches
|
||||
? 'portrait'
|
||||
: 'landscape';
|
||||
};
|
||||
|
||||
const ANIMATION_INTRO_LENGTH = 500;
|
||||
|
||||
const BEFORE_INTRO_TIMER_LENGTH = 100;
|
||||
|
||||
export const FingerGame = () => {
|
||||
const { players } = usePlayers();
|
||||
|
||||
const aboutToStartTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const selectingPlayerTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const [touchPoints, setTouchPoints] = useState<TouchPoint[]>([]);
|
||||
const [selectedTouchPoint, setSelectedTouchPoint] = useState<
|
||||
TouchPoint | undefined
|
||||
>();
|
||||
const [timerStarted, setTimerStarted] = useState(false);
|
||||
|
||||
const { setPlaying, goToStart } = useGlobalSettings();
|
||||
|
||||
useEffect(() => {
|
||||
//Start playing when someone is selected and any touch point is released
|
||||
if (selectedTouchPoint && touchPoints.length !== players.length) {
|
||||
aboutToStartTimerRef.current = setTimeout(() => {
|
||||
setSelectedTouchPoint(undefined);
|
||||
setPlaying(true);
|
||||
}, ANIMATION_INTRO_LENGTH);
|
||||
|
||||
setTimerStarted(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// If no touch point is selected, select one with a delay
|
||||
if (touchPoints.length === players.length && !selectedTouchPoint) {
|
||||
selectingPlayerTimerRef.current = setTimeout(() => {
|
||||
const randomIndex = Math.floor(Math.random() * touchPoints.length);
|
||||
const randomTouchPoint = touchPoints[randomIndex];
|
||||
setSelectedTouchPoint(randomTouchPoint);
|
||||
}, BEFORE_INTRO_TIMER_LENGTH);
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectingPlayerTimerRef.current) {
|
||||
clearTimeout(selectingPlayerTimerRef.current);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (aboutToStartTimerRef.current) {
|
||||
clearTimeout(aboutToStartTimerRef.current);
|
||||
}
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [touchPoints, players.length]);
|
||||
|
||||
const handleOnTouchStart = (e: React.TouchEvent) => {
|
||||
if (selectedTouchPoint) {
|
||||
return;
|
||||
}
|
||||
//Get the first touch point id that isn't already in the touchPoints array
|
||||
const touch = Array.from(e.changedTouches).find(
|
||||
(t) => !touchPoints.find((p) => p.id === t.identifier)
|
||||
);
|
||||
|
||||
if (!touch) {
|
||||
console.error('No touch found');
|
||||
return;
|
||||
}
|
||||
|
||||
let { clientX, clientY } = touch;
|
||||
|
||||
// Adjust coordinates for portrait mode
|
||||
if (getOrientation() === 'portrait') {
|
||||
const tempX = clientX;
|
||||
clientX = clientY;
|
||||
clientY = window.innerWidth - tempX;
|
||||
}
|
||||
|
||||
const newTouchPoints = {
|
||||
x: clientX,
|
||||
y: clientY,
|
||||
id: touch.identifier,
|
||||
};
|
||||
|
||||
setTouchPoints([...touchPoints, newTouchPoints]);
|
||||
};
|
||||
|
||||
const handleOnTouchEnd = (e: React.TouchEvent) => {
|
||||
if (selectedTouchPoint) {
|
||||
aboutToStartTimerRef.current = setTimeout(() => {
|
||||
setSelectedTouchPoint(undefined);
|
||||
setPlaying(true);
|
||||
}, ANIMATION_INTRO_LENGTH);
|
||||
setTimerStarted(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the touch point that was just released
|
||||
const touch = e.changedTouches[e.changedTouches.length - 1];
|
||||
|
||||
// Get the index of the touch point that was just released
|
||||
const index = touchPoints.findIndex((p) => p.id === touch.identifier);
|
||||
|
||||
// Remove the touch point that was just released
|
||||
setTouchPoints([
|
||||
...touchPoints.slice(0, index),
|
||||
...touchPoints.slice(index + 1),
|
||||
]);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="absolute flex justify-center items-center w-full h-full portrait:h-[100dvw] portrait:w-[100dvh] z-50 bg-secondary-main overflow-hidden"
|
||||
onTouchStart={handleOnTouchStart}
|
||||
onTouchEnd={handleOnTouchEnd}
|
||||
|
||||
// FIXEME: This code is not performant, but updates a touch point's position when it moves
|
||||
// onTouchMove={(e) => {
|
||||
// e.preventDefault();
|
||||
|
||||
// // Get the touch point that was just moved
|
||||
// const touch = Array.from(e.changedTouches).find((t) =>
|
||||
// touchPoints.find((p) => p.id === t.identifier)
|
||||
// );
|
||||
|
||||
// if (!touch) {
|
||||
// console.error('No touch found');
|
||||
// return;
|
||||
// }
|
||||
|
||||
// let { clientX, clientY } = touch;
|
||||
|
||||
// // Adjust coordinates for portrait mode
|
||||
// if (getOrientation() === 'portrait') {
|
||||
// const tempX = clientX;
|
||||
// clientX = clientY;
|
||||
// clientY = window.innerWidth - tempX;
|
||||
// }
|
||||
|
||||
// // Get the index of the touch point that was just moved
|
||||
// const index = touchPoints.findIndex(
|
||||
// (p) => p.id === touch.identifier
|
||||
// );
|
||||
|
||||
// // Update the touch point that was just moved
|
||||
// setTouchPoints([
|
||||
// ...touchPoints.slice(0, index),
|
||||
// { x: clientX, y: clientY, id: touch.identifier },
|
||||
// ...touchPoints.slice(index + 1),
|
||||
// ]);
|
||||
// }}
|
||||
>
|
||||
<button
|
||||
className="absolute flex top-4 left-4 rounded-lg px-2 py-1 justify-center bg-primary-main text-text-primary text-xs duration-200 ease-in-out shadow-[1px_2px_4px_0px_rgba(0,0,0,0.3)] hover:bg-primary-dark"
|
||||
onClick={goToStart}
|
||||
>
|
||||
<div className="text-xl leading-4">{'<'} </div>
|
||||
Back
|
||||
</button>
|
||||
{touchPoints.length !== players.length && (
|
||||
<div className="flex flex-col items-center text-[13vmin] whitespace-nowrap pointer-events-none webkit-user-select-none">
|
||||
Waiting for fingers <br />
|
||||
<div className="tabular-nums">
|
||||
{touchPoints.length}/{players.length}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{touchPoints.map((point, index) => (
|
||||
<div
|
||||
key={`touch-point-${index}`}
|
||||
data-is-selected={selectedTouchPoint?.id === point.id}
|
||||
data-unloading={timerStarted}
|
||||
className="absolute rounded-full translate-x-[-50%] translate-y-[-50%] transition-all duration-500
|
||||
h-[75px] w-[75px]
|
||||
data-[unloading=false]:data-[is-selected=true]:h-[250px] data-[unloading=false]:data-[is-selected=true]:w-[250px]
|
||||
data-[unloading=true]:h-[0px] data-[unloading=true]:w-[0px] data-[unloading=true]:duration-[400ms]
|
||||
pointer-events-none
|
||||
"
|
||||
style={{
|
||||
left: point.x,
|
||||
top: point.y,
|
||||
backgroundColor: players[index]?.color ?? 'red',
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
import { usePlayers } from '../../../../Hooks/usePlayers';
|
||||
import { Player } from '../../../../Types/Player';
|
||||
import { GridLayout } from '../../../Views/Play';
|
||||
import { RoulettePlayerCard } from './RoulettePlayerCard';
|
||||
|
||||
const getGridArea = (player: Player) => {
|
||||
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 RandomKingPlayers = ({
|
||||
gridLayout,
|
||||
}: {
|
||||
gridLayout: GridLayout;
|
||||
}) => {
|
||||
const { players } = usePlayers();
|
||||
|
||||
return (
|
||||
<div className="w-full h-full bg-black">
|
||||
<div className={`grid w-full h-full gap-1 box-border ${gridLayout} `}>
|
||||
{players.map((player) => {
|
||||
const gridArea = getGridArea(player);
|
||||
return (
|
||||
<div
|
||||
key={player.index}
|
||||
className={`flex justify-center items-center align-middle ${gridArea}`}
|
||||
>
|
||||
<RoulettePlayerCard player={player} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useGlobalSettings } from '../../../../Hooks/useGlobalSettings';
|
||||
import { usePlayers } from '../../../../Hooks/usePlayers';
|
||||
|
||||
export const RandomKingSelectWrapper = () => {
|
||||
const { setRandomizingPlayer } = useGlobalSettings();
|
||||
|
||||
const randomIntervalRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const prevRandomIndexRef = useRef<number>(-1);
|
||||
|
||||
const { settings, randomizingPlayer, setPreStartCompleted } =
|
||||
useGlobalSettings();
|
||||
|
||||
const { players, setPlayers } = usePlayers();
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
players.length > 1 &&
|
||||
settings.showStartingPlayer &&
|
||||
randomizingPlayer
|
||||
) {
|
||||
randomIntervalRef.current = setInterval(() => {
|
||||
let randomIndex: number;
|
||||
|
||||
do {
|
||||
randomIndex = Math.floor(Math.random() * players.length);
|
||||
} while (randomIndex === prevRandomIndexRef.current);
|
||||
|
||||
prevRandomIndexRef.current = randomIndex;
|
||||
setPlayers(
|
||||
players.map((p) =>
|
||||
p.index === prevRandomIndexRef.current
|
||||
? {
|
||||
...p,
|
||||
isStartingPlayer: true,
|
||||
}
|
||||
: {
|
||||
...p,
|
||||
isStartingPlayer: false,
|
||||
}
|
||||
)
|
||||
);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
const randomPlayerIndex = Math.floor(Math.random() * players.length);
|
||||
setPlayers(
|
||||
players.map((p) =>
|
||||
p.index === randomPlayerIndex
|
||||
? {
|
||||
...p,
|
||||
isStartingPlayer: true,
|
||||
}
|
||||
: {
|
||||
...p,
|
||||
isStartingPlayer: false,
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
return () => {
|
||||
if (randomIntervalRef.current) {
|
||||
clearInterval(randomIntervalRef.current);
|
||||
}
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [players.length, setPlayers, randomizingPlayer]);
|
||||
|
||||
const gradientColors = players.map((player) => player.color).join(', ');
|
||||
|
||||
return (
|
||||
<div
|
||||
className="absolute flex justify-center items-center h-screen w-screen portrait:h-[100vw] portrait:w-[100vh] z-40 cursor-pointer text-5xl"
|
||||
onClick={() => {
|
||||
if (randomIntervalRef.current) {
|
||||
clearInterval(randomIntervalRef.current);
|
||||
randomIntervalRef.current = null;
|
||||
}
|
||||
setRandomizingPlayer(false);
|
||||
setPreStartCompleted(true);
|
||||
}}
|
||||
>
|
||||
<div className="absolute flex top-[30%] justify-center items-center px-8 py-4">
|
||||
<div
|
||||
className="absolute size-full blur-[3px] rounded-2xl opacity-90 saturate-150"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(60deg, ${gradientColors})`,
|
||||
}}
|
||||
/>
|
||||
<p className="relative z-10 text-[5vmax]">PRESS TO SELECT PLAYER</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useGlobalSettings } from '../../../../Hooks/useGlobalSettings';
|
||||
import { Player, Rotation } from '../../../../Types/Player';
|
||||
import { Paragraph } from '../../../Misc/TextComponents';
|
||||
import { DynamicText } from '../../StartingPlayerCard';
|
||||
|
||||
export const RoulettePlayerCard = ({ player }: { player: Player }) => {
|
||||
const startPlayingTimerRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||
|
||||
const { settings, randomizingPlayer, playing, setPlaying } =
|
||||
useGlobalSettings();
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
player.isStartingPlayer &&
|
||||
((!playing && randomizingPlayer) || !playing)
|
||||
) {
|
||||
startPlayingTimerRef.current = setTimeout(() => {
|
||||
setPlaying(true);
|
||||
}, 10_000);
|
||||
}
|
||||
|
||||
return () => clearTimeout(startPlayingTimerRef.current);
|
||||
}, [
|
||||
player.isStartingPlayer,
|
||||
playing,
|
||||
setPlaying,
|
||||
settings.preStartMode,
|
||||
randomizingPlayer,
|
||||
]);
|
||||
|
||||
const calcTextRotation =
|
||||
player.settings.rotation === Rotation.SideFlipped ||
|
||||
player.settings.rotation === Rotation.Side
|
||||
? player.settings.rotation - 180
|
||||
: player.settings.rotation;
|
||||
|
||||
return (
|
||||
<div className="relative flex flex-grow flex-col items-center w-full h-full overflow-hidden">
|
||||
<div
|
||||
className="flex absolute w-full h-full justify-center items-center pointer-events-none select-none webkit-user-select-none z-10"
|
||||
style={{ backgroundColor: player.color }}
|
||||
>
|
||||
{player.isStartingPlayer && (
|
||||
<DynamicText
|
||||
style={{
|
||||
rotate: `${calcTextRotation}deg`,
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-col justify-center items-center">
|
||||
<Paragraph>👑</Paragraph>
|
||||
</div>
|
||||
</DynamicText>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
159
src/Components/PreStartGame/Games/Trivia.tsx
Normal file
159
src/Components/PreStartGame/Games/Trivia.tsx
Normal file
@@ -0,0 +1,159 @@
|
||||
import { useState } from 'react';
|
||||
import { useGlobalSettings } from '../../../Hooks/useGlobalSettings';
|
||||
|
||||
const questions = [
|
||||
'Who has the most siblings?',
|
||||
'Who has the most pets?',
|
||||
'Who has the most tattoos?',
|
||||
'Who has the most piercings?',
|
||||
'Who has the most expensive shoes?',
|
||||
'Who has the most most amount of teeth?',
|
||||
'Who has the least amount of teeth?',
|
||||
'Who lives closest to the equator?',
|
||||
'Who is the tallest person in the group?',
|
||||
'Who is the shortest person in the group?',
|
||||
'Who speaks the most languages?',
|
||||
'Who has traveled to the most countries?',
|
||||
'Who has the earliest birthday in the year?',
|
||||
'Who has won the most awards or trophies?',
|
||||
'Who is the best cook among you?',
|
||||
'Who is the fastest runner?',
|
||||
'Who has the most unique hobby?',
|
||||
'Who is the biggest movie buff?',
|
||||
'Who is the most tech-savvy?',
|
||||
'Who is the best at solving puzzles?',
|
||||
'Who has the most extensive music collection?',
|
||||
'Who has the most impressive collection of books?',
|
||||
'Who has the most experience in a particular sport or activity?',
|
||||
'Who has the most interesting job or profession?',
|
||||
'Who has the most artistic talent?',
|
||||
'Who is the most organized person?',
|
||||
'Who is the best at keeping secrets?',
|
||||
'Who has the most fascinating family history?',
|
||||
'Who has the most embarrassing childhood nickname?',
|
||||
'Who has the most unusual talent or skill?',
|
||||
'Who has the most interesting family tradition?',
|
||||
'Who has the most impressive celebrity encounter?',
|
||||
'Who has the most unusual phobia?',
|
||||
'Who has the most adventurous spirit?',
|
||||
'Who has the most unique item in their wallet/purse?',
|
||||
'Who has the most daring fashion sense?',
|
||||
'Who has the most impressive party trick?',
|
||||
'Who has the most memorable encounter with a wild animal?',
|
||||
'Who has the most adventurous palate?',
|
||||
'Who has the most unusual collection?',
|
||||
'Who has the most unique bucket list item?',
|
||||
'Who has the most inspiring life motto or mantra?',
|
||||
'Who is the most likely to break out into song or dance in public?',
|
||||
'Who is the most likely to be found binge-watching TV shows?',
|
||||
'Who is the biggest procrastinator?',
|
||||
'Who is the most likely to cry during a movie?',
|
||||
'Who is the most adventurous when it comes to trying new foods?',
|
||||
"Who is the most likely to forget someone's birthday?",
|
||||
'Who is the best at giving advice?',
|
||||
'Who is the worst at giving advice?',
|
||||
'Who is the most likely to be found reading a book at a party?',
|
||||
'Who is the most likely to win in a game of charades?',
|
||||
'Who is the most likely to get lost in their own neighborhood?',
|
||||
'Who is the most sentimental?',
|
||||
'Who is the most likely to become famous?',
|
||||
'Who is the most likely to become a millionaire?',
|
||||
'Who is the most likely to start their own business?',
|
||||
'Who is the most likely to become president?',
|
||||
'Who is the most likely to go viral on social media?',
|
||||
'Who is the most likely to win a Nobel Prize?',
|
||||
'Who is the most likely to be a superhero in disguise?',
|
||||
'Who is the most likely to survive a zombie apocalypse?',
|
||||
'Who is the most likely to believe in aliens?',
|
||||
'Who is the most likely to spend all their money on something silly?',
|
||||
'Who is the most likely to write a bestselling novel?',
|
||||
'Who is the most likely to be a secret agent?',
|
||||
'Who is the most likely to be a professional athlete?',
|
||||
'Who is the most likely to win a game of trivia?',
|
||||
|
||||
'Who is the most likely to win the upcoming game?',
|
||||
'Who is the most likely to win at a game of Pokémon TCG?',
|
||||
'Who has the most valuable card in their collection?',
|
||||
'Who is the best at building decks?',
|
||||
'Who has won the most games?',
|
||||
'Who has the largest collection of cards?',
|
||||
'Who is the most knowledgeable about Magic the Gathering lore?',
|
||||
'Who is the most strategic?',
|
||||
'Who is the most likely to trade away their most valuable card for something silly?',
|
||||
'Who is the most competitive?',
|
||||
'Who would be the most creative when it comes to making up new Magic the Gathering rules?',
|
||||
'Who is the most likely to organize a Magic the Gathering draft tournament?',
|
||||
'Who is the most enthusiastic about opening booster packs?',
|
||||
'Who has the most unique and unusual Magic the Gathering deck?',
|
||||
'Who is the most likely to cosplay as their favorite Magic the Gathering character?',
|
||||
'Who is the most likely to forget to bring their Magic the Gathering deck to a game night?',
|
||||
'Who is the most generous when it comes to lending out their decks?',
|
||||
'Who is the most likely to start their own Magic the Gathering YouTube channel?',
|
||||
'Who is the most skilled at bluffing during a game of Magic the Gathering?',
|
||||
'Who is the most likely to spend all their money on Magic the Gathering cards?',
|
||||
'Who is the most likely to rage quit during a game of Magic the Gathering?',
|
||||
'Who is the most likely to win in a Magic the Gathering trivia contest?',
|
||||
'Who is the most likely to build a themed Magic the Gathering deck?',
|
||||
'Who is the most likely to organize a Magic the Gathering cube draft?',
|
||||
'Who is the most likely to teach new players how to play Magic the Gathering?',
|
||||
'Who is the most likely to build a commander deck with a ridiculous theme?',
|
||||
'Who is the most likely to collect foreign-language Magic the Gathering cards?',
|
||||
'Who is the most likely to participate in a Magic the Gathering charity event?',
|
||||
'Who is the most likely to cosplay as their Magic the Gathering commander?',
|
||||
'Who is the most likely to organize a Magic the Gathering charity tournament?',
|
||||
];
|
||||
|
||||
export const Trivia = () => {
|
||||
const { setPlaying, goToStart } = useGlobalSettings();
|
||||
|
||||
const [randomQuestion, setRandomQuestion] = useState(
|
||||
questions[Math.floor(Math.random() * questions.length)]
|
||||
);
|
||||
|
||||
const setUniqueRandomQuestion = () => {
|
||||
let newRandomQuestion =
|
||||
questions[Math.floor(Math.random() * questions.length)];
|
||||
while (newRandomQuestion === randomQuestion) {
|
||||
newRandomQuestion =
|
||||
questions[Math.floor(Math.random() * questions.length)];
|
||||
}
|
||||
setRandomQuestion(newRandomQuestion);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="absolute flex justify-center items-center w-full h-full portrait:h-[100dvw] portrait:w-[100dvh] z-50 bg-primary-main overflow-hidden"
|
||||
onClick={() => setPlaying(true)}
|
||||
>
|
||||
<button
|
||||
className="absolute flex top-4 left-4 rounded-lg px-2 py-1 justify-center bg-primary-main text-text-primary text-xs duration-200 ease-in-out shadow-[1px_2px_4px_0px_rgba(0,0,0,0.3)] hover:bg-primary-dark"
|
||||
onClick={goToStart}
|
||||
>
|
||||
<div className="text-xl leading-[0.80rem]">{'<'} </div>
|
||||
Back
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="absolute flex top-4 right-4 rounded-lg px-2 py-1 justify-center bg-primary-main text-text-primary text-xs duration-200 ease-in-out shadow-[1px_2px_4px_0px_rgba(0,0,0,0.3)] hover:bg-primary-dark"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setUniqueRandomQuestion();
|
||||
}}
|
||||
>
|
||||
Reroll
|
||||
</button>
|
||||
|
||||
<div className="size-full flex flex-col justify-between items-center whitespace-nowrap pointer-events-none webkit-user-select-none text-wrap text-center py-[10vmin] px-[10vmax]">
|
||||
<div className="text-[6vmin]">Decide who starts by answering:</div>
|
||||
<div className="flex flex-col">
|
||||
<div className="text-[8vmin] rotate-180 text-text-primary opacity-40">
|
||||
{randomQuestion}
|
||||
</div>
|
||||
<div className="text-[8vmin]">{randomQuestion}</div>
|
||||
</div>
|
||||
|
||||
<div className="text-[6vmin]">(Tap the screen to dismiss)</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
35
src/Components/PreStartGame/PreStart.tsx
Normal file
35
src/Components/PreStartGame/PreStart.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
|
||||
import { PreStartMode } from '../../Types/Settings';
|
||||
import { GridLayout } from '../Views/Play';
|
||||
import { FingerGame } from './Games/FingerGame';
|
||||
import { RandomKingPlayers } from './Games/RandomKing/RandomKingPlayers';
|
||||
import { RandomKingSelectWrapper } from './Games/RandomKing/RandomKingSelectWrapper';
|
||||
import { Trivia } from './Games/Trivia';
|
||||
|
||||
export const PreStart = ({ gridLayout }: { gridLayout: GridLayout }) => {
|
||||
const { settings, randomizingPlayer, goToStart } = useGlobalSettings();
|
||||
|
||||
if (settings.preStartMode === PreStartMode.RandomKing) {
|
||||
if (!randomizingPlayer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<RandomKingSelectWrapper />
|
||||
<RandomKingPlayers gridLayout={gridLayout} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (settings.preStartMode === PreStartMode.FingerGame) {
|
||||
return <FingerGame />;
|
||||
}
|
||||
|
||||
if (settings.preStartMode === PreStartMode.Trivia) {
|
||||
return <Trivia />;
|
||||
}
|
||||
|
||||
goToStart();
|
||||
return null;
|
||||
};
|
||||
60
src/Components/PreStartGame/StartingPlayerCard.tsx
Normal file
60
src/Components/PreStartGame/StartingPlayerCard.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import { twc } from 'react-twc';
|
||||
import { baseColors } from '../../../tailwind.config';
|
||||
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
|
||||
import { Player, Rotation } from '../../Types/Player';
|
||||
import { PreStartMode } from '../../Types/Settings';
|
||||
import { Paragraph } from '../Misc/TextComponents';
|
||||
|
||||
export const DynamicText = twc.div`text-[8vmin] whitespace-nowrap`;
|
||||
|
||||
export const StartingPlayerCard = ({ player }: { player: Player }) => {
|
||||
const { settings, setPlaying, randomizingPlayer } = useGlobalSettings();
|
||||
|
||||
const calcTextRotation =
|
||||
player.settings.rotation === Rotation.SideFlipped ||
|
||||
player.settings.rotation === Rotation.Side
|
||||
? player.settings.rotation - 180
|
||||
: player.settings.rotation;
|
||||
|
||||
const calcRotation =
|
||||
player.settings.rotation === Rotation.SideFlipped ||
|
||||
player.settings.rotation === Rotation.Side
|
||||
? player.settings.rotation - 90
|
||||
: player.settings.rotation;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="z-20 flex absolute w-full h-full justify-center items-center select-none cursor-pointer webkit-user-select-none"
|
||||
style={{
|
||||
rotate: `${calcRotation}deg`,
|
||||
backgroundImage:
|
||||
!randomizingPlayer ||
|
||||
(settings.preStartMode !== PreStartMode.None &&
|
||||
settings.preStartMode !== PreStartMode.FingerGame)
|
||||
? `radial-gradient(circle at center, ${player.color}, ${baseColors.primary.main})`
|
||||
: 'none',
|
||||
}}
|
||||
onClick={() => {
|
||||
setPlaying(true);
|
||||
}}
|
||||
>
|
||||
<DynamicText
|
||||
style={{
|
||||
rotate: `${calcTextRotation}deg`,
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-col justify-center items-center">
|
||||
<Paragraph>👑</Paragraph>
|
||||
{(!randomizingPlayer ||
|
||||
(settings.preStartMode !== PreStartMode.None &&
|
||||
settings.preStartMode !== PreStartMode.FingerGame)) && (
|
||||
<>
|
||||
<Paragraph>You start!</Paragraph>
|
||||
<Paragraph className="text-xl">(Press to hide)</Paragraph>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</DynamicText>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,67 +1,116 @@
|
||||
import { useEffect } from 'react';
|
||||
import { twc } from 'react-twc';
|
||||
import { twGridTemplateAreas } from '../../../tailwind.config';
|
||||
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
|
||||
import { usePlayers } from '../../Hooks/usePlayers';
|
||||
import { Orientation } from '../../Types/Settings';
|
||||
import { Player } from '../Player/Player';
|
||||
import { twc } from 'react-twc';
|
||||
import { Orientation, PreStartMode } from '../../Types/Settings';
|
||||
import { Players } from '../Players/Players';
|
||||
import { PreStart } from '../PreStartGame/PreStart';
|
||||
|
||||
const MainWrapper = twc.div`w-[100dvmax] h-[100dvmin] overflow-hidden`;
|
||||
const MainWrapper = twc.div`w-[100dvmax] h-[100dvmin] overflow-hidden, setPlayers`;
|
||||
|
||||
type GridTemplateAreasKeys = keyof typeof twGridTemplateAreas;
|
||||
|
||||
export type GridLayout = `grid-areas-${GridTemplateAreasKeys}`;
|
||||
|
||||
export const Play = () => {
|
||||
const { players } = usePlayers();
|
||||
const { initialGameSettings } = useGlobalSettings();
|
||||
const { players, setPlayers } = usePlayers();
|
||||
const { initialGameSettings, playing, settings, preStartCompleted } =
|
||||
useGlobalSettings();
|
||||
|
||||
let Layout: JSX.Element;
|
||||
let gridLayout: GridLayout;
|
||||
switch (players.length) {
|
||||
case 1:
|
||||
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
||||
Layout = Player(players, 'grid-areas-onePlayerPortrait');
|
||||
gridLayout = 'grid-areas-onePlayerPortrait';
|
||||
}
|
||||
Layout = Player(players, 'grid-areas-onePlayerLandscape');
|
||||
gridLayout = 'grid-areas-onePlayerLandscape';
|
||||
break;
|
||||
case 2:
|
||||
switch (initialGameSettings?.orientation) {
|
||||
case Orientation.Portrait:
|
||||
Layout = Player(players, 'grid-areas-twoPlayersOppositePortrait');
|
||||
gridLayout = 'grid-areas-twoPlayersOppositePortrait';
|
||||
break;
|
||||
default:
|
||||
case Orientation.Landscape:
|
||||
Layout = Player(players, 'grid-areas-twoPlayersSameSideLandscape');
|
||||
gridLayout = 'grid-areas-twoPlayersSameSideLandscape';
|
||||
break;
|
||||
case Orientation.OppositeLandscape:
|
||||
Layout = Player(players, 'grid-areas-twoPlayersOppositeLandscape');
|
||||
gridLayout = 'grid-areas-twoPlayersOppositeLandscape';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
||||
Layout = Player(players, 'grid-areas-threePlayersSide');
|
||||
gridLayout = 'grid-areas-threePlayersSide';
|
||||
break;
|
||||
}
|
||||
Layout = Player(players, 'grid-areas-threePlayers');
|
||||
gridLayout = 'grid-areas-threePlayers';
|
||||
break;
|
||||
default:
|
||||
case 4:
|
||||
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
||||
Layout = Player(players, 'grid-areas-fourPlayerPortrait');
|
||||
gridLayout = 'grid-areas-fourPlayerPortrait';
|
||||
break;
|
||||
}
|
||||
Layout = Player(players, 'grid-areas-fourPlayer');
|
||||
gridLayout = 'grid-areas-fourPlayer';
|
||||
break;
|
||||
case 5:
|
||||
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
||||
Layout = Player(players, 'grid-areas-fivePlayersSide');
|
||||
gridLayout = 'grid-areas-fivePlayersSide';
|
||||
break;
|
||||
}
|
||||
Layout = Player(players, 'grid-areas-fivePlayers');
|
||||
gridLayout = 'grid-areas-fivePlayers';
|
||||
break;
|
||||
case 6:
|
||||
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
||||
Layout = Player(players, 'grid-areas-sixPlayersSide');
|
||||
gridLayout = 'grid-areas-sixPlayersSide';
|
||||
break;
|
||||
}
|
||||
Layout = Player(players, 'grid-areas-sixPlayers');
|
||||
gridLayout = 'grid-areas-sixPlayers';
|
||||
break;
|
||||
}
|
||||
|
||||
return <MainWrapper>{Layout}</MainWrapper>;
|
||||
useEffect(() => {
|
||||
if (settings.preStartMode !== PreStartMode.None) {
|
||||
return;
|
||||
}
|
||||
|
||||
const randomIndex = Math.floor(Math.random() * players.length);
|
||||
|
||||
setPlayers(
|
||||
players.map((p) =>
|
||||
p.index === randomIndex
|
||||
? {
|
||||
...p,
|
||||
isStartingPlayer: true,
|
||||
}
|
||||
: {
|
||||
...p,
|
||||
isStartingPlayer: false,
|
||||
}
|
||||
)
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
if (
|
||||
players.length > 1 &&
|
||||
!preStartCompleted &&
|
||||
settings.preStartMode !== PreStartMode.None &&
|
||||
!playing &&
|
||||
settings.showStartingPlayer
|
||||
) {
|
||||
return (
|
||||
<MainWrapper>
|
||||
<PreStart gridLayout={gridLayout} />
|
||||
</MainWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<MainWrapper>
|
||||
<Players gridLayout={gridLayout} />
|
||||
</MainWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
import { FormControlLabel, Radio, RadioGroup } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { theme } from '../../../Data/theme';
|
||||
import { twc } from 'react-twc';
|
||||
import {
|
||||
FivePlayers,
|
||||
FivePlayersSide,
|
||||
FourPlayers,
|
||||
FourPlayersSide,
|
||||
OnePlayerPortrait,
|
||||
SixPlayers,
|
||||
SixPlayersSide,
|
||||
ThreePlayers,
|
||||
ThreePlayersSide,
|
||||
TwoPlayersOppositeLandscape,
|
||||
TwoPlayersOppositePortrait,
|
||||
TwoPlayersSameSide,
|
||||
} from '../../../Icons/generated/Layouts';
|
||||
|
||||
import { twc } from 'react-twc';
|
||||
import OnePlayerLandscape from '../../../Icons/generated/Layouts/OnePlayerLandscape';
|
||||
import { Orientation } from '../../../Types/Settings';
|
||||
|
||||
const LayoutWrapper = twc.div`flex flex-row justify-between self-center`;
|
||||
const LayoutsRadioGroup = twc.div`flex flex-row justify-center items-center gap-4 self-center w-full`;
|
||||
|
||||
const Label = twc.label`flex flex-row relative max-w-[118px] hover:bg-primary-main hover:bg-opacity-5 rounded-2xl cursor-pointer`;
|
||||
|
||||
const Input = twc.input`peer sr-only`;
|
||||
|
||||
const IconWrapper = twc(
|
||||
'div'
|
||||
)`peer-checked:fill-primary-main fill-primary-dark max-h-[200px] h-[40vmin] w-[21vmin]`;
|
||||
|
||||
type LayoutOptionsProps = {
|
||||
numberOfPlayers: number;
|
||||
@@ -26,366 +32,212 @@ type LayoutOptionsProps = {
|
||||
onChange: (orientation: Orientation) => void;
|
||||
};
|
||||
|
||||
export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
||||
export const LayoutOptions = ({
|
||||
numberOfPlayers,
|
||||
selectedOrientation,
|
||||
onChange,
|
||||
}) => {
|
||||
const iconHeight = '30vmin';
|
||||
const iconWidth = '20vmin';
|
||||
}: LayoutOptionsProps) => {
|
||||
switch (numberOfPlayers) {
|
||||
case 1:
|
||||
return (
|
||||
<LayoutsRadioGroup>
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Landscape}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Landscape}`}
|
||||
checked={selectedOrientation === Orientation.Landscape}
|
||||
value={Orientation.Landscape}
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
<IconWrapper>
|
||||
<OnePlayerLandscape className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
|
||||
const renderLayoutOptions = () => {
|
||||
switch (numberOfPlayers) {
|
||||
case 1:
|
||||
return (
|
||||
<>
|
||||
<FormControlLabel
|
||||
value={Orientation.Landscape}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<OnePlayerLandscape
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<OnePlayerLandscape
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
/>
|
||||
<FormControlLabel
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Portrait}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Portrait}`}
|
||||
checked={selectedOrientation === Orientation.Portrait}
|
||||
value={Orientation.Portrait}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<OnePlayerPortrait
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<OnePlayerPortrait
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
case 2:
|
||||
return (
|
||||
<>
|
||||
<FormControlLabel
|
||||
<IconWrapper>
|
||||
<OnePlayerPortrait className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
</LayoutsRadioGroup>
|
||||
);
|
||||
case 2:
|
||||
return (
|
||||
<LayoutsRadioGroup>
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Landscape}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Landscape}`}
|
||||
checked={selectedOrientation === Orientation.Landscape}
|
||||
value={Orientation.Landscape}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<TwoPlayersSameSide
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<TwoPlayersSameSide
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
<FormControlLabel
|
||||
<IconWrapper>
|
||||
<TwoPlayersSameSide className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Portrait}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Portrait}`}
|
||||
checked={selectedOrientation === Orientation.Portrait}
|
||||
value={Orientation.Portrait}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<TwoPlayersOppositePortrait
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<TwoPlayersOppositePortrait
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
<FormControlLabel
|
||||
<IconWrapper>
|
||||
<TwoPlayersOppositePortrait className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
|
||||
<Label
|
||||
htmlFor={`${numberOfPlayers}p-${Orientation.OppositeLandscape}`}
|
||||
>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.OppositeLandscape}`}
|
||||
checked={selectedOrientation === Orientation.OppositeLandscape}
|
||||
value={Orientation.OppositeLandscape}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<TwoPlayersOppositeLandscape
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<TwoPlayersOppositeLandscape
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
case 3:
|
||||
return (
|
||||
<>
|
||||
<FormControlLabel
|
||||
<IconWrapper>
|
||||
<TwoPlayersOppositeLandscape className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
</LayoutsRadioGroup>
|
||||
);
|
||||
case 3:
|
||||
return (
|
||||
<LayoutsRadioGroup>
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Landscape}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Landscape}`}
|
||||
checked={selectedOrientation === Orientation.Landscape}
|
||||
value={Orientation.Landscape}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<ThreePlayers
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<ThreePlayers
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
<FormControlLabel
|
||||
<IconWrapper>
|
||||
<ThreePlayers className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Portrait}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Portrait}`}
|
||||
checked={selectedOrientation === Orientation.Portrait}
|
||||
value={Orientation.Portrait}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<ThreePlayersSide
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<ThreePlayersSide
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
<IconWrapper>
|
||||
<ThreePlayersSide className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
</LayoutsRadioGroup>
|
||||
);
|
||||
|
||||
case 4:
|
||||
return (
|
||||
<>
|
||||
<FormControlLabel
|
||||
case 4:
|
||||
return (
|
||||
<LayoutsRadioGroup>
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Landscape}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Landscape}`}
|
||||
checked={selectedOrientation === Orientation.Landscape}
|
||||
value={Orientation.Landscape}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<FourPlayers
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<FourPlayers
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
<FormControlLabel
|
||||
<IconWrapper>
|
||||
<FourPlayers className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Portrait}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Portrait}`}
|
||||
checked={selectedOrientation === Orientation.Portrait}
|
||||
value={Orientation.Portrait}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<FourPlayersSide
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<FourPlayersSide
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
<IconWrapper>
|
||||
<FourPlayersSide className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
</LayoutsRadioGroup>
|
||||
);
|
||||
|
||||
case 5:
|
||||
return (
|
||||
<>
|
||||
<FormControlLabel
|
||||
case 5:
|
||||
return (
|
||||
<LayoutsRadioGroup>
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Landscape}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Landscape}`}
|
||||
checked={selectedOrientation === Orientation.Landscape}
|
||||
value={Orientation.Landscape}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<FivePlayers
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<FivePlayers
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
{/* <FormControlLabel
|
||||
value={GridTemplateAreas.FivePlayersSide}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<FivePlayersSide
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<FivePlayersSide
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
/> */}
|
||||
</>
|
||||
);
|
||||
<IconWrapper>
|
||||
<FivePlayers className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
|
||||
case 6:
|
||||
return (
|
||||
<>
|
||||
<FormControlLabel
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Portrait}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Portrait}`}
|
||||
checked={selectedOrientation === Orientation.Portrait}
|
||||
value={Orientation.Portrait}
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
<IconWrapper>
|
||||
<FivePlayersSide className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
</LayoutsRadioGroup>
|
||||
);
|
||||
|
||||
case 6:
|
||||
return (
|
||||
<LayoutsRadioGroup>
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Landscape}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Landscape}`}
|
||||
checked={selectedOrientation === Orientation.Landscape}
|
||||
value={Orientation.Landscape}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<SixPlayers
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<SixPlayers
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
{/* <FormControlLabel
|
||||
value={GridTemplateAreas.SixPlayersSide}
|
||||
control={
|
||||
<Radio
|
||||
icon={
|
||||
<SixPlayersSide
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.secondary.main}
|
||||
/>
|
||||
}
|
||||
checkedIcon={
|
||||
<SixPlayersSide
|
||||
height={iconHeight}
|
||||
width={iconWidth}
|
||||
fill={theme.palette.primary.main}
|
||||
/>
|
||||
}
|
||||
TouchRippleProps={{ style: { display: 'none' } }}
|
||||
/>
|
||||
}
|
||||
label=""
|
||||
/> */}
|
||||
</>
|
||||
);
|
||||
<IconWrapper>
|
||||
<SixPlayers className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Portrait}`}>
|
||||
<Input
|
||||
type="radio"
|
||||
id={`${numberOfPlayers}p-${Orientation.Portrait}`}
|
||||
checked={selectedOrientation === Orientation.Portrait}
|
||||
value={Orientation.Portrait}
|
||||
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||
/>
|
||||
<IconWrapper>
|
||||
<SixPlayersSide className="w-full h-full" />
|
||||
</IconWrapper>
|
||||
</Label>
|
||||
</LayoutsRadioGroup>
|
||||
);
|
||||
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<RadioGroup
|
||||
row
|
||||
onChange={(_e, value) => {
|
||||
onChange(value as Orientation);
|
||||
}}
|
||||
value={selectedOrientation}
|
||||
style={{ justifyContent: 'center' }}
|
||||
>
|
||||
{renderLayoutOptions()}
|
||||
</RadioGroup>
|
||||
</LayoutWrapper>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,80 +1,51 @@
|
||||
import { Button, FormControl, FormLabel, Switch } from '@mui/material';
|
||||
import Slider from '@mui/material/Slider';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { twc } from 'react-twc';
|
||||
import { createInitialPlayers } from '../../../Data/getInitialPlayers';
|
||||
import { theme } from '../../../Data/theme';
|
||||
import { useAnalytics } from '../../../Hooks/useAnalytics';
|
||||
import { useGlobalSettings } from '../../../Hooks/useGlobalSettings';
|
||||
import { usePlayers } from '../../../Hooks/usePlayers';
|
||||
import { Cog, Info } from '../../../Icons/generated';
|
||||
import {
|
||||
GameFormat,
|
||||
InitialGameSettings,
|
||||
Orientation,
|
||||
PreStartMode,
|
||||
defaultInitialGameSettings,
|
||||
} from '../../../Types/Settings';
|
||||
import { InfoModal } from '../../Misc/InfoModal';
|
||||
import { SettingsModal } from '../../Misc/SettingsModal';
|
||||
import { SupportMe } from '../../Misc/SupportMe';
|
||||
|
||||
import { LayoutOptions } from './LayoutOptions';
|
||||
import { InfoDialog } from '../../Dialogs/InfoDialog';
|
||||
import { SettingsDialog } from '../../Dialogs/SettingsDialog';
|
||||
import { ToggleButton } from '../../Misc/ToggleButton';
|
||||
|
||||
const MainWrapper = twc.div`w-[100dvw] h-fit pb-14 overflow-hidden items-center flex flex-col`;
|
||||
const commanderSettings: Pick<
|
||||
InitialGameSettings,
|
||||
'numberOfPlayers' | 'startingLifeTotal' | 'orientation'
|
||||
> = {
|
||||
numberOfPlayers: 4,
|
||||
startingLifeTotal: 40,
|
||||
orientation: Orientation.Landscape,
|
||||
};
|
||||
|
||||
const StartButtonFooter = twc.div`fixed bottom-4 z-1`;
|
||||
const standardSettings: Pick<
|
||||
InitialGameSettings,
|
||||
'numberOfPlayers' | 'startingLifeTotal' | 'orientation'
|
||||
> = {
|
||||
numberOfPlayers: 2,
|
||||
startingLifeTotal: 20,
|
||||
orientation: Orientation.Landscape,
|
||||
};
|
||||
|
||||
const MainWrapper = twc.div`w-[100dvw] h-fit pb-24 overflow-hidden items-center flex flex-col min-[349px]:pb-10`;
|
||||
|
||||
const StartButtonFooter = twc.div`w-full max-w-[548px] fixed bottom-4 z-1 items-center flex flex-row flex-wrap px-4 z-10 gap-4`;
|
||||
|
||||
const SliderWrapper = twc.div`mx-8 relative`;
|
||||
|
||||
const ToggleButtonsWrapper = twc.div`flex flex-row justify-between items-center`;
|
||||
|
||||
const ToggleContainer = twc.div`flex flex-col items-center`;
|
||||
export const LabelText = twc.div`text-md text-text-primary font-medium`;
|
||||
|
||||
const playerMarks = [
|
||||
{
|
||||
value: 1,
|
||||
label: '1',
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: '2',
|
||||
},
|
||||
{
|
||||
value: 3,
|
||||
label: '3',
|
||||
},
|
||||
{
|
||||
value: 4,
|
||||
label: '4',
|
||||
},
|
||||
{
|
||||
value: 5,
|
||||
label: '5',
|
||||
},
|
||||
{
|
||||
value: 6,
|
||||
label: '6',
|
||||
},
|
||||
];
|
||||
|
||||
const healthMarks = [
|
||||
{
|
||||
value: 20,
|
||||
label: '20',
|
||||
},
|
||||
{
|
||||
value: 30,
|
||||
label: '30',
|
||||
},
|
||||
{
|
||||
value: 40,
|
||||
label: '40',
|
||||
},
|
||||
{
|
||||
value: 50,
|
||||
label: '50',
|
||||
},
|
||||
{
|
||||
value: 60,
|
||||
label: '60',
|
||||
},
|
||||
];
|
||||
let tracked = false;
|
||||
|
||||
const Start = () => {
|
||||
const { setPlayers } = usePlayers();
|
||||
@@ -87,27 +58,50 @@ const Start = () => {
|
||||
setInitialGameSettings,
|
||||
settings,
|
||||
isPWA,
|
||||
setRandomizingPlayer,
|
||||
version,
|
||||
setPlaying,
|
||||
savedGame,
|
||||
saveCurrentGame,
|
||||
} = useGlobalSettings();
|
||||
|
||||
const [openInfoModal, setOpenInfoModal] = useState(false);
|
||||
const [openSettingsModal, setOpenSettingsModal] = useState(false);
|
||||
const infoDialogRef = useRef<HTMLDialogElement | null>(null);
|
||||
const settingsDialogRef = useRef<HTMLDialogElement | null>(null);
|
||||
|
||||
const [playerOptions, setPlayerOptions] = useState<InitialGameSettings>(
|
||||
initialGameSettings || {
|
||||
numberOfPlayers: 4,
|
||||
startingLifeTotal: 40,
|
||||
useCommanderDamage: true,
|
||||
orientation: Orientation.Portrait,
|
||||
gameFormat: GameFormat.Commander,
|
||||
}
|
||||
initialGameSettings || defaultInitialGameSettings
|
||||
);
|
||||
|
||||
const doStartGame = () => {
|
||||
// Check for new version on mount
|
||||
useEffect(() => {
|
||||
if (!tracked) {
|
||||
version.checkForNewVersion('start_menu');
|
||||
|
||||
tracked = true;
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setInitialGameSettings(playerOptions);
|
||||
}, [playerOptions, setInitialGameSettings]);
|
||||
|
||||
useEffect(() => {
|
||||
setPlayerOptions({
|
||||
...playerOptions,
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [playerOptions.numberOfPlayers]);
|
||||
|
||||
const doStartNewGame = () => {
|
||||
if (!initialGameSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
analytics.trackEvent('game_started', { ...initialGameSettings });
|
||||
analytics.trackEvent('game_started', {
|
||||
...initialGameSettings,
|
||||
...settings,
|
||||
isPWA,
|
||||
});
|
||||
|
||||
try {
|
||||
if (settings.goFullscreenOnStart) {
|
||||
@@ -123,180 +117,234 @@ const Start = () => {
|
||||
|
||||
setInitialGameSettings(initialGameSettings);
|
||||
setPlayers(createInitialPlayers(initialGameSettings));
|
||||
setRandomizingPlayer(settings.preStartMode === PreStartMode.RandomKing);
|
||||
setShowPlay(true);
|
||||
localStorage.setItem('playing', 'false');
|
||||
localStorage.setItem('showPlay', 'true');
|
||||
setPlaying(false);
|
||||
tracked = false;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setInitialGameSettings(playerOptions);
|
||||
}, [playerOptions, setInitialGameSettings]);
|
||||
const doResumeGame = () => {
|
||||
if (!savedGame) {
|
||||
return;
|
||||
}
|
||||
|
||||
const valuetext = (value: number) => {
|
||||
return `${value}`;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setPlayerOptions({
|
||||
...playerOptions,
|
||||
analytics.trackEvent('game_resumed', {
|
||||
...initialGameSettings,
|
||||
...settings,
|
||||
isPWA,
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [playerOptions.numberOfPlayers]);
|
||||
|
||||
try {
|
||||
if (settings.goFullscreenOnStart) {
|
||||
fullscreen.enableFullscreen();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
if (settings.keepAwake && !wakeLock.active) {
|
||||
wakeLock.request();
|
||||
}
|
||||
|
||||
setInitialGameSettings(savedGame.initialGameSettings);
|
||||
setPlayers(savedGame.players);
|
||||
saveCurrentGame(null);
|
||||
setRandomizingPlayer(false);
|
||||
setShowPlay(true);
|
||||
setPlaying(true);
|
||||
tracked = false;
|
||||
};
|
||||
|
||||
const openInfo = () => {
|
||||
if (infoDialogRef.current) {
|
||||
infoDialogRef.current.showModal();
|
||||
}
|
||||
};
|
||||
|
||||
const openSettings = () => {
|
||||
if (settingsDialogRef.current) {
|
||||
settingsDialogRef.current.showModal();
|
||||
version.checkForNewVersion('settings');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<MainWrapper>
|
||||
<Info
|
||||
color={theme.palette.primary.light}
|
||||
size="2rem"
|
||||
style={{ position: 'absolute', top: '1rem', left: '1rem' }}
|
||||
onClick={() => {
|
||||
setOpenInfoModal(!openInfoModal);
|
||||
}}
|
||||
/>
|
||||
<>
|
||||
<InfoDialog dialogRef={infoDialogRef} />
|
||||
|
||||
<InfoModal
|
||||
closeModal={() => {
|
||||
setOpenInfoModal(false);
|
||||
}}
|
||||
isOpen={openInfoModal}
|
||||
/>
|
||||
<SettingsDialog dialogRef={settingsDialogRef} />
|
||||
|
||||
<SettingsModal
|
||||
closeModal={() => {
|
||||
setOpenSettingsModal(false);
|
||||
}}
|
||||
isOpen={openSettingsModal}
|
||||
/>
|
||||
|
||||
<SupportMe />
|
||||
|
||||
<h1 className="text-3xl block font-bold mt-6 mb-5 text-text-primary">
|
||||
Life Trinket
|
||||
</h1>
|
||||
|
||||
<FormControl focused={false} style={{ width: '80vw' }}>
|
||||
<FormLabel>Number of Players</FormLabel>
|
||||
<Slider
|
||||
title="Number of Players"
|
||||
max={6}
|
||||
min={1}
|
||||
aria-label="Custom marks"
|
||||
value={playerOptions?.numberOfPlayers ?? 4}
|
||||
getAriaValueText={valuetext}
|
||||
step={null}
|
||||
marks={playerMarks}
|
||||
onChange={(_e, value) => {
|
||||
setPlayerOptions({
|
||||
...playerOptions,
|
||||
numberOfPlayers: value as number,
|
||||
orientation: Orientation.Landscape,
|
||||
});
|
||||
<MainWrapper>
|
||||
<Info
|
||||
className="size-8 absolute top-4 left-4 text-primary-main"
|
||||
onClick={() => {
|
||||
openInfo();
|
||||
}}
|
||||
/>
|
||||
<FormLabel className="mt-[0.7rem]">Starting Health</FormLabel>
|
||||
<Slider
|
||||
title="Starting Health"
|
||||
max={60}
|
||||
min={20}
|
||||
aria-label="Custom marks"
|
||||
value={playerOptions?.startingLifeTotal ?? 40}
|
||||
getAriaValueText={valuetext}
|
||||
step={10}
|
||||
marks={healthMarks}
|
||||
onChange={(_e, value) =>
|
||||
setPlayerOptions({
|
||||
...playerOptions,
|
||||
startingLifeTotal: value as number,
|
||||
orientation: Orientation.Landscape,
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
||||
<ToggleButtonsWrapper className="mt-4">
|
||||
<ToggleContainer>
|
||||
<FormLabel>Commander</FormLabel>
|
||||
<Switch
|
||||
checked={
|
||||
playerOptions.useCommanderDamage ??
|
||||
initialGameSettings?.useCommanderDamage ??
|
||||
true
|
||||
}
|
||||
onChange={(_e, value) => {
|
||||
if (value) {
|
||||
<h1 className="relative flex flex-col text-3xl font-bold mt-6 mb-6 text-text-primary justify-center items-center">
|
||||
Life Trinket
|
||||
<div className="h-[1px] w-[120%] bg-common-white opacity-50" />
|
||||
<div className="flex absolute text-xs font-medium -bottom-4">
|
||||
v{version.installedVersion}
|
||||
</div>
|
||||
</h1>
|
||||
|
||||
<div className="overflow-hidden items-center flex flex-col max-w-[548px] w-full mb-8 px-4">
|
||||
<div className="w-full">
|
||||
<ToggleButtonsWrapper className="mt-4">
|
||||
<ToggleButton
|
||||
label="Commander"
|
||||
checked={
|
||||
playerOptions.useCommanderDamage ??
|
||||
initialGameSettings?.useCommanderDamage ??
|
||||
true
|
||||
}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
setPlayerOptions({
|
||||
...playerOptions,
|
||||
useCommanderDamage: e.target.checked,
|
||||
...commanderSettings,
|
||||
});
|
||||
return;
|
||||
}
|
||||
setPlayerOptions({
|
||||
...playerOptions,
|
||||
useCommanderDamage: value,
|
||||
numberOfPlayers: 4,
|
||||
startingLifeTotal: 40,
|
||||
useCommanderDamage: e.target.checked,
|
||||
...standardSettings,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="flex flex-nowrap text-nowrap relative justify-center items-start">
|
||||
<button
|
||||
className="flex justify-center self-center items-center mt-1 mb-1 bg-primary-main px-3 py-2 rounded-md transition-colors duration-200 ease-in-out shadow-[1px_2px_4px_0px_rgba(0,0,0,0.3)] hover:bg-primary-dark"
|
||||
onClick={openSettings}
|
||||
>
|
||||
<span className="text-sm flex flex-row items-center text-text-primary">
|
||||
<Cog />
|
||||
Game Settings
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div
|
||||
data-not-latest-version={
|
||||
!version.isLatest && !!version.remoteVersion
|
||||
}
|
||||
className="absolute flex justify-center text-text-primary text-xxs -bottom-5 bg-primary-dark px-2 rounded-md
|
||||
opacity-0 transition-all duration-200 delay-500
|
||||
data-[not-latest-version=true]:opacity-100
|
||||
"
|
||||
>
|
||||
<div className="absolute bg-primary-dark rotate-45 size-2 -top-[2px] z-0" />
|
||||
<span className="z-10">
|
||||
v{version.remoteVersion} available!
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</ToggleButtonsWrapper>
|
||||
<LabelText className="mt-4">Number of Players</LabelText>
|
||||
<SliderWrapper>
|
||||
<input
|
||||
className="accent-primary-main text-primary-dark w-full h-3 rounded-lg cursor-pointer"
|
||||
title="Number of Players"
|
||||
type="range"
|
||||
max={6}
|
||||
min={1}
|
||||
value={playerOptions?.numberOfPlayers ?? 4}
|
||||
onChange={(e) => {
|
||||
setPlayerOptions({
|
||||
...playerOptions,
|
||||
numberOfPlayers: Number.parseInt(e.target.value),
|
||||
orientation: Orientation.Landscape,
|
||||
});
|
||||
return;
|
||||
}}
|
||||
/>
|
||||
<div className="flex w-full justify-between px-1 text-text-primary pointer-events-none">
|
||||
<div>1</div>
|
||||
<div>2</div>
|
||||
<div>3</div>
|
||||
<div>4</div>
|
||||
<div>5</div>
|
||||
<div>6</div>
|
||||
</div>
|
||||
</SliderWrapper>
|
||||
|
||||
<LabelText className="mt-4">Starting Health</LabelText>
|
||||
<SliderWrapper>
|
||||
<input
|
||||
className="accent-primary-main text-primary-dark w-full h-3 rounded-lg cursor-pointer"
|
||||
title="Starting Health"
|
||||
type="range"
|
||||
max={60}
|
||||
min={20}
|
||||
aria-label="Custom marks"
|
||||
value={playerOptions?.startingLifeTotal ?? 40}
|
||||
step={10}
|
||||
onChange={(e) =>
|
||||
setPlayerOptions({
|
||||
...playerOptions,
|
||||
startingLifeTotal: Number.parseInt(e.target.value),
|
||||
orientation: Orientation.Landscape,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<div className="flex w-full justify-between px-1 text-text-primary pointer-events-none">
|
||||
<div>20</div>
|
||||
<div>30</div>
|
||||
<div>40</div>
|
||||
<div>50</div>
|
||||
<div>60</div>
|
||||
</div>
|
||||
</SliderWrapper>
|
||||
|
||||
<LabelText className="mt-4">Layout</LabelText>
|
||||
<LayoutOptions
|
||||
numberOfPlayers={playerOptions.numberOfPlayers}
|
||||
selectedOrientation={playerOptions.orientation}
|
||||
onChange={(orientation) => {
|
||||
setPlayerOptions({
|
||||
...playerOptions,
|
||||
useCommanderDamage: value,
|
||||
numberOfPlayers: 2,
|
||||
startingLifeTotal: 20,
|
||||
orientation: Orientation.Landscape,
|
||||
orientation,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</ToggleContainer>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ height: '2rem' }}
|
||||
onClick={() => {
|
||||
setOpenSettingsModal(true);
|
||||
}}
|
||||
</div>
|
||||
{!isPWA && (
|
||||
<p className="text-center text-xs text-text-primary w-11/12 mt-4">
|
||||
If you're on iOS, this page works better if you{' '}
|
||||
<strong>hide the toolbar</strong> or{' '}
|
||||
<strong>add the app to your home screen</strong>.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<StartButtonFooter>
|
||||
<button
|
||||
className="flex flex-grow basis-0 justify-center self-center items-center bg-primary-main px-3 py-2 rounded-md text-text-primary min-w-[150px] duration-200 ease-in-out shadow-[1px_2px_4px_0px_rgba(0,0,0,0.3)] hover:bg-primary-dark"
|
||||
onClick={doStartNewGame}
|
||||
>
|
||||
<Cog /> Other settings
|
||||
</Button>
|
||||
</ToggleButtonsWrapper>
|
||||
NEW GAME
|
||||
</button>
|
||||
|
||||
<FormLabel>Layout</FormLabel>
|
||||
{/* <LayoutOptions
|
||||
numberOfPlayers={playerOptions.numberOfPlayers}
|
||||
gridAreas={playerOptions.gridAreas}
|
||||
onChange={(gridAreas) =>
|
||||
setPlayerOptions({
|
||||
...playerOptions,
|
||||
gridAreas,
|
||||
//TODO fix the layout selection
|
||||
orientation: Orientation.Portrait,
|
||||
})
|
||||
}
|
||||
/> */}
|
||||
<LayoutOptions
|
||||
numberOfPlayers={playerOptions.numberOfPlayers}
|
||||
selectedOrientation={playerOptions.orientation}
|
||||
onChange={(orientation) => {
|
||||
setPlayerOptions({
|
||||
...playerOptions,
|
||||
orientation,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
{!isPWA && (
|
||||
<p className="text-center, max-w-[75%] text-xs text-text-primary">
|
||||
If you're on iOS, this page works better if you{' '}
|
||||
<strong>hide the toolbar</strong> or{' '}
|
||||
<strong>add the app to your home screen</strong>.
|
||||
</p>
|
||||
)}
|
||||
|
||||
<StartButtonFooter>
|
||||
<Button
|
||||
size="large"
|
||||
variant="contained"
|
||||
onClick={doStartGame}
|
||||
style={{ width: '90dvw' }}
|
||||
>
|
||||
START GAME
|
||||
</Button>
|
||||
</StartButtonFooter>
|
||||
</MainWrapper>
|
||||
{savedGame && (
|
||||
<button
|
||||
className="flex flex-grow basis-0 justify-center self-center items-center bg-secondary-main px-3 py-2 rounded-md text-text-primary min-w-[150px]
|
||||
|
||||
duration-200 ease-in-out shadow-[1px_2px_4px_0px_rgba(0,0,0,0.3)] hover:bg-secondary-dark"
|
||||
onClick={doResumeGame}
|
||||
>
|
||||
RESUME
|
||||
<span className="text-xs">
|
||||
({savedGame.players.length}
|
||||
{savedGame.players.length > 1 ? 'players' : 'player'})
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
</StartButtonFooter>
|
||||
</MainWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
import { createContext } from 'react';
|
||||
import { InitialGameSettings, Settings } from '../Types/Settings';
|
||||
import { Player } from '../Types/Player';
|
||||
|
||||
type Version = {
|
||||
installedVersion: string;
|
||||
isLatest: boolean;
|
||||
checkForNewVersion: (source: 'settings' | 'start_menu') => Promise<void>;
|
||||
remoteVersion?: string;
|
||||
};
|
||||
|
||||
export type SavedGame = {
|
||||
initialGameSettings: InitialGameSettings;
|
||||
players: Player[];
|
||||
} | null;
|
||||
|
||||
export type GlobalSettingsContextType = {
|
||||
fullscreen: {
|
||||
@@ -18,11 +31,20 @@ export type GlobalSettingsContextType = {
|
||||
goToStart: () => void;
|
||||
showPlay: boolean;
|
||||
setShowPlay: (showPlay: boolean) => void;
|
||||
initialGameSettings: InitialGameSettings | null;
|
||||
initialGameSettings: InitialGameSettings;
|
||||
setInitialGameSettings: (initialGameSettings: InitialGameSettings) => void;
|
||||
settings: Settings;
|
||||
setSettings: (settings: Settings) => void;
|
||||
playing: boolean;
|
||||
setPlaying: (playing: boolean) => void;
|
||||
randomizingPlayer: boolean;
|
||||
setRandomizingPlayer: (stopRandom: boolean) => void;
|
||||
isPWA: boolean;
|
||||
preStartCompleted: boolean;
|
||||
setPreStartCompleted: (completed: boolean) => void;
|
||||
version: Version;
|
||||
savedGame: SavedGame;
|
||||
saveCurrentGame: (currentGame: SavedGame) => void;
|
||||
};
|
||||
|
||||
export const GlobalSettingsContext =
|
||||
|
||||
@@ -7,6 +7,8 @@ export type PlayersContextType = {
|
||||
updatePlayer: (updatedPlayer: Player) => void;
|
||||
updateLifeTotal: (player: Player, updatedLifeTotal: number) => number;
|
||||
resetCurrentGame: () => void;
|
||||
startingPlayerIndex: number;
|
||||
setStartingPlayerIndex: (index: number) => void;
|
||||
};
|
||||
|
||||
export const PlayersContext = createContext<PlayersContextType | null>(null);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Player, Rotation } from '../Types/Player';
|
||||
import { InitialGameSettings, Orientation } from '../Types/Settings';
|
||||
|
||||
const presetColors = [
|
||||
export const presetColors = [
|
||||
'#F06292', // Light Pink
|
||||
'#4DB6AC', // Teal
|
||||
'#FFA726', // Orange
|
||||
@@ -127,15 +127,15 @@ const getOrientationRotations = (
|
||||
case Orientation.Portrait:
|
||||
switch (index) {
|
||||
case 0:
|
||||
return Rotation.Side;
|
||||
return Rotation.Flipped;
|
||||
case 1:
|
||||
return Rotation.Side;
|
||||
return Rotation.Flipped;
|
||||
case 2:
|
||||
return Rotation.SideFlipped;
|
||||
return Rotation.Side;
|
||||
case 3:
|
||||
return Rotation.SideFlipped;
|
||||
return Rotation.Normal;
|
||||
case 4:
|
||||
return Rotation.SideFlipped;
|
||||
return Rotation.Normal;
|
||||
default:
|
||||
return Rotation.Normal;
|
||||
}
|
||||
@@ -163,17 +163,17 @@ const getOrientationRotations = (
|
||||
case Orientation.Portrait:
|
||||
switch (index) {
|
||||
case 0:
|
||||
return Rotation.Side;
|
||||
return Rotation.SideFlipped;
|
||||
case 1:
|
||||
return Rotation.Side;
|
||||
return Rotation.Flipped;
|
||||
case 2:
|
||||
return Rotation.Side;
|
||||
return Rotation.Flipped;
|
||||
case 3:
|
||||
return Rotation.SideFlipped;
|
||||
return Rotation.Side;
|
||||
case 4:
|
||||
return Rotation.SideFlipped;
|
||||
return Rotation.Normal;
|
||||
case 5:
|
||||
return Rotation.SideFlipped;
|
||||
return Rotation.Normal;
|
||||
default:
|
||||
return Rotation.Normal;
|
||||
}
|
||||
@@ -191,10 +191,8 @@ export const createInitialPlayers = ({
|
||||
}: InitialGameSettings): Player[] => {
|
||||
const players: Player[] = [];
|
||||
const availableColors = [...presetColors]; // Create a copy of the colors array
|
||||
const firstPlayerIndex = Math.floor(Math.random() * numberOfPlayers);
|
||||
|
||||
for (let i = 0; i <= numberOfPlayers - 1; i++) {
|
||||
const isStartingPlayer = i === firstPlayerIndex;
|
||||
const colorIndex = Math.floor(Math.random() * availableColors.length);
|
||||
const color = availableColors[colorIndex];
|
||||
|
||||
@@ -224,11 +222,11 @@ export const createInitialPlayers = ({
|
||||
usePoison: false,
|
||||
rotation,
|
||||
},
|
||||
isStartingPlayer,
|
||||
showStartingPlayer: isStartingPlayer,
|
||||
extraCounters: [],
|
||||
commanderDamage,
|
||||
hasLost: false,
|
||||
isStartingPlayer: false,
|
||||
isSide: rotation === Rotation.Side || rotation === Rotation.SideFlipped,
|
||||
};
|
||||
|
||||
players.push(player);
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
import { createTheme } from '@mui/material';
|
||||
import resolveConfig from 'tailwindcss/resolveConfig';
|
||||
import tailwindConfig from '../../tailwind.config';
|
||||
|
||||
//TODO Create provider for this
|
||||
const fullConfig = resolveConfig(tailwindConfig);
|
||||
|
||||
const { primary, secondary, background, text, action, common } =
|
||||
fullConfig.theme.colors;
|
||||
|
||||
export const theme = createTheme({
|
||||
palette: {
|
||||
primary,
|
||||
secondary,
|
||||
background,
|
||||
text,
|
||||
action,
|
||||
common,
|
||||
},
|
||||
components: {
|
||||
MuiFormLabel: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
fontSize: '1rem',
|
||||
color: text.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiSlider: {
|
||||
styleOverrides: {
|
||||
markLabel: {
|
||||
fontSize: '1rem',
|
||||
color: text.primary,
|
||||
},
|
||||
valueLabel: {
|
||||
display: 'none',
|
||||
color: text.primary,
|
||||
background: secondary.main,
|
||||
},
|
||||
track: {
|
||||
height: '0.7rem',
|
||||
},
|
||||
rail: {
|
||||
height: '0.7rem',
|
||||
},
|
||||
mark: {
|
||||
width: '0.5rem',
|
||||
height: '0.5rem',
|
||||
borderRadius: '50%',
|
||||
display: 'none',
|
||||
},
|
||||
thumb: {
|
||||
width: '1.3rem',
|
||||
height: '1.3rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiFormControlLabel: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
margin: '0',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiFormGroup: {
|
||||
styleOverrides: {
|
||||
root: {},
|
||||
},
|
||||
},
|
||||
MuiDrawer: {
|
||||
styleOverrides: {
|
||||
paper: {
|
||||
top: '1rem',
|
||||
background: background.default,
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiBackdrop: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: background.backdrop,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiButton: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
textTransform: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiSwitch: {
|
||||
styleOverrides: {
|
||||
colorPrimary: {
|
||||
color: action.disabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -18,7 +18,17 @@ export const useAnalytics = () => {
|
||||
eventName: string,
|
||||
eventParams?: { [key: string]: unknown }
|
||||
) => {
|
||||
logEvent(analytics, eventName, eventParams);
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.info('Event not tracked:', { eventName, eventParams });
|
||||
return;
|
||||
}
|
||||
|
||||
const paramsWithVersion = {
|
||||
...eventParams,
|
||||
app_version: import.meta.env.VITE_APP_VERSION,
|
||||
};
|
||||
|
||||
logEvent(analytics, eventName, paramsWithVersion);
|
||||
};
|
||||
|
||||
return { trackEvent };
|
||||
|
||||
52
src/Hooks/useOrientation.ts
Normal file
52
src/Hooks/useOrientation.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export interface OrientationState {
|
||||
angle: number;
|
||||
type: string;
|
||||
}
|
||||
|
||||
const defaultState: OrientationState = {
|
||||
angle: 0,
|
||||
type: 'landscape-primary',
|
||||
};
|
||||
|
||||
export default function useOrientation(
|
||||
initialState: OrientationState = defaultState
|
||||
) {
|
||||
const [state, setState] = useState(initialState);
|
||||
const [isLandscape, setIsLandscape] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const screen = window.screen;
|
||||
let mounted = true;
|
||||
|
||||
const onChange = () => {
|
||||
if (mounted) {
|
||||
const { orientation } = screen;
|
||||
|
||||
if (orientation) {
|
||||
const { angle, type } = orientation;
|
||||
setState({ angle, type });
|
||||
if (type.includes('landscape')) {
|
||||
setIsLandscape(true);
|
||||
} else if (type.includes('portrait')) {
|
||||
setIsLandscape(false);
|
||||
}
|
||||
} else if (window.orientation !== undefined) {
|
||||
setState({
|
||||
angle:
|
||||
typeof window.orientation === 'number' ? window.orientation : 0,
|
||||
type: '',
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
onChange();
|
||||
|
||||
return () => {
|
||||
mounted = false;
|
||||
};
|
||||
}, [isLandscape]);
|
||||
|
||||
return { state, isLandscape };
|
||||
}
|
||||
@@ -22,7 +22,7 @@ const Cog = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M80.7 1c-4.6 1.4-9.4 5.7-11.6 10.3-1.6 3.4-2.1 6.2-2.1 12.8v8.5l-5.7-5.4C48.2 15 38.1 15 26.3 27.1 14.9 38.9 15.2 49.2 27.4 61l5.7 5.5-10.1.6c-9 .5-10.4.8-14.2 3.5-2.3 1.6-5.2 4.9-6.6 7.4-2.1 4-2.3 5.5-2 14 .4 11.1 2.4 15.4 9 19.8 3.5 2.2 5.3 2.7 13.4 3l9.4.4-5.2 5.7c-11.6 12.7-11.8 22.4-.5 34 5.7 5.8 11.5 9 16.3 9.1 7 0 9.7-1.3 16.9-8.2l7.3-6.8.4 9.9c.3 8.6.7 10.3 3 13.8 1.5 2.2 4.4 5.1 6.5 6.4 3.4 2.1 5 2.4 14.3 2.4s10.9-.3 14.3-2.4c2.1-1.3 5-4.1 6.5-6.3 2.3-3.5 2.7-5.3 3-13.5l.4-9.5 4.2 4c7.3 6.9 11.1 9.2 16.4 9.9 7 .8 11.7-1.1 18.6-7.6 12.7-12.1 12.9-22.2.5-34.7l-6.1-6.2 9.9-.4c8.9-.3 10.2-.6 14.2-3.3 6.2-4.2 8.5-9.1 8.9-19.2.5-10.7-2.4-17.7-9-21.9-3.8-2.5-5.5-2.9-14.2-3.2l-9.8-.4 6.1-6.2c12.2-12.4 12.2-22.4 0-34.3-11.6-11.2-20.5-11.2-33.4.2l-6.3 5.5-.4-9.4c-.3-8.1-.8-9.9-3-13.4-4.4-6.6-8.7-8.6-19.3-8.9-4.9-.1-10.3.2-11.8.7zm24.4 59.9c5.9 3 12.1 9.2 15 14.9 2.1 4 2.4 6.1 2.4 14.7 0 8.5-.3 10.7-2.3 14.5-3.2 6.1-8.7 11.6-14.7 14.8-4.5 2.4-6.1 2.7-15 2.7s-10.5-.3-15-2.7c-6-3.2-11.5-8.7-14.7-14.8-3.1-6-3.7-18.6-1.3-25.9 2.7-8.3 12.1-17.4 20.6-20 6-1.8 19.9-.8 25 1.8z" />
|
||||
<path d="M80.7 1c-4.6 1.4-9.4 5.7-11.6 10.3-1.6 3.4-2.1 6.2-2.1 12.8v8.5l-5.7-5.4C48.2 15 38.1 15 26.3 27.1 14.9 38.9 15.2 49.2 27.4 61l5.7 5.5-10.1.6c-9 .5-10.4.8-14.2 3.5-2.3 1.6-5.2 4.9-6.6 7.4-2.1 4-2.3 5.5-2 14 .4 11.1 2.4 15.4 9 19.8 3.5 2.2 5.3 2.7 13.4 3l9.4.4-5.2 5.7c-11.6 12.7-11.8 22.4-.5 34 5.7 5.8 11.5 9 16.3 9.1 7 0 9.7-1.3 16.9-8.2l7.3-6.8.4 9.9c.3 8.6.7 10.3 3 13.8 1.5 2.2 4.4 5.1 6.5 6.4 3.4 2.1 5 2.4 14.3 2.4s10.9-.3 14.3-2.4c2.1-1.3 5-4.1 6.5-6.3 2.3-3.5 2.7-5.3 3-13.5l.4-9.5 4.2 4c7.3 6.9 11.1 9.2 16.4 9.9 7 .8 11.7-1.1 18.6-7.6 12.7-12.1 12.9-22.2.5-34.7l-6.1-6.2 9.9-.4c8.9-.3 10.2-.6 14.2-3.3 6.2-4.2 8.5-9.1 8.9-19.2.5-10.7-2.4-17.7-9-21.9-3.8-2.5-5.5-2.9-14.2-3.2l-9.8-.4 6.1-6.2c12.2-12.4 12.2-22.4 0-34.3-11.6-11.2-20.5-11.2-33.4.2l-6.3 5.5-.4-9.4c-.3-8.1-.8-9.9-3-13.4-4.4-6.6-8.7-8.6-19.3-8.9-4.9-.1-10.3.2-11.8.7m24.4 59.9c5.9 3 12.1 9.2 15 14.9 2.1 4 2.4 6.1 2.4 14.7 0 8.5-.3 10.7-2.3 14.5-3.2 6.1-8.7 11.6-14.7 14.8-4.5 2.4-6.1 2.7-15 2.7s-10.5-.3-15-2.7c-6-3.2-11.5-8.7-14.7-14.8-3.1-6-3.7-18.6-1.3-25.9 2.7-8.3 12.1-17.4 20.6-20 6-1.8 19.9-.8 25 1.8" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ const CommanderTax = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M256 23.9c-1.9.4-5.5 1.8-7.9 3.2-5.1 2.8-130.3 133.3-135.8 141.5-5.4 8.1-7.5 14.7-8.1 25.5-.5 11.3.7 17.6 5.2 26.9 3.7 7.8 13.8 18.4 21.1 22.1 2.8 1.4 20.4 7.5 39.3 13.4 18.8 6 33.7 11.2 33 11.6-.7.3-24.2 9.3-52.3 19.9-32.8 12.4-52.9 20.5-56.3 22.7-6 4-12 10.7-15.6 17.4-1.5 2.7-9.7 31.1-20.6 71.5C41.3 461.3 39.9 467 40.3 473c.9 12.3 7.2 21.7 18.5 27.2l6.7 3.3H262c190.8 0 196.7-.1 202-1.9 7.5-2.6 15.9-11 18.8-18.9 4.1-10.8 3.9-11.8-15.3-81.5-9.6-35-18.7-66.6-20.2-70.1-3.4-8.3-13-18.6-21-22.8-3.2-1.7-27.9-11.5-55-21.9-27.1-10.4-48.9-19.2-48.5-19.5.4-.4 15.1-5.3 32.7-10.8 17.6-5.6 34.5-11.4 37.5-12.9 11.4-5.6 23-20.5 25.9-33.2 2.7-11.5.7-27.5-4.7-37.3-3.6-6.7-5.2-8.5-73.7-80.2-45.1-47.2-61.4-63.7-65.1-65.7-5.3-2.8-13.7-4.1-19.4-2.9zm32.5 97.6c9.3 1.8 31.6 8.3 32.9 9.5 1.6 1.5-12.1 43.6-18.3 56.5-6 12.3-16.1 27.7-22.6 34.7-7.3 7.7-16.8 10.3-26.6 7.5-7.3-2.2-11.4-5.8-19.6-17.4-16.1-22.8-22.4-36.2-29.9-64.3-2.4-9-4.1-16.7-3.6-17 2.3-2.1 30.7-9.3 44.7-11.4 6.3-.9 35.2.3 43 1.9zM325.1 225l62.1-31.1-.7 3.3c-1 4.7-2.1 6.4-5.8 9.1-1.7 1.3-28.8 16-60.1 32.7-51.8 27.7-57.1 30.2-59.6 29.3-5.3-2-114.5-60.6-116.9-62.7-2.5-2.2-5.1-7.4-5.1-10.1 0-1.1 18.7 7.8 62 29.5l61.9 31 62.2-31zm-194 131.4c1.1 3 .1 11.2-8.7 69.9-5.4 36.7-10.2 66.3-10.5 65.9-.4-.4-3-8-5.8-16.9l-5.1-16.2 11-57.8c6.1-31.8 11.4-58.5 11.6-59.3.5-1.4 4.6 6.4 7.5 14.4zm280.8 44.2 11.2 58.1-5.2 16.6c-2.9 9.2-5.6 16.4-6 15.9-.3-.4-5-30.4-10.4-66.7l-9.8-66 3.9-8.7c2.2-4.8 4.2-8.4 4.5-8 .4.4 5.7 26.8 11.8 58.8z" />
|
||||
<path d="M256 23.9c-1.9.4-5.5 1.8-7.9 3.2-5.1 2.8-130.3 133.3-135.8 141.5-5.4 8.1-7.5 14.7-8.1 25.5-.5 11.3.7 17.6 5.2 26.9 3.7 7.8 13.8 18.4 21.1 22.1 2.8 1.4 20.4 7.5 39.3 13.4 18.8 6 33.7 11.2 33 11.6-.7.3-24.2 9.3-52.3 19.9-32.8 12.4-52.9 20.5-56.3 22.7-6 4-12 10.7-15.6 17.4-1.5 2.7-9.7 31.1-20.6 71.5C41.3 461.3 39.9 467 40.3 473c.9 12.3 7.2 21.7 18.5 27.2l6.7 3.3H262c190.8 0 196.7-.1 202-1.9 7.5-2.6 15.9-11 18.8-18.9 4.1-10.8 3.9-11.8-15.3-81.5-9.6-35-18.7-66.6-20.2-70.1-3.4-8.3-13-18.6-21-22.8-3.2-1.7-27.9-11.5-55-21.9s-48.9-19.2-48.5-19.5c.4-.4 15.1-5.3 32.7-10.8 17.6-5.6 34.5-11.4 37.5-12.9 11.4-5.6 23-20.5 25.9-33.2 2.7-11.5.7-27.5-4.7-37.3-3.6-6.7-5.2-8.5-73.7-80.2-45.1-47.2-61.4-63.7-65.1-65.7-5.3-2.8-13.7-4.1-19.4-2.9m32.5 97.6c9.3 1.8 31.6 8.3 32.9 9.5 1.6 1.5-12.1 43.6-18.3 56.5-6 12.3-16.1 27.7-22.6 34.7-7.3 7.7-16.8 10.3-26.6 7.5-7.3-2.2-11.4-5.8-19.6-17.4-16.1-22.8-22.4-36.2-29.9-64.3-2.4-9-4.1-16.7-3.6-17 2.3-2.1 30.7-9.3 44.7-11.4 6.3-.9 35.2.3 43 1.9M325.1 225l62.1-31.1-.7 3.3c-1 4.7-2.1 6.4-5.8 9.1-1.7 1.3-28.8 16-60.1 32.7-51.8 27.7-57.1 30.2-59.6 29.3-5.3-2-114.5-60.6-116.9-62.7-2.5-2.2-5.1-7.4-5.1-10.1 0-1.1 18.7 7.8 62 29.5l61.9 31zm-194 131.4c1.1 3 .1 11.2-8.7 69.9-5.4 36.7-10.2 66.3-10.5 65.9-.4-.4-3-8-5.8-16.9l-5.1-16.2 11-57.8c6.1-31.8 11.4-58.5 11.6-59.3.5-1.4 4.6 6.4 7.5 14.4m280.8 44.2 11.2 58.1-5.2 16.6c-2.9 9.2-5.6 16.4-6 15.9-.3-.4-5-30.4-10.4-66.7l-9.8-66 3.9-8.7c2.2-4.8 4.2-8.4 4.5-8 .4.4 5.7 26.8 11.8 58.8" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ const Cross = ({
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M85.8 34.4c-5.3 1.9-9.2 5.3-30 26.3C35.9 80.8 33 84.8 33 93c0 2.5.9 6.4 1.9 8.6 1.2 2.7 27.7 32.1 74.5 82.7 39.9 43.3 72.6 79.1 72.6 79.7 0 .6-32.3 35.2-71.7 77-48.5 51.3-72.7 77.7-74.6 81.1-3.4 6.4-3.5 11.7-.3 18.4 3.3 6.8 42 45.5 48.6 48.4 6.4 2.9 12.7 2.7 18.8-.7 3.3-1.7 31.6-27.6 81.3-74.5 42-39.4 76.7-71.6 77.1-71.5.4.2 35.5 32.5 77.9 71.8 42.4 39.3 79.2 72.7 81.8 74.2 3.2 1.9 6 2.8 9.1 2.8 10.1 0 10.9-.6 34.9-24.3 14.2-14.1 23-23.7 24.2-26.2 2.4-5.1 2.4-12.8 0-18.1-1.2-2.6-27.1-30.8-74.5-81.2-40-42.5-72.6-77.6-72.4-78.1.2-.4 32.5-34.7 71.8-76.1 39.3-41.4 72.5-76.7 73.8-78.4 4.5-6.3 4.4-17.9-.1-24.2-5.1-7.2-43.3-46.7-46.9-48.5-2.1-1.1-5.8-2.2-8.2-2.5-9.6-1.4-5.3-5.2-158.3 138.2L262.2 183l-78.4-73.1c-49.6-46.5-79.8-73.9-82.3-75-4.7-2.2-10.5-2.3-15.7-.5z"
|
||||
d="M85.8 34.4c-5.3 1.9-9.2 5.3-30 26.3C35.9 80.8 33 84.8 33 93c0 2.5.9 6.4 1.9 8.6 1.2 2.7 27.7 32.1 74.5 82.7 39.9 43.3 72.6 79.1 72.6 79.7s-32.3 35.2-71.7 77c-48.5 51.3-72.7 77.7-74.6 81.1-3.4 6.4-3.5 11.7-.3 18.4 3.3 6.8 42 45.5 48.6 48.4 6.4 2.9 12.7 2.7 18.8-.7 3.3-1.7 31.6-27.6 81.3-74.5 42-39.4 76.7-71.6 77.1-71.5.4.2 35.5 32.5 77.9 71.8s79.2 72.7 81.8 74.2c3.2 1.9 6 2.8 9.1 2.8 10.1 0 10.9-.6 34.9-24.3 14.2-14.1 23-23.7 24.2-26.2 2.4-5.1 2.4-12.8 0-18.1-1.2-2.6-27.1-30.8-74.5-81.2-40-42.5-72.6-77.6-72.4-78.1.2-.4 32.5-34.7 71.8-76.1s72.5-76.7 73.8-78.4c4.5-6.3 4.4-17.9-.1-24.2-5.1-7.2-43.3-46.7-46.9-48.5-2.1-1.1-5.8-2.2-8.2-2.5-9.6-1.4-5.3-5.2-158.3 138.2L262.2 183l-78.4-73.1c-49.6-46.5-79.8-73.9-82.3-75-4.7-2.2-10.5-2.3-15.7-.5"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -22,7 +22,7 @@ const Energy = ({
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M115 56.7c0 43.4-3.9 70.1-15.2 105.3-13.2 41.2-31 72.7-64.7 114.9-9.4 11.8-16.8 21.8-16.4 22.1.5.4 15.9 7.1 34.3 15 45.7 19.5 62.7 28.1 85.5 43.3 20.7 13.8 37.9 28 56 46.2 25.5 25.5 37.6 41.5 64.9 86.1l2.8 4.7 4.2-6.7c23.6-38.7 58.8-78.7 94.3-107.4 36.6-29.6 69.6-48.8 120.8-70.6 12.7-5.4 23.4-10.2 23.8-10.6.5-.4-6.1-9.5-14.6-20.1-18.3-23.1-25-32.4-34.6-48.3-22.9-38.1-38.1-82-44.6-128.6-1.1-7.4-1.8-22.4-2.2-41.8l-.6-30.3-2.6.5c-1.4.3-24.6 4.1-51.6 8.5-92 15-94.4 15-199.8-2.5-21.3-3.5-39-6.4-39.2-6.4-.3 0-.5 12-.5 26.7zm129 28.7c14.8 6.1 22.9 7.8 39.5 8.3 13.2.4 16.9.2 30.8-2.2 8.7-1.5 16-2.6 16.2-2.4.2.2-4 4-9.2 8.4-19.6 16.6-37.7 36.8-50.7 56.6-9.5 14.7-24.6 45.4-24.6 50.2 0 1 3.2 1.8 12.3 3 42.6 5.8 64 5.9 108 .6 9.3-1.1 17-1.9 17.2-1.7.2.2-7.6 9.3-17.2 20.3-28.6 32.6-40.9 48.8-55.3 72.5-10.5 17.4-14.4 26.9-26.6 64-6.3 19.5-13.9 42.7-16.8 51.5l-5.3 16-.9-28c-1.2-36.9-1-59 .5-70 2.3-17.3 7.5-35.6 15.1-53.8 4.5-10.5 3.9-11.7-6.9-14.6-22.9-6.2-71.6-4.5-114.5 3.9-8.3 1.6-15.1 2.8-15.3 2.6-.2-.1 3-4.1 7-8.7 31.2-35.8 55.4-78.7 69.6-123.3 2.1-6.6 6.4-22.4 9.6-34.9 4.8-18.9 6.1-22.8 7.4-22.3.9.2 5.4 2 10.1 4z"
|
||||
d="M115 56.7c0 43.4-3.9 70.1-15.2 105.3-13.2 41.2-31 72.7-64.7 114.9-9.4 11.8-16.8 21.8-16.4 22.1.5.4 15.9 7.1 34.3 15 45.7 19.5 62.7 28.1 85.5 43.3 20.7 13.8 37.9 28 56 46.2 25.5 25.5 37.6 41.5 64.9 86.1l2.8 4.7 4.2-6.7c23.6-38.7 58.8-78.7 94.3-107.4 36.6-29.6 69.6-48.8 120.8-70.6 12.7-5.4 23.4-10.2 23.8-10.6.5-.4-6.1-9.5-14.6-20.1-18.3-23.1-25-32.4-34.6-48.3-22.9-38.1-38.1-82-44.6-128.6-1.1-7.4-1.8-22.4-2.2-41.8l-.6-30.3-2.6.5c-1.4.3-24.6 4.1-51.6 8.5-92 15-94.4 15-199.8-2.5-21.3-3.5-39-6.4-39.2-6.4-.3 0-.5 12-.5 26.7m129 28.7c14.8 6.1 22.9 7.8 39.5 8.3 13.2.4 16.9.2 30.8-2.2 8.7-1.5 16-2.6 16.2-2.4s-4 4-9.2 8.4c-19.6 16.6-37.7 36.8-50.7 56.6-9.5 14.7-24.6 45.4-24.6 50.2 0 1 3.2 1.8 12.3 3 42.6 5.8 64 5.9 108 .6 9.3-1.1 17-1.9 17.2-1.7s-7.6 9.3-17.2 20.3c-28.6 32.6-40.9 48.8-55.3 72.5-10.5 17.4-14.4 26.9-26.6 64-6.3 19.5-13.9 42.7-16.8 51.5l-5.3 16-.9-28c-1.2-36.9-1-59 .5-70 2.3-17.3 7.5-35.6 15.1-53.8 4.5-10.5 3.9-11.7-6.9-14.6-22.9-6.2-71.6-4.5-114.5 3.9-8.3 1.6-15.1 2.8-15.3 2.6-.2-.1 3-4.1 7-8.7 31.2-35.8 55.4-78.7 69.6-123.3 2.1-6.6 6.4-22.4 9.6-34.9 4.8-18.9 6.1-22.8 7.4-22.3.9.2 5.4 2 10.1 4"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -21,8 +21,8 @@ const Exit = ({
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<g fill="currentColor">
|
||||
<path d="M149.3 6.5c-20.9 4.6-40.3 24.4-44.8 46-2.2 10.6-2.2 408.5 0 419 2.4 11.3 7.7 20.9 16.4 29.6 9 9 16.2 13.2 26.7 15.9 7.5 1.9 11.2 2 113.3 2 87.8 0 106.7-.3 112.4-1.5 20-4.2 38.2-21.9 44.4-43.1 1.5-5.2 1.7-12.9 2.1-68.7l.3-62.7h-30l-.3 60.7c-.3 59.8-.3 60.9-2.5 65.5-2.6 5.7-9.4 12.4-15.3 15.2-4.5 2.1-4.9 2.1-110.5 2.1h-106l-5.7-2.8c-3.2-1.6-7.5-4.8-9.7-7.3-7.7-8.8-7.1 9.5-6.9-215.9.3-199 .3-202.1 2.3-206 2.7-5.5 9.7-12.2 15.3-14.8l4.7-2.2h211l5.6 2.6c6.8 3.2 12.4 8.7 15.3 14.8 2 4.5 2.1 6.1 2.4 54.3l.3 49.8h30l-.3-51.8c-.4-45.1-.7-52.5-2.1-57.6-6.1-20.9-22.8-37.4-43.2-42.6-7.6-1.9-11-2-113.4-1.9-84.8 0-106.8.3-111.8 1.4z" />
|
||||
<path d="M426 188.7c-.8.3-2.5 1.5-3.7 2.6-2.2 1.9-2.3 2.8-2.3 16.8 0 8.1-.3 15.4-.6 16.3-.6 1.4-9.5 1.6-91.3 1.6-56.9 0-91.9.4-94.2 1-1.9.6-4.6 2.2-6 3.6-2.3 2.5-2.4 3.2-2.7 19.1-.4 18 .2 21 4.7 24 2.4 1.7 8 1.8 95.6 2.1 72.2.2 93.1.5 93.7 1.5.4.6.8 7.8.8 15.9 0 8 .3 15.4.6 16.3 1.6 4.1 11.6 6.1 17 3.2 5.2-2.7 67.2-56.1 68.4-58.9.7-1.5 1-3.8.6-5.2-.7-2.9-65-57.5-69.9-59.3-3.4-1.2-8.2-1.5-10.7-.6z" />
|
||||
<path d="M149.3 6.5c-20.9 4.6-40.3 24.4-44.8 46-2.2 10.6-2.2 408.5 0 419 2.4 11.3 7.7 20.9 16.4 29.6 9 9 16.2 13.2 26.7 15.9 7.5 1.9 11.2 2 113.3 2 87.8 0 106.7-.3 112.4-1.5 20-4.2 38.2-21.9 44.4-43.1 1.5-5.2 1.7-12.9 2.1-68.7l.3-62.7h-30l-.3 60.7c-.3 59.8-.3 60.9-2.5 65.5-2.6 5.7-9.4 12.4-15.3 15.2-4.5 2.1-4.9 2.1-110.5 2.1h-106l-5.7-2.8c-3.2-1.6-7.5-4.8-9.7-7.3-7.7-8.8-7.1 9.5-6.9-215.9.3-199 .3-202.1 2.3-206 2.7-5.5 9.7-12.2 15.3-14.8l4.7-2.2h211l5.6 2.6c6.8 3.2 12.4 8.7 15.3 14.8 2 4.5 2.1 6.1 2.4 54.3l.3 49.8h30l-.3-51.8c-.4-45.1-.7-52.5-2.1-57.6-6.1-20.9-22.8-37.4-43.2-42.6-7.6-1.9-11-2-113.4-1.9-84.8 0-106.8.3-111.8 1.4" />
|
||||
<path d="M426 188.7c-.8.3-2.5 1.5-3.7 2.6-2.2 1.9-2.3 2.8-2.3 16.8 0 8.1-.3 15.4-.6 16.3-.6 1.4-9.5 1.6-91.3 1.6-56.9 0-91.9.4-94.2 1-1.9.6-4.6 2.2-6 3.6-2.3 2.5-2.4 3.2-2.7 19.1-.4 18 .2 21 4.7 24 2.4 1.7 8 1.8 95.6 2.1 72.2.2 93.1.5 93.7 1.5.4.6.8 7.8.8 15.9 0 8 .3 15.4.6 16.3 1.6 4.1 11.6 6.1 17 3.2 5.2-2.7 67.2-56.1 68.4-58.9.7-1.5 1-3.8.6-5.2-.7-2.9-65-57.5-69.9-59.3-3.4-1.2-8.2-1.5-10.7-.6" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -21,7 +21,7 @@ const Experience = ({
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<g fill="currentColor">
|
||||
<path d="M24.2 73.7c14 18.5 27.2 42.3 30.4 55.3 2.8 11.1 1.5 23.8-6.1 58.5-15 69-16.8 93.2-7.9 111.3 8.7 17.8 45 48.1 121.5 101.4 23.5 16.4 84.8 56.8 86.2 56.8.4 0 .6-64.2.5-142.6l-.3-142.6-7-2.2c-25.3-8-38.8-24.2-41.1-49-.8-8.6 1.4-20.7 5.2-29.4 1.3-3 2.1-5.9 1.7-6.3-.5-.4-9-4.6-19-9.3L170.1 67h-151l5.1 6.7zM334.3 76c-10.1 4.9-18.3 9.1-18.3 9.3 0 .3 1.1 2.9 2.4 5.8 3.7 8.5 5.1 15.7 5 25.9-.1 16.1-4.7 27.6-15 37.7-6.9 6.8-18.7 13.3-28.1 15.4l-5.3 1.2v142.9c0 78.5.3 142.8.8 142.8.4 0 11.8-7.3 25.4-16.3C409.9 369.3 469 323.6 482.5 300.6c9.9-16.9 8.4-41.8-6.6-111.1-8.5-39-9.6-50.6-5.9-62.6 4.3-14.5 13.5-31.3 27-49.5 3.9-5.2 7-9.6 7-9.9 0-.3-34.1-.5-75.7-.4l-75.8.1-18.2 8.8z" />
|
||||
<path d="M24.2 73.7c14 18.5 27.2 42.3 30.4 55.3 2.8 11.1 1.5 23.8-6.1 58.5-15 69-16.8 93.2-7.9 111.3 8.7 17.8 45 48.1 121.5 101.4 23.5 16.4 84.8 56.8 86.2 56.8.4 0 .6-64.2.5-142.6l-.3-142.6-7-2.2c-25.3-8-38.8-24.2-41.1-49-.8-8.6 1.4-20.7 5.2-29.4 1.3-3 2.1-5.9 1.7-6.3-.5-.4-9-4.6-19-9.3L170.1 67h-151zM334.3 76c-10.1 4.9-18.3 9.1-18.3 9.3 0 .3 1.1 2.9 2.4 5.8 3.7 8.5 5.1 15.7 5 25.9-.1 16.1-4.7 27.6-15 37.7-6.9 6.8-18.7 13.3-28.1 15.4l-5.3 1.2v142.9c0 78.5.3 142.8.8 142.8.4 0 11.8-7.3 25.4-16.3C409.9 369.3 469 323.6 482.5 300.6c9.9-16.9 8.4-41.8-6.6-111.1-8.5-39-9.6-50.6-5.9-62.6 4.3-14.5 13.5-31.3 27-49.5 3.9-5.2 7-9.6 7-9.9s-34.1-.5-75.7-.4l-75.8.1z" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -21,7 +21,7 @@ const FullscreenOff = ({
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<g fill="currentColor">
|
||||
<path d="M29.3 20c-1.3.5-3.2 2.4-4.3 4.2-2 3.2-2 5-2 85.6V192l3.4 3.7c3.2 3.5 3.6 3.7 10 3.7 6.2 0 6.9-.3 9.9-3.2l3.2-3.2.2-69.8c.2-52.4.6-70.3 1.5-72 2.8-5.3 1.4-5.2 75.9-5.2h69.1l3.4-3.4c3.2-3.2 3.4-3.8 3.4-10.4 0-6.8-.1-7.1-3.5-10.1l-3.6-3.1-82.2.1c-46.4 0-83.2.4-84.4.9zM323.7 22.1c-5.5 4.2-5.8 16-.6 21.1l2.7 2.8h67.9c43.4 0 69.1.4 71.5 1 2 .6 4.6 2.2 5.8 3.7 2 2.5 2 3.6 2 71.5 0 75.9-.2 73.1 6.2 76.4 4.9 2.5 14.1 1.5 17.6-1.9l2.7-2.7.3-83.5.2-83.4-3.1-3.5-3.1-3.6H410c-82.9 0-83.8 0-86.3 2.1zM26.5 320.9c-1.1.5-2.9 1.9-4 3.1-2 2.2-2 3.8-2.3 85.6l-.2 83.3 3.1 3.5 3.1 3.6H110c82.9 0 83.8 0 86.3-2.1 5.5-4.2 5.8-16 .6-21.1l-2.7-2.8h-67.9c-43.4 0-69.1-.4-71.5-1-2-.6-4.6-2.2-5.8-3.7-2-2.5-2-3.6-2-71.5 0-75.6.2-73.1-6-76.3-3.1-1.6-11.2-1.9-14.5-.6zM477.2 323.4l-3.7 3.4-.5 71.1c-.6 79.2 0 73.4-7.6 75.1-2.1.5-34.3 1-71.5 1h-67.7l-3.1 3.5c-2.7 3.1-3.1 4.3-3.1 9.5s.4 6.4 3.1 9.5l3.1 3.5h168l2.9-2.9 2.9-2.9V326.8l-3.4-3.4c-3.1-3.1-3.9-3.4-9.5-3.4s-6.5.3-9.9 3.4z" />
|
||||
<path d="M29.3 20c-1.3.5-3.2 2.4-4.3 4.2-2 3.2-2 5-2 85.6V192l3.4 3.7c3.2 3.5 3.6 3.7 10 3.7 6.2 0 6.9-.3 9.9-3.2l3.2-3.2.2-69.8c.2-52.4.6-70.3 1.5-72 2.8-5.3 1.4-5.2 75.9-5.2h69.1l3.4-3.4c3.2-3.2 3.4-3.8 3.4-10.4 0-6.8-.1-7.1-3.5-10.1l-3.6-3.1-82.2.1c-46.4 0-83.2.4-84.4.9M323.7 22.1c-5.5 4.2-5.8 16-.6 21.1l2.7 2.8h67.9c43.4 0 69.1.4 71.5 1 2 .6 4.6 2.2 5.8 3.7 2 2.5 2 3.6 2 71.5 0 75.9-.2 73.1 6.2 76.4 4.9 2.5 14.1 1.5 17.6-1.9l2.7-2.7.3-83.5.2-83.4-3.1-3.5-3.1-3.6H410c-82.9 0-83.8 0-86.3 2.1M26.5 320.9c-1.1.5-2.9 1.9-4 3.1-2 2.2-2 3.8-2.3 85.6l-.2 83.3 3.1 3.5 3.1 3.6H110c82.9 0 83.8 0 86.3-2.1 5.5-4.2 5.8-16 .6-21.1l-2.7-2.8h-67.9c-43.4 0-69.1-.4-71.5-1-2-.6-4.6-2.2-5.8-3.7-2-2.5-2-3.6-2-71.5 0-75.6.2-73.1-6-76.3-3.1-1.6-11.2-1.9-14.5-.6M477.2 323.4l-3.7 3.4-.5 71.1c-.6 79.2 0 73.4-7.6 75.1-2.1.5-34.3 1-71.5 1h-67.7l-3.1 3.5c-2.7 3.1-3.1 4.3-3.1 9.5s.4 6.4 3.1 9.5l3.1 3.5h168l2.9-2.9 2.9-2.9V326.8l-3.4-3.4c-3.1-3.1-3.9-3.4-9.5-3.4s-6.5.3-9.9 3.4" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -21,7 +21,7 @@ const FullscreenOn = ({
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<g fill="currentColor">
|
||||
<path d="M185.3 20c-1.8.4-4 1.4-4.9 2.1-4.3 3.6-4.4 4.5-4.4 76.3v68.5l-2.4 2.8-2.4 2.8-71.2.5-71.2.5-2.9 3.3c-2.6 2.9-2.9 4-2.9 9.7 0 5.7.3 6.8 2.9 9.7l2.9 3.3h168.4l2.9-3.3 2.9-3.2v-83.3c0-89.3.2-86-4.8-88.6-2.7-1.4-9.4-2-12.9-1.1zM328 20c-1.9.5-4.5 2-5.7 3.5l-2.3 2.6v167.1l3.4 3.4 3.4 3.4 83.7-.2 83.7-.3 3-3.4c2.8-3.2 3-3.7 2.6-10.2-.3-5.9-.8-7.3-3.1-9.7l-2.7-2.7-70.9-.5-70.9-.5-2.6-2.4-2.5-2.4-.3-70.1c-.3-64.9-.4-70.4-2-72.9-1-1.4-2.6-3-3.5-3.5-2.9-1.5-9.5-2.1-13.3-1.2zM26.4 321c-1.2.4-3.1 2.1-4.4 3.7-1.9 2.4-2.1 3.7-1.8 9.6.3 5.7.8 7.1 3.1 9.5l2.7 2.7 70.9.5 70.9.5 2.6 2.4 2.6 2.4v67.6c0 37.2.5 69.4 1 71.5.5 2.1 1.7 4.8 2.8 5.8 4.6 4.7 16.7 4.2 21-.7l2.2-2.6V326.8l-3.4-3.4-3.4-3.4-82.3.1c-45.3 0-83.4.4-84.5.9zM326.3 321c-1.3.5-3.2 2.4-4.3 4.2-2 3.2-2 5-2 85.6V493l3.4 3.7c3.2 3.5 3.6 3.7 10 3.7 6.2 0 6.9-.3 9.9-3.2l3.2-3.2.2-69.8c.2-52.4.6-70.3 1.5-72 2.8-5.3 1.4-5.2 75.9-5.2h69.1l3.4-3.4c3.2-3.2 3.4-3.8 3.4-10.4 0-6.8-.1-7.1-3.5-10.1l-3.6-3.1-82.2.1c-46.4 0-83.2.4-84.4.9z" />
|
||||
<path d="M185.3 20c-1.8.4-4 1.4-4.9 2.1-4.3 3.6-4.4 4.5-4.4 76.3v68.5l-2.4 2.8-2.4 2.8-71.2.5-71.2.5-2.9 3.3c-2.6 2.9-2.9 4-2.9 9.7s.3 6.8 2.9 9.7l2.9 3.3h168.4l2.9-3.3 2.9-3.2v-83.3c0-89.3.2-86-4.8-88.6-2.7-1.4-9.4-2-12.9-1.1M328 20c-1.9.5-4.5 2-5.7 3.5l-2.3 2.6v167.1l3.4 3.4 3.4 3.4 83.7-.2 83.7-.3 3-3.4c2.8-3.2 3-3.7 2.6-10.2-.3-5.9-.8-7.3-3.1-9.7l-2.7-2.7-70.9-.5-70.9-.5-2.6-2.4-2.5-2.4-.3-70.1c-.3-64.9-.4-70.4-2-72.9-1-1.4-2.6-3-3.5-3.5-2.9-1.5-9.5-2.1-13.3-1.2M26.4 321c-1.2.4-3.1 2.1-4.4 3.7-1.9 2.4-2.1 3.7-1.8 9.6.3 5.7.8 7.1 3.1 9.5l2.7 2.7 70.9.5 70.9.5 2.6 2.4 2.6 2.4v67.6c0 37.2.5 69.4 1 71.5s1.7 4.8 2.8 5.8c4.6 4.7 16.7 4.2 21-.7l2.2-2.6V326.8l-3.4-3.4-3.4-3.4-82.3.1c-45.3 0-83.4.4-84.5.9M326.3 321c-1.3.5-3.2 2.4-4.3 4.2-2 3.2-2 5-2 85.6V493l3.4 3.7c3.2 3.5 3.6 3.7 10 3.7 6.2 0 6.9-.3 9.9-3.2l3.2-3.2.2-69.8c.2-52.4.6-70.3 1.5-72 2.8-5.3 1.4-5.2 75.9-5.2h69.1l3.4-3.4c3.2-3.2 3.4-3.8 3.4-10.4 0-6.8-.1-7.1-3.5-10.1l-3.6-3.1-82.2.1c-46.4 0-83.2.4-84.4.9" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -21,8 +21,8 @@ const Info = ({
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<g fill="currentColor">
|
||||
<path d="M236.7 33.5c-28.8 3.6-51.4 10.2-75.4 22C92.7 89.2 46.2 152.7 34.4 229c-2.5 16-2.5 50 0 66C46 370 91.6 433.3 158.5 467.2c32.9 16.7 65.2 24.3 103.5 24.3 22.1 0 34.2-1.4 54.5-6.2 31.1-7.3 65.4-24.3 90.8-45.2 9.1-7.4 27-25.5 34.3-34.6 25-31.3 41.8-70.1 48-111 2.5-16.4 2.5-48.3 0-65-11.4-76.2-58.6-140.8-126.9-174-23.2-11.2-42.1-17.1-67.7-21-14.5-2.2-44.7-2.8-58.3-1zM294 78.9c74.6 13.2 133.6 70.2 149.6 144.4 8.6 40.3 3.5 82-14.6 119.3C390.5 422 302.6 463 216.5 441.9c-88.7-21.8-148.8-107.6-139.4-199 7.3-71.5 56.7-133.8 124.4-156.8 12.2-4.1 27.1-7.4 40.5-9.1 11.8-1.4 38.8-.4 52 1.9z" />
|
||||
<path d="M246.5 112c-20.8 2-36.2 8.6-48.5 21.1-11.5 11.6-19.3 26.4-27.5 52-3.4 10.6-3.6 11.9-2.4 14.4 2 4.1 5.8 6.5 11.4 7.1 7.4.9 9.2-1 17.8-19 14.9-30.8 25.7-41.9 46-47.3 8.4-2.3 29.8-2.2 38.6.1 21.2 5.5 34.6 19.5 35.9 37.6.8 11.1-2.3 16.4-20.5 35.2-26 26.8-38 45.6-44.2 69.2-3 11.3-4.6 31.6-3.6 46 .7 11.3.9 12.1 3.5 14.8 2.6 2.5 3.5 2.8 9.5 2.8 5.7 0 6.9-.3 9-2.5 1.4-1.3 2.5-3.2 2.6-4.2.1-1 .2-9.9.3-19.8.2-20.3 1.6-28.1 7.1-40.2 7.6-16.6 23.7-36 42.5-51.3 22.4-18.2 28.1-27.9 28-47.8-.1-19.8-6.1-35.4-17.9-46.5-8.6-8.1-14.8-11.8-26.6-15.7-16.5-5.4-41.3-7.8-61-6zM252.4 372.9c-4.2 1.8-5.4 5-5.4 13.9 0 4.6.5 9.2 1 10.3 1.8 3.3 6.4 4.9 14 4.9 12.6 0 15.5-3.3 14.9-16.9-.6-11.3-1.9-12.5-13.7-12.8-4.8-.2-9.7.1-10.8.6z" />
|
||||
<path d="M236.7 33.5c-28.8 3.6-51.4 10.2-75.4 22C92.7 89.2 46.2 152.7 34.4 229c-2.5 16-2.5 50 0 66C46 370 91.6 433.3 158.5 467.2c32.9 16.7 65.2 24.3 103.5 24.3 22.1 0 34.2-1.4 54.5-6.2 31.1-7.3 65.4-24.3 90.8-45.2 9.1-7.4 27-25.5 34.3-34.6 25-31.3 41.8-70.1 48-111 2.5-16.4 2.5-48.3 0-65-11.4-76.2-58.6-140.8-126.9-174-23.2-11.2-42.1-17.1-67.7-21-14.5-2.2-44.7-2.8-58.3-1M294 78.9c74.6 13.2 133.6 70.2 149.6 144.4 8.6 40.3 3.5 82-14.6 119.3C390.5 422 302.6 463 216.5 441.9c-88.7-21.8-148.8-107.6-139.4-199 7.3-71.5 56.7-133.8 124.4-156.8 12.2-4.1 27.1-7.4 40.5-9.1 11.8-1.4 38.8-.4 52 1.9" />
|
||||
<path d="M246.5 112c-20.8 2-36.2 8.6-48.5 21.1-11.5 11.6-19.3 26.4-27.5 52-3.4 10.6-3.6 11.9-2.4 14.4 2 4.1 5.8 6.5 11.4 7.1 7.4.9 9.2-1 17.8-19 14.9-30.8 25.7-41.9 46-47.3 8.4-2.3 29.8-2.2 38.6.1 21.2 5.5 34.6 19.5 35.9 37.6.8 11.1-2.3 16.4-20.5 35.2-26 26.8-38 45.6-44.2 69.2-3 11.3-4.6 31.6-3.6 46 .7 11.3.9 12.1 3.5 14.8 2.6 2.5 3.5 2.8 9.5 2.8 5.7 0 6.9-.3 9-2.5 1.4-1.3 2.5-3.2 2.6-4.2s.2-9.9.3-19.8c.2-20.3 1.6-28.1 7.1-40.2 7.6-16.6 23.7-36 42.5-51.3 22.4-18.2 28.1-27.9 28-47.8-.1-19.8-6.1-35.4-17.9-46.5-8.6-8.1-14.8-11.8-26.6-15.7-16.5-5.4-41.3-7.8-61-6M252.4 372.9c-4.2 1.8-5.4 5-5.4 13.9 0 4.6.5 9.2 1 10.3 1.8 3.3 6.4 4.9 14 4.9 12.6 0 15.5-3.3 14.9-16.9-.6-11.3-1.9-12.5-13.7-12.8-4.8-.2-9.7.1-10.8.6" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -20,8 +20,8 @@ const FivePlayers = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zM396 269v221H57V409.3l11.3-.6c18.4-1 32.5-6 42.3-15C125.7 380 138.1 334 138.1 292c0-23.9-3.5-47.1-10.7-71-9.5-31.4-25.9-44.2-58.8-45.7l-11.9-.6.6-11.6c1.1-18.8 4.8-33.4 12.7-49.2C83.9 86 109.2 64.3 139.7 54c17.7-5.9 15.3-5.8 141.1-5.9L396 48v221zM651.5 50.9c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.2 6.9 1.5 19.8 1.5 68.3v59.7l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6v353.4l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6v59.7c0 65.6-.2 69-6.1 86.4-13.7 41-49.7 71.9-92.9 79.7-6.1 1.1-29.8 1.4-123.5 1.4h-116l-.3-638.8-.2-638.8 118.7.4 118.8.3 9 2.3zM396 692v192H57V805.3l11.3-.6c18.4-1 32.5-6 42.3-15C125.7 776 138.1 730 138.1 688c0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V500h339v192zm0 417.5V1326H285.3c-63.3 0-115-.5-120.7-1-32.5-3.2-63-20.2-83-46.5-15-19.7-24.6-47.5-24.6-71.6v-6.6l11.3-.6c18.4-1 32.5-6 42.3-15 15.1-13.7 27.5-59.7 27.5-101.7 0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V893h339v216.5z" />
|
||||
<path d="M195 236.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM574.1 340.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM574.1 928.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM195 632.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM195 1027.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 4-19-1.3-36.4-15.6-50.7-11.5-11.6-24.1-16.8-40.2-16.6-4 0-9.7.7-12.7 1.5z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7M396 269v221H57v-80.7l11.3-.6q27.6-1.5 42.3-15C125.7 380 138.1 334 138.1 292c0-23.9-3.5-47.1-10.7-71-9.5-31.4-25.9-44.2-58.8-45.7l-11.9-.6.6-11.6c1.1-18.8 4.8-33.4 12.7-49.2C83.9 86 109.2 64.3 139.7 54c17.7-5.9 15.3-5.8 141.1-5.9L396 48zM651.5 50.9c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.2 6.9 1.5 19.8 1.5 68.3v59.7l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6v353.4l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6v59.7c0 65.6-.2 69-6.1 86.4-13.7 41-49.7 71.9-92.9 79.7-6.1 1.1-29.8 1.4-123.5 1.4h-116l-.3-638.8-.2-638.8 118.7.4 118.8.3zM396 692v192H57v-78.7l11.3-.6q27.6-1.5 42.3-15C125.7 776 138.1 730 138.1 688c0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V500h339zm0 417.5V1326H285.3c-63.3 0-115-.5-120.7-1-32.5-3.2-63-20.2-83-46.5-15-19.7-24.6-47.5-24.6-71.6v-6.6l11.3-.6q27.6-1.5 42.3-15c15.1-13.7 27.5-59.7 27.5-101.7 0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V893h339z" />
|
||||
<path d="M195 236.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M574.1 340.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M574.1 928.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M195 632.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M195 1027.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 4-19-1.3-36.4-15.6-50.7-11.5-11.6-24.1-16.8-40.2-16.6-4 0-9.7.7-12.7 1.5" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const FivePlayersSide = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zM396 285.5V523H57V418.3l9.8-.6c17.2-1.2 31.4-6.3 40.8-15 8.8-8 16-24.7 21.9-51.2 7.6-33.9 7.6-68.2-.1-102-5.7-25.6-11.3-39-19.9-48.3-9.3-10.1-23.7-15.9-42.5-17.1l-9.5-.6.1-15c.1-21.7 3.3-36.1 12.1-54 14.1-28.4 39.2-50.1 70-60.5 17.7-5.9 15.3-5.8 141.1-5.9L396 48v237.5zM651.5 50.9c36 9.4 63.5 30.9 79.4 62 9.1 17.9 13.1 35 13.1 56.6v13.2l-9.4.7c-18 1.2-33.9 7.2-42.3 15.9-5.5 5.6-10.5 15-14.7 27.7-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.1 10.1 22.9 15.1 41.4 16.1l10.2.6V523H405V47.9l118.8.4 118.7.3 9 2.3zM395.8 767.2l.2 234.8H57V872.3l11.8-.6c18.9-1 32.8-5.9 42.8-15C126.7 843 139.1 797 139.1 755c0-23.9-3.5-47.1-10.7-71-9.5-31.5-25.9-44.2-59.1-45.7l-12.3-.6V532l169.3.2 169.2.3.3 234.7zM744 584.4v52.3l-9.4.7c-18 1.2-33.9 7.2-42.3 15.9-5.5 5.6-10.5 15-14.7 27.7-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.1 10.1 22.9 15.1 41.4 16.1l10.2.6V1002H405V532h339v52.4zm0 530c0 113.4.1 111.6-6.1 130-13.4 40-47.4 70-89.9 79.2-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.6-10.3c-.7-11.8-4-24.6-8.3-32.3-8.3-14.9-24-23.3-57.9-30.9-23.8-5.4-54.3-7.2-76-4.6-21.2 2.5-48 9.3-60.9 15.5-19.1 9-28.7 25.4-30.4 52l-.7 10-53 .3c-57.6.3-70.7-.4-85.4-4.3-24.3-6.6-47.8-22.5-63.5-43-7.7-10.1-16.6-27.7-19.6-38.6-4.9-18.3-5-19.6-5-127.7V1011h687v103.4z" />
|
||||
<path d="M192 245.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM578.1 247.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM196 699.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM578.1 701.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM388.3 1121.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7M396 285.5V523H57V418.3l9.8-.6c17.2-1.2 31.4-6.3 40.8-15 8.8-8 16-24.7 21.9-51.2 7.6-33.9 7.6-68.2-.1-102-5.7-25.6-11.3-39-19.9-48.3-9.3-10.1-23.7-15.9-42.5-17.1l-9.5-.6.1-15c.1-21.7 3.3-36.1 12.1-54 14.1-28.4 39.2-50.1 70-60.5 17.7-5.9 15.3-5.8 141.1-5.9L396 48zM651.5 50.9c36 9.4 63.5 30.9 79.4 62 9.1 17.9 13.1 35 13.1 56.6v13.2l-9.4.7c-18 1.2-33.9 7.2-42.3 15.9-5.5 5.6-10.5 15-14.7 27.7-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.1 10.1 22.9 15.1 41.4 16.1l10.2.6V523H405V47.9l118.8.4 118.7.3zM395.8 767.2l.2 234.8H57V872.3l11.8-.6c18.9-1 32.8-5.9 42.8-15C126.7 843 139.1 797 139.1 755c0-23.9-3.5-47.1-10.7-71-9.5-31.5-25.9-44.2-59.1-45.7l-12.3-.6V532l169.3.2 169.2.3zM744 584.4v52.3l-9.4.7c-18 1.2-33.9 7.2-42.3 15.9-5.5 5.6-10.5 15-14.7 27.7-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.1 10.1 22.9 15.1 41.4 16.1l10.2.6V1002H405V532h339zm0 530c0 113.4.1 111.6-6.1 130-13.4 40-47.4 70-89.9 79.2-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.6-10.3c-.7-11.8-4-24.6-8.3-32.3-8.3-14.9-24-23.3-57.9-30.9-23.8-5.4-54.3-7.2-76-4.6-21.2 2.5-48 9.3-60.9 15.5-19.1 9-28.7 25.4-30.4 52l-.7 10-53 .3c-57.6.3-70.7-.4-85.4-4.3-24.3-6.6-47.8-22.5-63.5-43-7.7-10.1-16.6-27.7-19.6-38.6-4.9-18.3-5-19.6-5-127.7V1011h687z" />
|
||||
<path d="M192 245.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M578.1 247.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M196 699.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M578.1 701.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M388.3 1121.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const FourPlayers = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zM396 365v317H57V511.3l11.3-.6c18.4-1 32.5-6 42.3-15C125.7 482 138.1 436 138.1 394c0-23.9-3.5-47.1-10.7-71-9.4-31.4-25.9-44.2-58.7-45.7l-11.8-.6.4-62.6c.3-59.6.4-63 2.5-71.6 2.8-11.9 5.1-18.4 10.2-28.6C83.9 86 109.2 64.3 139.7 54c17.7-5.9 15.3-5.8 141.1-5.9L396 48v317zM651.5 50.9c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.2 6.9 1.5 19.8 1.5 68.3v59.7l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6V682H405V47.9l118.8.4 118.7.3 9 2.3zM396 1009v317H285.3c-63.3 0-115-.5-120.7-1-32.5-3.2-63-20.2-83-46.5-7.7-10.1-16.6-27.7-19.6-38.6-4.6-17.2-5-22.8-5-83.5v-57.1l11.3-.6c18.4-1 32.5-6 42.3-15 15.1-13.7 27.5-59.7 27.5-101.7 0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V692h339v317zm348-231.2v85.9l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6v59.7c0 65.6-.2 69-6.1 86.4-13.7 41-49.7 71.9-92.9 79.7-6.1 1.1-29.8 1.4-123.5 1.4h-116l-.3-316.8L405 692h339v85.8z" />
|
||||
<path d="M195 338.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM574.1 340.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM195 926.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM574.1 928.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7M396 365v317H57V511.3l11.3-.6q27.6-1.5 42.3-15C125.7 482 138.1 436 138.1 394c0-23.9-3.5-47.1-10.7-71-9.4-31.4-25.9-44.2-58.7-45.7l-11.8-.6.4-62.6c.3-59.6.4-63 2.5-71.6 2.8-11.9 5.1-18.4 10.2-28.6C83.9 86 109.2 64.3 139.7 54c17.7-5.9 15.3-5.8 141.1-5.9L396 48zM651.5 50.9c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.2 6.9 1.5 19.8 1.5 68.3v59.7l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6V682H405V47.9l118.8.4 118.7.3zM396 1009v317H285.3c-63.3 0-115-.5-120.7-1-32.5-3.2-63-20.2-83-46.5-7.7-10.1-16.6-27.7-19.6-38.6-4.6-17.2-5-22.8-5-83.5v-57.1l11.3-.6q27.6-1.5 42.3-15c15.1-13.7 27.5-59.7 27.5-101.7 0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V692h339zm348-231.2v85.9l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6v59.7c0 65.6-.2 69-6.1 86.4-13.7 41-49.7 71.9-92.9 79.7-6.1 1.1-29.8 1.4-123.5 1.4h-116l-.3-316.8L405 692h339z" />
|
||||
<path d="M195 338.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M574.1 340.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M195 926.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M574.1 928.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const FourPlayersSide = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zm124 41.2c.1 21 5.7 36.8 16.7 47.4 14.3 13.6 60.7 25.4 100.3 25.4 23.7 0 42.4-2.7 66.7-9.7 23.4-6.7 35.7-15 42.3-28.8 5-10.6 6.6-17.6 7.2-32.9l.6-13.8 62.1.3c61.6.3 62.2.3 71.6 2.7 48.7 12.2 83.1 48.6 91.5 96.8 1.3 7.3 1.5 26.3 1.5 124.9V389l-343.2-.2-343.3-.3V271c0-109.1.1-118.1 1.8-126 9.2-43.6 38.7-77 80.4-91 16.6-5.5 20.3-5.8 84.8-5.9l59-.1v12.3zM396 687v289H57V805.3l12.8-.6c19.8-.9 33.6-5.6 43.8-15C128.7 776 141.1 730 141.1 688c0-23.9-3.5-47.1-10.7-71-9.6-31.9-26-44.4-60.1-45.7l-13.3-.6V398h339v289zm348-202.8v86.3h-12.3c-14.9.1-24.8 2.2-35.5 7.5-13.1 6.6-19.9 15.8-26.6 36-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 11.1 11 23.1 15.3 45.4 16.1l14.2.6V976H405V398h339v86.2zm0 617.2c0 127.7.1 124.4-6.1 143-13.4 40-47.4 70-89.9 79.2-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.7-8.6c-.8-10.3-4.3-23-8.2-30-8.3-14.9-24-23.3-57.9-30.9-23.8-5.4-54.3-7.2-76-4.6-21.2 2.5-48 9.3-60.9 15.5-18.5 8.7-28.1 24.5-30.3 49.6l-.8 8.4-53 .3c-57.6.3-70.7-.4-85.4-4.3-24.3-6.6-47.8-22.5-63.5-43-7.7-10.1-16.6-27.7-19.6-38.6-5-18.4-5-18.6-5-140.7V985h687v116.4z" />
|
||||
<path d="M391.8 148c-16.5 3-30 12.2-39.1 26.7-7.9 12.6-10 31-5.2 46.1 4.5 14.4 15.5 26.9 29.1 33.4 22.1 10.4 46.1 6.2 63.5-11.1 11.5-11.5 16.9-24.2 16.9-39.9 0-23.4-16.1-45.5-38.6-53.1-7.1-2.3-19.8-3.4-26.6-2.1zM198 632.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM570.1 634.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM388.3 1125.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7m124 41.2c.1 21 5.7 36.8 16.7 47.4 14.3 13.6 60.7 25.4 100.3 25.4 23.7 0 42.4-2.7 66.7-9.7 23.4-6.7 35.7-15 42.3-28.8 5-10.6 6.6-17.6 7.2-32.9l.6-13.8 62.1.3c61.6.3 62.2.3 71.6 2.7 48.7 12.2 83.1 48.6 91.5 96.8 1.3 7.3 1.5 26.3 1.5 124.9V389l-343.2-.2-343.3-.3V271c0-109.1.1-118.1 1.8-126 9.2-43.6 38.7-77 80.4-91 16.6-5.5 20.3-5.8 84.8-5.9l59-.1zM396 687v289H57V805.3l12.8-.6c19.8-.9 33.6-5.6 43.8-15C128.7 776 141.1 730 141.1 688c0-23.9-3.5-47.1-10.7-71-9.6-31.9-26-44.4-60.1-45.7l-13.3-.6V398h339zm348-202.8v86.3h-12.3c-14.9.1-24.8 2.2-35.5 7.5-13.1 6.6-19.9 15.8-26.6 36-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 11.1 11 23.1 15.3 45.4 16.1l14.2.6V976H405V398h339zm0 617.2c0 127.7.1 124.4-6.1 143-13.4 40-47.4 70-89.9 79.2-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.7-8.6c-.8-10.3-4.3-23-8.2-30-8.3-14.9-24-23.3-57.9-30.9-23.8-5.4-54.3-7.2-76-4.6-21.2 2.5-48 9.3-60.9 15.5-18.5 8.7-28.1 24.5-30.3 49.6l-.8 8.4-53 .3c-57.6.3-70.7-.4-85.4-4.3-24.3-6.6-47.8-22.5-63.5-43-7.7-10.1-16.6-27.7-19.6-38.6-5-18.4-5-18.6-5-140.7V985h687z" />
|
||||
<path d="M391.8 148c-16.5 3-30 12.2-39.1 26.7-7.9 12.6-10 31-5.2 46.1 4.5 14.4 15.5 26.9 29.1 33.4 22.1 10.4 46.1 6.2 63.5-11.1 11.5-11.5 16.9-24.2 16.9-39.9 0-23.4-16.1-45.5-38.6-53.1-7.1-2.3-19.8-3.4-26.6-2.1M198 632.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M570.1 634.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M388.3 1125.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const OnePlayerLandscape = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zm492 31.8c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.5 1.5 73.4 1.5 539.3 0 474.6-.2 531.7-1.5 539.6-8.5 48.4-45 85.9-94.5 97.1-6.9 1.6-26.1 1.7-239 2-154.7.3-235.3 0-243-.7-20.8-1.8-38.3-8-55.8-19.7-28.1-18.7-46.6-48.2-51.8-82.8-1.1-7.4-1.4-45.9-1.4-213.6V804.3l9.8-.6c17.2-1.2 31.4-6.3 40.8-15 8.8-8 16-24.7 21.9-51.2 7.6-33.9 7.6-68.2-.1-102-5.7-25.6-11.3-39-19.9-48.3-9.3-10.1-23.7-15.9-42.5-17.1l-9.5-.6v-208c0-196.2.1-208.5 1.8-216.5 9.2-43.6 38.7-77 80.4-91 18.5-6.2 3.5-5.8 264.3-5.6l238.5.1 9 2.4z" />
|
||||
<path d="M192 631.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7m492 31.8c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.5 1.5 73.4 1.5 539.3 0 474.6-.2 531.7-1.5 539.6-8.5 48.4-45 85.9-94.5 97.1-6.9 1.6-26.1 1.7-239 2-154.7.3-235.3 0-243-.7-20.8-1.8-38.3-8-55.8-19.7-28.1-18.7-46.6-48.2-51.8-82.8-1.1-7.4-1.4-45.9-1.4-213.6V804.3l9.8-.6c17.2-1.2 31.4-6.3 40.8-15 8.8-8 16-24.7 21.9-51.2 7.6-33.9 7.6-68.2-.1-102-5.7-25.6-11.3-39-19.9-48.3-9.3-10.1-23.7-15.9-42.5-17.1l-9.5-.6v-208c0-196.2.1-208.5 1.8-216.5 9.2-43.6 38.7-77 80.4-91 18.5-6.2 3.5-5.8 264.3-5.6l238.5.1z" />
|
||||
<path d="M192 631.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const OnePlayerPortrait = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zm492 31.8c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.5 1.5 73.4 1.5 539.3 0 474.6-.2 531.7-1.5 539.6-8.5 48.4-45.4 86.3-94.5 97-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.7-9c-.8-10.6-4.3-23.4-8.2-30.6-8.3-14.9-24-23.3-57.9-30.9-23.8-5.4-54.3-7.2-76-4.6-21.2 2.5-48 9.3-60.9 15.5-18.6 8.8-28.2 24.8-30.4 50.2l-.7 8.8-53 .3c-30.9.2-57.8-.2-64.5-.8-56.5-5-101.1-48.5-108-105.2-.8-6.8-1-151.9-.8-538.8l.3-529.5 2.2-9c2.9-12 5.2-18.5 10.3-28.6C83.9 86 109.2 64.3 139.7 54c18.5-6.2 3.5-5.8 264.3-5.6l238.5.1 9 2.4z" />
|
||||
<path d="M388.3 1124.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7m492 31.8c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.5 1.5 73.4 1.5 539.3 0 474.6-.2 531.7-1.5 539.6-8.5 48.4-45.4 86.3-94.5 97-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.7-9c-.8-10.6-4.3-23.4-8.2-30.6-8.3-14.9-24-23.3-57.9-30.9-23.8-5.4-54.3-7.2-76-4.6-21.2 2.5-48 9.3-60.9 15.5-18.6 8.8-28.2 24.8-30.4 50.2l-.7 8.8-53 .3c-30.9.2-57.8-.2-64.5-.8-56.5-5-101.1-48.5-108-105.2-.8-6.8-1-151.9-.8-538.8l.3-529.5 2.2-9c2.9-12 5.2-18.5 10.3-28.6C83.9 86 109.2 64.3 139.7 54c18.5-6.2 3.5-5.8 264.3-5.6l238.5.1z" />
|
||||
<path d="M388.3 1124.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const SixPlayers = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zM396 266.5V485l-169.2-.2-169.3-.3-.3-37.6-.2-37.6 11.2-.6c18.5-1 32.6-6 42.4-15C125.7 380 138.1 334 138.1 292c0-23.9-3.5-47.1-10.7-71-9.5-31.4-25.9-44.2-58.8-45.7l-11.9-.6.6-11.6c1.1-18.8 4.8-33.4 12.7-49.2C83.9 86 109.2 64.3 139.7 54c17.7-5.9 15.3-5.8 141.1-5.9L396 48v218.5zM651.5 50.9c36 9.4 63.5 30.9 79.4 62C739.3 129.4 744 148 744 165v8.7l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6V485l-169.2-.2-169.3-.3-.3-218.3-.2-218.3 118.7.4 118.8.3 9 2.3zM396 687v193H57V805.3l11.3-.6c18.4-1 32.5-6 42.3-15C125.7 776 138.1 730 138.1 688c0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V494h339v193zm348-155.2v37.9l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6V880H405V494h339v37.8zm-348 575.7V1326H285.3c-63.3 0-115-.5-120.7-1-32.5-3.2-63-20.2-83-46.5-15-19.7-24.6-47.5-24.6-71.6v-6.6l11.3-.6c18.4-1 32.5-6 42.3-15 15.1-13.7 27.5-59.7 27.5-101.7 0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V889h339v218.5zm348-180.7v37.9l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6v9.2c0 55.8-42.5 105.3-99 115.6-6.1 1.1-29.8 1.4-123.5 1.4h-116l-.3-217c-.1-119.4 0-217.6.3-218.3.3-.9 35.2-1.2 169.5-1.2h169v37.8z" />
|
||||
<path d="M195 236.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM574.1 238.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM195 632.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM574.1 634.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM195 1027.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 4-19-1.3-36.4-15.6-50.7-11.5-11.6-24.1-16.8-40.2-16.6-4 0-9.7.7-12.7 1.5zM574.1 1029.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7M396 266.5V485l-169.2-.2-169.3-.3-.3-37.6-.2-37.6 11.2-.6c18.5-1 32.6-6 42.4-15C125.7 380 138.1 334 138.1 292c0-23.9-3.5-47.1-10.7-71-9.5-31.4-25.9-44.2-58.8-45.7l-11.9-.6.6-11.6c1.1-18.8 4.8-33.4 12.7-49.2C83.9 86 109.2 64.3 139.7 54c17.7-5.9 15.3-5.8 141.1-5.9L396 48zM651.5 50.9c36 9.4 63.5 30.9 79.4 62C739.3 129.4 744 148 744 165v8.7l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6V485l-169.2-.2-169.3-.3-.3-218.3-.2-218.3 118.7.4 118.8.3zM396 687v193H57v-74.7l11.3-.6q27.6-1.5 42.3-15C125.7 776 138.1 730 138.1 688c0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V494h339zm348-155.2v37.9l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6V880H405V494h339zm-348 575.7V1326H285.3c-63.3 0-115-.5-120.7-1-32.5-3.2-63-20.2-83-46.5-15-19.7-24.6-47.5-24.6-71.6v-6.6l11.3-.6q27.6-1.5 42.3-15c15.1-13.7 27.5-59.7 27.5-101.7 0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V889h339zm348-180.7v37.9l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6v9.2c0 55.8-42.5 105.3-99 115.6-6.1 1.1-29.8 1.4-123.5 1.4h-116l-.3-217c-.1-119.4 0-217.6.3-218.3.3-.9 35.2-1.2 169.5-1.2h169z" />
|
||||
<path d="M195 236.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M574.1 238.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M195 632.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M574.1 634.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M195 1027.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 4-19-1.3-36.4-15.6-50.7-11.5-11.6-24.1-16.8-40.2-16.6-4 0-9.7.7-12.7 1.5M574.1 1029.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const SixPlayersSide = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zm124 42.1c0 22 5.5 37.7 16.7 48.5 14.3 13.6 60.7 25.4 100.3 25.4 23.7 0 42.4-2.7 66.7-9.7 23.4-6.7 35.7-15 42.3-28.8 5.2-10.9 6.6-17.5 7.2-33.9l.6-14.8 62.1.3c61.6.3 62.2.3 71.6 2.7 48.7 12.2 83.1 48.6 91.5 96.8 1.2 7 1.5 20.5 1.5 73.9V287H56.9l.4-67.8c.3-64.8.4-68.1 2.5-76.7 2.8-11.9 5.1-18.4 10.2-28.6C83.9 86 109.2 64.3 139.7 54c16.6-5.5 20.3-5.8 84.8-5.9l59-.1v13.2zM396 489v193H57v-42.7l9.8-.6c17.2-1.2 31.4-6.3 40.8-15 8.8-8 16-24.7 21.9-51.2 7.6-33.9 7.6-68.2-.1-102-5.7-25.6-11.3-39-19.9-48.3-9.3-10.1-23.7-15.9-42.5-17.1l-9.5-.6-.3-54.3L57 296h339v193zm348-139.1v53.8l-9.4.7c-18 1.2-33.9 7.2-42.3 15.9-5.5 5.6-10.5 15-14.7 27.7-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.1 10.1 22.9 15.1 41.4 16.1l10.2.6V682H405V296h339v53.9zM395.8 880.2l-.3 188.3-169.2.3-169.3.2V985.3l11.8-.6c18.9-1 32.8-5.9 42.8-15C126.7 956 139.1 910 139.1 868c0-23.9-3.5-47.1-10.7-71-9.5-31.5-25.9-44.2-59.1-45.7l-12.3-.6V692h339l-.2 188.2zM744 720.9v28.8l-9.4.7c-18 1.2-33.9 7.2-42.3 15.9-5.5 5.6-10.5 15-14.7 27.7-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.1 10.1 22.9 15.1 41.4 16.1l10.2.6V1069H405V692h339v28.9zm0 427c0 76.6-.1 78.7-6.1 96.5-13.4 40-47.4 70-89.9 79.2-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.6-10.3c-.7-11.8-4-24.6-8.3-32.3-8.3-14.9-24-23.3-57.9-30.9-23.8-5.4-54.3-7.2-76-4.6-21.2 2.5-48 9.3-60.9 15.5-19.1 9-28.7 25.4-30.4 52l-.7 10-53 .3c-57.6.3-70.7-.4-85.4-4.3-24.3-6.6-47.8-22.5-63.5-43-7.7-10.1-16.6-27.7-19.6-38.6-4.7-17.6-5-22.1-5-94.2V1078h687v69.9z" />
|
||||
<path d="M391.8 150c-16.5 3-30 12.2-39.1 26.7-7.9 12.6-10 31-5.2 46.1 4.5 14.4 15.5 26.9 29.1 33.4 22.1 10.4 46.1 6.2 63.5-11.1 11.5-11.5 16.9-24.2 16.9-39.9 0-23.4-16.1-45.5-38.6-53.1-7.1-2.3-19.8-3.4-26.6-2.1zM192 466.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM578.1 468.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM196 812.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM578.1 814.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM388.3 1121.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7m124 42.1c0 22 5.5 37.7 16.7 48.5 14.3 13.6 60.7 25.4 100.3 25.4 23.7 0 42.4-2.7 66.7-9.7 23.4-6.7 35.7-15 42.3-28.8 5.2-10.9 6.6-17.5 7.2-33.9l.6-14.8 62.1.3c61.6.3 62.2.3 71.6 2.7 48.7 12.2 83.1 48.6 91.5 96.8 1.2 7 1.5 20.5 1.5 73.9V287H56.9l.4-67.8c.3-64.8.4-68.1 2.5-76.7 2.8-11.9 5.1-18.4 10.2-28.6C83.9 86 109.2 64.3 139.7 54c16.6-5.5 20.3-5.8 84.8-5.9l59-.1zM396 489v193H57v-42.7l9.8-.6c17.2-1.2 31.4-6.3 40.8-15 8.8-8 16-24.7 21.9-51.2 7.6-33.9 7.6-68.2-.1-102-5.7-25.6-11.3-39-19.9-48.3-9.3-10.1-23.7-15.9-42.5-17.1l-9.5-.6-.3-54.3L57 296h339zm348-139.1v53.8l-9.4.7c-18 1.2-33.9 7.2-42.3 15.9-5.5 5.6-10.5 15-14.7 27.7-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.1 10.1 22.9 15.1 41.4 16.1l10.2.6V682H405V296h339zM395.8 880.2l-.3 188.3-169.2.3-169.3.2v-83.7l11.8-.6c18.9-1 32.8-5.9 42.8-15C126.7 956 139.1 910 139.1 868c0-23.9-3.5-47.1-10.7-71-9.5-31.5-25.9-44.2-59.1-45.7l-12.3-.6V692h339zM744 720.9v28.8l-9.4.7c-18 1.2-33.9 7.2-42.3 15.9-5.5 5.6-10.5 15-14.7 27.7-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.1 10.1 22.9 15.1 41.4 16.1l10.2.6v84.7H405V692h339zm0 427c0 76.6-.1 78.7-6.1 96.5-13.4 40-47.4 70-89.9 79.2-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.6-10.3c-.7-11.8-4-24.6-8.3-32.3-8.3-14.9-24-23.3-57.9-30.9-23.8-5.4-54.3-7.2-76-4.6-21.2 2.5-48 9.3-60.9 15.5-19.1 9-28.7 25.4-30.4 52l-.7 10-53 .3c-57.6.3-70.7-.4-85.4-4.3-24.3-6.6-47.8-22.5-63.5-43-7.7-10.1-16.6-27.7-19.6-38.6-4.7-17.6-5-22.1-5-94.2V1078h687z" />
|
||||
<path d="M391.8 150c-16.5 3-30 12.2-39.1 26.7-7.9 12.6-10 31-5.2 46.1 4.5 14.4 15.5 26.9 29.1 33.4 22.1 10.4 46.1 6.2 63.5-11.1 11.5-11.5 16.9-24.2 16.9-39.9 0-23.4-16.1-45.5-38.6-53.1-7.1-2.3-19.8-3.4-26.6-2.1M192 466.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M578.1 468.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M196 812.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M578.1 814.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M388.3 1121.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const ThreePlayers = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zM396 365v317H57V511.3l11.3-.6c18.4-1 32.5-6 42.3-15C125.7 482 138.1 436 138.1 394c0-23.9-3.5-47.1-10.7-71-9.4-31.4-25.9-44.2-58.7-45.7l-11.8-.6.4-62.6c.3-59.6.4-63 2.5-71.6 2.8-11.9 5.1-18.4 10.2-28.6C83.9 86 109.2 64.3 139.7 54c17.7-5.9 15.3-5.8 141.1-5.9L396 48v317zM651.5 50.9c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.4 1.5 36.6 1.5 215.3v206.7l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6V1011c0 227.3.3 214.2-6.1 233.4-13.4 40-47 69.6-89.9 79.3-6.9 1.6-26.1 1.7-239 2-154.7.3-235.3 0-243-.7-20.8-1.8-38.3-8-55.8-19.7-28.1-18.7-46.6-48.2-51.8-82.8-1.1-6.8-1.4-23-1.4-66.1v-57.1l11.3-.6c18.4-1 32.5-6 42.3-15 15.1-13.7 27.5-59.7 27.5-101.7 0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V691h339v634h9V47.9l118.8.4 118.7.3 9 2.3z" />
|
||||
<path d="M195 338.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM574.1 634.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM195 926.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7M396 365v317H57V511.3l11.3-.6q27.6-1.5 42.3-15C125.7 482 138.1 436 138.1 394c0-23.9-3.5-47.1-10.7-71-9.4-31.4-25.9-44.2-58.7-45.7l-11.8-.6.4-62.6c.3-59.6.4-63 2.5-71.6 2.8-11.9 5.1-18.4 10.2-28.6C83.9 86 109.2 64.3 139.7 54c17.7-5.9 15.3-5.8 141.1-5.9L396 48zM651.5 50.9c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.4 1.5 36.6 1.5 215.3v206.7l-11.2.6c-13.6.8-24.6 3.4-33.7 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.6 10.6 23 15.2 43.4 16.1l12.2.6V1011c0 227.3.3 214.2-6.1 233.4-13.4 40-47 69.6-89.9 79.3-6.9 1.6-26.1 1.7-239 2-154.7.3-235.3 0-243-.7-20.8-1.8-38.3-8-55.8-19.7-28.1-18.7-46.6-48.2-51.8-82.8-1.1-6.8-1.4-23-1.4-66.1v-57.1l11.3-.6q27.6-1.5 42.3-15c15.1-13.7 27.5-59.7 27.5-101.7 0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.6-45.7l-11.8-.6V691h339v634h9V47.9l118.8.4 118.7.3z" />
|
||||
<path d="M195 338.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M574.1 634.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M195 926.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const ThreePlayersSide = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zM397 471.5V895H57V592.3l9.8-.6c17.2-1.2 31.4-6.3 40.8-15 8.8-8 16-24.7 21.9-51.2 7.6-33.9 7.6-68.2-.1-102-5.7-25.6-11.3-39-19.9-48.3-9.3-10.1-23.7-15.9-42.5-17.1l-9.5-.6v-102c0-94.2.1-102.6 1.8-110.5 9.2-43.6 38.7-77 80.4-91 17.7-5.9 15.2-5.8 141.6-5.9L397 48v423.5zM651.5 50.9c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.2 1.5 24.4 1.5 108.8v100.2l-8.2.8c-17.1 1.4-32.5 7.5-40.5 15.8-5.5 5.6-10.5 15-14.7 27.7-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 9.7 9.7 22.6 14.9 39.9 16.1l8.7.6V895H407V47.9l117.8.4 117.7.3 9 2.3zm92.5 1010c0 172.4.3 164.6-6.1 183.5-13.4 40-47.4 70-89.9 79.2-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.7-8.6c-.8-10.3-4.3-23-8.2-30-8.3-14.9-24-23.3-57.9-30.9-23.8-5.4-54.3-7.2-76-4.6-21.2 2.5-48 9.3-60.9 15.5-18.5 8.7-28.1 24.5-30.3 49.6l-.8 8.4-53 .3c-57.6.3-70.7-.4-85.4-4.3-24.3-6.6-47.8-22.5-63.5-43-7.7-10.1-16.6-27.7-19.6-38.6-5.1-18.8-5-15.5-5-181.2V904h687v156.9z" />
|
||||
<path d="M192 419.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM581.1 421.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2zM388.3 1125.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7M397 471.5V895H57V592.3l9.8-.6c17.2-1.2 31.4-6.3 40.8-15 8.8-8 16-24.7 21.9-51.2 7.6-33.9 7.6-68.2-.1-102-5.7-25.6-11.3-39-19.9-48.3-9.3-10.1-23.7-15.9-42.5-17.1l-9.5-.6v-102c0-94.2.1-102.6 1.8-110.5 9.2-43.6 38.7-77 80.4-91 17.7-5.9 15.2-5.8 141.6-5.9L397 48zM651.5 50.9c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.2 1.5 24.4 1.5 108.8v100.2l-8.2.8c-17.1 1.4-32.5 7.5-40.5 15.8-5.5 5.6-10.5 15-14.7 27.7-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 9.7 9.7 22.6 14.9 39.9 16.1l8.7.6V895H407V47.9l117.8.4 117.7.3zm92.5 1010c0 172.4.3 164.6-6.1 183.5-13.4 40-47.4 70-89.9 79.2-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.7-8.6c-.8-10.3-4.3-23-8.2-30-8.3-14.9-24-23.3-57.9-30.9-23.8-5.4-54.3-7.2-76-4.6-21.2 2.5-48 9.3-60.9 15.5-18.5 8.7-28.1 24.5-30.3 49.6l-.8 8.4-53 .3c-57.6.3-70.7-.4-85.4-4.3-24.3-6.6-47.8-22.5-63.5-43-7.7-10.1-16.6-27.7-19.6-38.6-5.1-18.8-5-15.5-5-181.2V904h687z" />
|
||||
<path d="M192 419.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M581.1 421.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2M388.3 1125.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const TwoPlayersOppositeLandscape = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zM396 687v639H285.3c-63.3 0-115-.5-120.7-1-32.5-3.2-63-20.2-83-46.5-7.7-10.1-16.6-27.7-19.6-38.6-5.1-19-5-11.7-5-230.5V805.3l11.3-.6c18.4-1 32.5-6 42.3-15C125.7 776 138.1 730 138.1 688c0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.7-45.7l-11.7-.6.3-209.6.3-209.6 2.1-9c2.9-11.9 5.2-18.4 10.3-28.6C83.9 86 109.2 64.3 139.7 54c17.7-5.9 15.3-5.8 141.1-5.9L396 48v639zM651.5 50.9c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.4 1.5 36.5 1.5 214.8v206.2l-11.7.6c-14 .7-24.9 3.3-34.2 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.7 10.7 23.1 15.2 43.9 16.1l12.7.6v207.2c0 227.9.3 214.7-6.1 233.9-13.7 41-49.7 71.9-92.9 79.7-6.1 1.1-29.8 1.4-123.5 1.4h-116l-.3-638.8-.2-638.8 118.7.4 118.8.3 9 2.3z" />
|
||||
<path d="M195 632.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM573.1 633.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7M396 687v639H285.3c-63.3 0-115-.5-120.7-1-32.5-3.2-63-20.2-83-46.5-7.7-10.1-16.6-27.7-19.6-38.6-5.1-19-5-11.7-5-230.5V805.3l11.3-.6q27.6-1.5 42.3-15C125.7 776 138.1 730 138.1 688c0-23.9-3.5-47.1-10.7-71-9.4-31.3-25.9-44.2-58.7-45.7l-11.7-.6.3-209.6.3-209.6 2.1-9c2.9-11.9 5.2-18.4 10.3-28.6C83.9 86 109.2 64.3 139.7 54c17.7-5.9 15.3-5.8 141.1-5.9L396 48zM651.5 50.9c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.4 1.5 36.5 1.5 214.8v206.2l-11.7.6c-14 .7-24.9 3.3-34.2 8.2-12.2 6.4-19 15.9-25.5 35.5-13.2 40-15.3 83.2-6 124.8 5.8 25.6 11.8 39.8 20.8 48.8 10.7 10.7 23.1 15.2 43.9 16.1l12.7.6v207.2c0 227.9.3 214.7-6.1 233.9-13.7 41-49.7 71.9-92.9 79.7-6.1 1.1-29.8 1.4-123.5 1.4h-116l-.3-638.8-.2-638.8 118.7.4 118.8.3z" />
|
||||
<path d="M195 632.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M573.1 633.5c-14.3 4.6-27 15.7-33.3 29.1-10.4 22.2-6.2 46.1 11.1 63.5 11.5 11.5 24.2 16.9 39.9 16.9 23.6 0 45.3-15.9 53.3-39 3.1-9.2 3.2-23.7.1-33.7-3.9-12.7-12.9-24.1-24.9-31.6-12.5-7.9-31.4-10-46.2-5.2" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const TwoPlayersOppositePortrait = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zm123.9 39.6c1.2 20.3 6.6 34.2 16.8 44 10.3 9.8 39.8 19.5 72.3 23.8 13.9 1.8 40.1 2.1 53 .5 21.2-2.5 48-9.3 60.9-15.5 19.3-9.2 28.8-25.6 30.3-52.3l.6-11.3 62.1.3c61.6.3 62.2.3 71.6 2.7 48.7 12.2 83.1 48.6 91.5 96.8 1.3 7.4 1.5 43.1 1.5 272.9V685H57l.3-266.8.3-266.7 2.1-9c2.9-12 5.2-18.4 10.3-28.6C83.9 86 109.2 64.3 139.7 54c16.6-5.5 20.4-5.8 84.4-5.9l58.6-.1.7 10.7zM744 955.9c0 288.1.4 269.2-6.1 288.5-13.4 40-47.4 70-89.9 79.2-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.6-11.3c-1.5-27-10.8-43.5-29.8-52.6-13.9-6.7-36.6-12.7-59.4-15.7-13.9-1.8-40-2.1-53-.5-21.2 2.5-48 9.3-60.9 15.5-19.4 9.2-28.8 25.7-30.5 53l-.6 11-53 .3c-57.6.3-70.7-.4-85.4-4.3-24.3-6.6-47.8-22.5-63.5-43-7.7-10.1-16.6-27.7-19.6-38.6-5.2-19.2-5-7.3-5-286.2V694h687v261.9z" />
|
||||
<path d="M391.8 143c-16.5 3-30 12.2-39.1 26.7-7.9 12.6-10 31-5.2 46.1 4.5 14.4 15.5 26.9 29.1 33.4 22.1 10.4 46.1 6.2 63.5-11.1 11.5-11.5 16.9-24.2 16.9-39.9 0-23.4-16.1-45.5-38.6-53.1-7.1-2.3-19.8-3.4-26.6-2.1zM388.3 1119.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7m123.9 39.6c1.2 20.3 6.6 34.2 16.8 44 10.3 9.8 39.8 19.5 72.3 23.8 13.9 1.8 40.1 2.1 53 .5 21.2-2.5 48-9.3 60.9-15.5 19.3-9.2 28.8-25.6 30.3-52.3l.6-11.3 62.1.3c61.6.3 62.2.3 71.6 2.7 48.7 12.2 83.1 48.6 91.5 96.8 1.3 7.4 1.5 43.1 1.5 272.9V685H57l.3-266.8.3-266.7 2.1-9c2.9-12 5.2-18.4 10.3-28.6C83.9 86 109.2 64.3 139.7 54c16.6-5.5 20.4-5.8 84.4-5.9l58.6-.1zM744 955.9c0 288.1.4 269.2-6.1 288.5-13.4 40-47.4 70-89.9 79.2-6.3 1.4-17 1.7-68.6 2.1l-61.1.4-.6-11.3c-1.5-27-10.8-43.5-29.8-52.6-13.9-6.7-36.6-12.7-59.4-15.7-13.9-1.8-40-2.1-53-.5-21.2 2.5-48 9.3-60.9 15.5-19.4 9.2-28.8 25.7-30.5 53l-.6 11-53 .3c-57.6.3-70.7-.4-85.4-4.3-24.3-6.6-47.8-22.5-63.5-43-7.7-10.1-16.6-27.7-19.6-38.6-5.2-19.2-5-7.3-5-286.2V694h687z" />
|
||||
<path d="M391.8 143c-16.5 3-30 12.2-39.1 26.7-7.9 12.6-10 31-5.2 46.1 4.5 14.4 15.5 26.9 29.1 33.4 22.1 10.4 46.1 6.2 63.5-11.1 11.5-11.5 16.9-24.2 16.9-39.9 0-23.4-16.1-45.5-38.6-53.1-7.1-2.3-19.8-3.4-26.6-2.1M388.3 1119.5c-10.8 2.3-19 7-27.6 15.6-11.4 11.4-16.7 23.9-16.7 39.7 0 23.6 15.9 45.3 39 53.3 9.2 3.1 23.7 3.2 33.7.1 12.7-3.9 24.1-12.9 31.6-24.9 7.9-12.6 10-31 5.2-46.1-8.6-27.2-37.2-43.8-65.2-37.7" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@ const TwoPlayersSameSide = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7zm492 31.8c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.4 1.5 42.9 1.5 271.4V682H57V511.3l11.8-.6c18.9-1 32.8-5.9 42.8-15C126.7 482 139.1 436 139.1 394c0-23.9-3.5-47.1-10.7-71-9.5-31.5-25.9-44.2-59.2-45.7l-12.3-.6.4-62.6c.3-59.6.4-63 2.5-71.6 2.8-11.9 5.1-18.4 10.2-28.6C83.9 86 109.2 64.3 139.7 54c18.5-6.2 3.5-5.8 264.3-5.6l238.5.1 9 2.4zm92.5 904c0 289.2.4 270.2-6.1 289.5-13.4 40-47 69.6-89.9 79.3-6.9 1.6-26.1 1.7-239 2-154.7.3-235.3 0-243-.7-20.8-1.8-38.3-8-55.8-19.7-28.1-18.7-46.6-48.2-51.8-82.8-1.1-6.8-1.4-23.1-1.4-67.1v-58.1l11.8-.6c18.9-1 32.8-5.9 42.8-15 15.1-13.7 27.5-59.7 27.5-101.7 0-23.9-3.5-47.1-10.7-71-9.5-31.5-25.9-44.2-59.1-45.7l-12.3-.6V692h687v262.9z" />
|
||||
<path d="M196 338.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5zM196 924.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5z" />
|
||||
<path d="M159.5 19.1c-17.6 1.8-34.7 7.2-52.2 16.4-14.4 7.5-25 15.3-36.8 27-20.3 20.4-33.6 45.2-40.7 76l-2.3 10-.3 531.5c-.2 382 0 534.3.8 541.5 2.2 20.1 7.2 36.4 16.5 54.3 7.3 14 15.2 24.6 26.7 36.1 20.1 20.1 41 31.8 70.8 39.8l10.5 2.8h497l11.7-3.2c27-7.4 47-18.5 66.9-37.1 21.5-20.2 37-48.2 43.6-79.2 1.7-8.1 1.8-30.9 1.8-548 0-518.6-.1-539.8-1.8-548-12-55.7-49.8-97.4-103.5-114.4-20.5-6.4-.6-6-262.7-6.2-130.9-.1-241.6.2-246 .7m492 31.8c5 1.3 13.2 4.1 18.4 6.2 38.5 15.7 65.4 49.3 72.6 90.6 1.3 7.4 1.5 42.9 1.5 271.4V682H57V511.3l11.8-.6c18.9-1 32.8-5.9 42.8-15C126.7 482 139.1 436 139.1 394c0-23.9-3.5-47.1-10.7-71-9.5-31.5-25.9-44.2-59.2-45.7l-12.3-.6.4-62.6c.3-59.6.4-63 2.5-71.6 2.8-11.9 5.1-18.4 10.2-28.6C83.9 86 109.2 64.3 139.7 54c18.5-6.2 3.5-5.8 264.3-5.6l238.5.1zm92.5 904c0 289.2.4 270.2-6.1 289.5-13.4 40-47 69.6-89.9 79.3-6.9 1.6-26.1 1.7-239 2-154.7.3-235.3 0-243-.7-20.8-1.8-38.3-8-55.8-19.7-28.1-18.7-46.6-48.2-51.8-82.8-1.1-6.8-1.4-23.1-1.4-67.1v-58.1l11.8-.6c18.9-1 32.8-5.9 42.8-15 15.1-13.7 27.5-59.7 27.5-101.7 0-23.9-3.5-47.1-10.7-71-9.5-31.5-25.9-44.2-59.1-45.7l-12.3-.6V692h687z" />
|
||||
<path d="M196 338.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5M196 924.6c-18.6 4.9-33.7 19-40.1 37.4-1.7 5-2.2 8.9-2.3 16.5-.1 12.8 2.5 21.5 9.4 31.8 10.7 16 27 24.7 46.4 24.7 27.2 0 49.5-18 55.1-44.6 1.8-8.7 1.8-14.1 0-22.6-4.4-21.2-22.5-39.4-43.3-43.7-7.2-1.5-18.5-1.3-25.2.5" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -21,8 +21,8 @@ const LittleGuy = ({
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<g fill="currentColor">
|
||||
<path d="M233.8 9.7c-18.1 17.5-25.6 32.5-25.8 51.5 0 5.9.7 7.8 3.1 7.8 2.8 0 3.6-2.6 4.1-13.2.4-8.9.7-10.2 4.7-18.3 3.6-7.4 6.2-10.7 15.7-20.5C241.9 10.6 247 4.6 247 3.7c0-1.2-1.9-2.7-3.6-2.7-.3 0-4.6 3.9-9.6 8.7zM36.5 54.7c-8.4.6-31.6 4.3-33.6 5.4-2.3 1.2-2.5 4.5-.3 5.3.9.3 1.9.4 2.3.2.3-.2 7.2-1.4 15.1-2.6 12.9-2 17.1-2.2 37.5-1.6 24.9.6 31.9 1.5 52.6 6.9 16.2 4.3 29 8.8 42.3 15.1 8.7 4 10.2 4.5 11.4 3.2 2.3-2.3.8-4.3-5.5-7.4C141.9 70.9 111 61 90.5 57.5c-7.8-1.4-41.4-3.7-47-3.3-1.1.1-4.2.3-7 .5zM205.8 87.6c-16.9 3-35.3 12.3-44.8 22.7-4.5 4.8-9.9 16.6-11.6 25.4-2.6 12.8-.2 40.8 4.7 56.2 8.1 25.4 34.3 55.1 55.6 63.1 12.4 4.6 17.3 5.5 31.3 5.4 7.9 0 14.6-.5 16.3-1.2 2.5-1.1 2.7-1.5 2.7-7.6v-6.5l-4.2 1.6c-6.1 2.3-24.2 2.2-32.7-.1-13.5-3.7-26.2-12.2-36.9-24.5-16.9-19.7-22.9-34.2-25.1-60.6-1.4-17.8 0-27.4 5.6-37.6 3.6-6.8 9.5-11.8 19.5-16.7 21.8-10.7 42.8-11.5 66.3-2.3l7.5 2.9V94.2l-8-2.7c-16.2-5.4-31.1-6.7-46.2-3.9z" />
|
||||
<path d="M222.5 132.5c-4.8 4.7-1.9 11.5 4.9 11.5 6.4 0 9-7.9 4-11.9-3.5-2.7-5.9-2.6-8.9.4zM184.5 152.5c-3 3-3.1 5.4-.4 8.9 4 5 11.9 2.4 11.9-4 0-6.8-6.8-9.7-11.5-4.9zM255.8 171.8c-4.7 9.7-13.3 20.3-19.5 23.8-5.9 3.3-7.3 5-7.3 8.6 0 3.6 3.2 6.8 6.8 6.8 4.1 0 12-5.1 18.5-11.8l5.7-6.1v-14.5c0-8-.1-14.6-.2-14.5-.2 0-2 3.5-4 7.7z" />
|
||||
<path d="M233.8 9.7c-18.1 17.5-25.6 32.5-25.8 51.5 0 5.9.7 7.8 3.1 7.8 2.8 0 3.6-2.6 4.1-13.2.4-8.9.7-10.2 4.7-18.3 3.6-7.4 6.2-10.7 15.7-20.5C241.9 10.6 247 4.6 247 3.7c0-1.2-1.9-2.7-3.6-2.7-.3 0-4.6 3.9-9.6 8.7M36.5 54.7c-8.4.6-31.6 4.3-33.6 5.4-2.3 1.2-2.5 4.5-.3 5.3.9.3 1.9.4 2.3.2.3-.2 7.2-1.4 15.1-2.6 12.9-2 17.1-2.2 37.5-1.6 24.9.6 31.9 1.5 52.6 6.9 16.2 4.3 29 8.8 42.3 15.1 8.7 4 10.2 4.5 11.4 3.2 2.3-2.3.8-4.3-5.5-7.4C141.9 70.9 111 61 90.5 57.5c-7.8-1.4-41.4-3.7-47-3.3-1.1.1-4.2.3-7 .5M205.8 87.6c-16.9 3-35.3 12.3-44.8 22.7-4.5 4.8-9.9 16.6-11.6 25.4-2.6 12.8-.2 40.8 4.7 56.2 8.1 25.4 34.3 55.1 55.6 63.1 12.4 4.6 17.3 5.5 31.3 5.4 7.9 0 14.6-.5 16.3-1.2 2.5-1.1 2.7-1.5 2.7-7.6v-6.5l-4.2 1.6c-6.1 2.3-24.2 2.2-32.7-.1-13.5-3.7-26.2-12.2-36.9-24.5-16.9-19.7-22.9-34.2-25.1-60.6-1.4-17.8 0-27.4 5.6-37.6 3.6-6.8 9.5-11.8 19.5-16.7 21.8-10.7 42.8-11.5 66.3-2.3l7.5 2.9V94.2l-8-2.7c-16.2-5.4-31.1-6.7-46.2-3.9" />
|
||||
<path d="M222.5 132.5c-4.8 4.7-1.9 11.5 4.9 11.5 6.4 0 9-7.9 4-11.9-3.5-2.7-5.9-2.6-8.9.4M184.5 152.5c-3 3-3.1 5.4-.4 8.9 4 5 11.9 2.4 11.9-4 0-6.8-6.8-9.7-11.5-4.9M255.8 171.8c-4.7 9.7-13.3 20.3-19.5 23.8-5.9 3.3-7.3 5-7.3 8.6s3.2 6.8 6.8 6.8c4.1 0 12-5.1 18.5-11.8l5.7-6.1v-14.5c0-8-.1-14.6-.2-14.5-.2 0-2 3.5-4 7.7" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -22,7 +22,7 @@ const Logo = ({
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path
|
||||
d="M0-196.791c108.629 0 196.791 88.162 196.791 196.791 0 108.629-88.162 196.791-196.791 196.791-108.629 0-196.791-88.162-196.791-196.791 0-108.629 88.162-196.791 196.791-196.791z"
|
||||
d="M0-196.791c108.629 0 196.791 88.162 196.791 196.791S108.63 196.791 0 196.791-196.791 108.63-196.791 0-108.63-196.791 0-196.791z"
|
||||
style={{
|
||||
stroke: '#590713',
|
||||
strokeWidth: 0,
|
||||
@@ -39,7 +39,7 @@ const Logo = ({
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
d="M-17.706-50.704s-4.378 12.973.446 25.583c2.124 5.55 12.255 17.109 17.107 36.364 4.852 19.255 19.679 39.46 19.679 39.46"
|
||||
d="M-17.706-50.704s-4.378 12.973.446 25.583c2.124 5.55 12.255 17.109 17.107 36.364s19.679 39.46 19.679 39.46"
|
||||
style={{
|
||||
stroke: '#000',
|
||||
strokeWidth: 4,
|
||||
@@ -52,12 +52,12 @@ const Logo = ({
|
||||
fillRule: 'nonzero',
|
||||
opacity: 1,
|
||||
}}
|
||||
transform="rotate(1 -17129.538 10072.475) scale(2.11279)"
|
||||
transform="rotate(1 -17129.538 10072.475)scale(2.11279)"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
d="M50.163 56.172S31.68 34 24.46 3.6C17.239-26.8 13.467-35.306 2.42-47.373c-11.046-12.066-26.224-12.189-25.26 2.534.966 14.722 12.84 12.598 14.365 1.93 1.526-10.667-21.8-10.696-32.304 1.854C-53.573-25.77-49.57-2.79-49.57-2.79"
|
||||
d="M50.163 56.172S31.68 34 24.46 3.6 13.467-35.306 2.42-47.373c-11.046-12.066-26.224-12.189-25.26 2.534.966 14.722 12.84 12.598 14.365 1.93 1.526-10.667-21.8-10.696-32.304 1.854C-53.573-25.77-49.57-2.79-49.57-2.79"
|
||||
style={{
|
||||
stroke: '#000',
|
||||
strokeWidth: 6,
|
||||
@@ -76,7 +76,7 @@ const Logo = ({
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
d="M-61.541-71.832s39.965 62.644 41.684 89.093c1.718 26.45 7.326 33.328 17.516 44.667 10.19 11.339 36.055 16.684 32.478-4.845-3.578-21.53-29.514-8.071-16.735 4.07 12.779 12.143 30.514 9.462 39.88-2.368 6.188-7.814 9.732-26.682 7.67-41.524-1.059-7.627-14.72-28.434-14.72-28.434"
|
||||
d="M-61.541-71.832s39.965 62.644 41.684 89.093 7.326 33.328 17.516 44.667 36.055 16.684 32.478-4.845c-3.578-21.53-29.514-8.071-16.735 4.07 12.779 12.143 30.514 9.462 39.88-2.368 6.188-7.814 9.732-26.682 7.67-41.524-1.059-7.627-14.72-28.434-14.72-28.434"
|
||||
style={{
|
||||
stroke: '#000',
|
||||
strokeWidth: 6,
|
||||
@@ -95,7 +95,7 @@ const Logo = ({
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
d="M-26.889-69.574S-9.544-51.826-3.454-23.78c6.09 28.046 24.518 40.828 27.8 61.071 3.284 20.244 3.494 23.63 0 32.283"
|
||||
d="M-26.889-69.574S-9.544-51.826-3.454-23.78s24.518 40.828 27.8 61.071c3.284 20.244 3.494 23.63 0 32.283"
|
||||
style={{
|
||||
stroke: '#000',
|
||||
strokeWidth: 6,
|
||||
@@ -114,7 +114,7 @@ const Logo = ({
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
d="M30.481-85.77S31.897-63.74-.082-1.032C-32.06 61.673-30.478 85.769-30.478 85.769"
|
||||
d="M30.481-85.77S31.897-63.74-.082-1.032s-30.396 86.802-30.396 86.802"
|
||||
style={{
|
||||
stroke: '#000',
|
||||
strokeWidth: 6,
|
||||
@@ -133,7 +133,7 @@ const Logo = ({
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
d="M-30.017 97.228S-.607 52.493 6.833 6.645c7.44-45.849 23.184-103.873 23.184-103.873"
|
||||
d="M-30.017 97.228S-.607 52.493 6.833 6.645 30.016-97.228 30.016-97.228"
|
||||
style={{
|
||||
stroke: '#000',
|
||||
strokeWidth: 6,
|
||||
@@ -152,7 +152,7 @@ const Logo = ({
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
d="M-24.23-79.242s-7.454 19.782-.69 39.5c2.979 8.68 17.988 27.06 24.437 57.033 6.45 29.973 28.24 61.951 28.24 61.951"
|
||||
d="M-24.23-79.242s-7.454 19.782-.69 39.5c2.979 8.68 17.988 27.06 24.437 57.033s28.24 61.951 28.24 61.951"
|
||||
style={{
|
||||
stroke: '#000',
|
||||
strokeWidth: 1,
|
||||
@@ -166,11 +166,11 @@ const Logo = ({
|
||||
fillRule: 'nonzero',
|
||||
opacity: 1,
|
||||
}}
|
||||
transform="rotate(-1.005 17359.092 -9769.972) scale(1.36839)"
|
||||
transform="rotate(-1.005 17359.092 -9769.972)scale(1.36839)"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
d="M-45.63-48.464C-71.24-37.592-84.397-27.166-91.043-20.02c-4.07 4.376-3.966 4.338-5.24 6.898a4.617 4.617 0 0 0 .396 4.766c.894 1.234.96 1.326 2.899 3.595C-83.146 6.756-56.46 32.52-4.814 47.45c44.828 12.96 74.528 12.437 89.557 10.58 2.68-.332 2.726-.3 4.041-.593a10.178 10.178 0 0 0 7.957-9.425c.047-.93.022-1.057-.024-2.821-.34-12.824-3.372-35.645-18.26-58.984-22.56-35.37-46.732-40.492-46.732-40.492S.657-68.114-45.63-48.464z"
|
||||
d="M-45.63-48.464C-71.24-37.592-84.397-27.166-91.043-20.02c-4.07 4.376-3.966 4.338-5.24 6.898a4.62 4.62 0 0 0 .396 4.766c.894 1.234.96 1.326 2.899 3.595C-83.146 6.756-56.46 32.52-4.814 47.45c44.828 12.96 74.528 12.437 89.557 10.58 2.68-.332 2.726-.3 4.041-.593a10.18 10.18 0 0 0 7.957-9.425c.047-.93.022-1.057-.024-2.821-.34-12.824-3.372-35.645-18.26-58.984-22.56-35.37-46.732-40.492-46.732-40.492S.657-68.114-45.63-48.464z"
|
||||
style={{
|
||||
stroke: '#000',
|
||||
strokeWidth: 6,
|
||||
@@ -225,7 +225,7 @@ const Logo = ({
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
d="M-90.654-77.091S-74.41-28.509-9.055-2.309C56.299 23.89 100.897 9.078 100.897 9.078S61.451 101.65-37.09 70.793C-135.63 39.936-90.654-77.09-90.654-77.09z"
|
||||
d="M-90.654-77.091S-74.41-28.509-9.055-2.309C56.299 23.89 100.897 9.078 100.897 9.078S61.451 101.65-37.09 70.793-90.654-77.09-90.654-77.09z"
|
||||
style={{
|
||||
stroke: '#000',
|
||||
strokeWidth: 6,
|
||||
|
||||
@@ -22,7 +22,7 @@ const PartnerTax = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M196.7 79.1c-2.1.5-5 1.5-6.5 2.3-3.3 1.8-17.6 16.3-59.3 60.1-60 63.1-60.2 63.3-62.2 78.5-1.7 13.3 1.4 24.2 10 34.7 6.5 7.9 10.6 9.9 40.8 19.8 29.9 9.8 33 11 30.5 11.9-.8.3-8 3.1-16 6.1-8 3.1-19.7 7.5-26 9.9-20.7 7.9-40.3 15.7-45 18.1-2.6 1.3-7.2 5.1-10.2 8.4-6.6 7.1-7.2 8.7-17.9 47.6-19.1 69.1-21.3 78.3-20.3 84.8 1.6 9.6 7.1 16.9 16.3 21.7l4 2 233.6-.2 233.7-.3 3.3-3.7c5.2-5.6 5.3-7.6 1.6-22.3-5.9-23.2-13.2-47.9-15.3-51.3-3.3-5.3-7.3-7.5-30-16.3-12-4.6-21.8-8.6-21.8-8.9 0-.3 6.6-2.7 14.8-5.4 16.2-5.3 19.9-7.5 23.8-14.3 3.4-5.6 3.7-13.7.8-20-1.9-4.2-32.4-37.2-52.7-57.1-9-8.8-9.6-9.2-13.8-9.2-2.4.1-5.4.6-6.5 1.3-1.8 1-17.1 16.5-46 46.6l-7.2 7.5-3.3-3.5c-7.4-7.7-11.5-9.6-79.6-35.9-9-3.5-16.3-6.7-16.3-7.1 0-.4 12.5-4.8 27.8-9.8 16.3-5.3 29.6-10.2 32.2-11.9 6-3.8 13.3-11.8 16.3-17.8 7-13.9 5.4-33.5-3.8-45.3-7.2-9.1-103-109.8-110.2-115.7-5.8-4.8-13.2-6.7-19.6-5.3zm34.8 84.4c5.5 1.4 12.2 3.3 14.9 4.2l4.8 1.5-.6 4.6c-1 7.4-11.3 36.9-16.3 46.8-2.5 5.1-7.6 13.4-11.3 18.5-5.4 7.6-7.7 9.9-12 12.1-6.8 3.6-12.8 3.7-19.7.3-5.8-2.9-9.3-6.8-18.2-20.5-8.2-12.5-13.2-23.1-17.5-37.1-5.1-17-6.4-23.8-4.6-24.9.8-.5 7.9-2.5 15.9-4.4 8.1-1.9 15.5-3.8 16.6-4 1.1-.3 10.1-.3 20-.1 15.1.4 19.6.8 28 3zm-76.1 88.4 46.9 23.5 51.8-25.9c28.5-14.3 52.1-25.7 52.4-25.3.8.8-1.8 7-3.6 8.4-3.9 3.1-93.1 50.5-98.6 52.5-3.1 1-4.2.6-19-7.1-23.6-12.4-66.7-35.6-75.5-40.7-7.6-4.4-11.8-8.5-11.8-11.6 0-2.4 4.5-.3 57.4 26.2zM418.5 318c12 1.2 19.5 3.5 19.5 5.9 0 3.7-7.2 22.7-11 29.2-5.4 9.1-9.9 12.9-15.2 12.9-3.7 0-4.7-.6-8.7-4.8-5.3-5.5-12-17.7-15-27.6-3.2-10.5-3.1-11.3 3.2-13.1 12.1-3.5 15-3.8 27.2-2.5zM88.6 354.5c1.4 3.2 2.4 7.5 2.4 10.1 0 6-14 102.3-15.7 107.8-.5 1.8-.6 1.8-1.5.1-1.4-2.4-7.8-23.3-7.8-25.4-.1-3.8 18.5-98.1 19.2-98.1.5 0 2 2.5 3.4 5.5zm239.8 43.3c5.3 26.8 9.6 49.4 9.6 50.1 0 2.1-9.2 28.1-9.9 28.1-.4 0-1.9-7.8-3.4-17.3-1.4-9.4-5.4-34.7-8.7-56l-6-38.8 3.4-7.4c1.9-4.1 3.9-7.5 4.4-7.5.5 0 5.3 21.9 10.6 48.8zm136.5-43.3c-3 2.9-50.1 27.5-52.5 27.5-1.1 0-8.6-3.6-16.9-8.1-8.2-4.4-18.9-10.1-23.7-12.6-8-4.2-10.8-6.7-9.3-8.2.3-.3 11.7 5 25.3 11.8l24.7 12.3 27-13.5c25.2-12.6 31.2-14.8 25.4-9.2zm-86.6 25.1c4.3 1.4 7.7 2.8 7.5 3-.2.2-3.4 1.5-7.1 2.9l-6.6 2.5-1.6-5.2c-.8-2.8-1.5-5.3-1.5-5.5 0-.6 1.7-.2 9.3 2.3zm100.1 62.8 4.5 23.4-2.3 6.9c-2.9 8.4-2.5 9.8-7.6-24.5-3.7-25.3-3.8-26.5-2.2-29.8 1.5-3.2 1.7-3.3 2.4-1.5.4 1.1 2.7 12.6 5.2 25.5z" />
|
||||
<path d="M196.7 79.1c-2.1.5-5 1.5-6.5 2.3-3.3 1.8-17.6 16.3-59.3 60.1-60 63.1-60.2 63.3-62.2 78.5-1.7 13.3 1.4 24.2 10 34.7 6.5 7.9 10.6 9.9 40.8 19.8 29.9 9.8 33 11 30.5 11.9-.8.3-8 3.1-16 6.1-8 3.1-19.7 7.5-26 9.9-20.7 7.9-40.3 15.7-45 18.1-2.6 1.3-7.2 5.1-10.2 8.4-6.6 7.1-7.2 8.7-17.9 47.6-19.1 69.1-21.3 78.3-20.3 84.8 1.6 9.6 7.1 16.9 16.3 21.7l4 2 233.6-.2 233.7-.3 3.3-3.7c5.2-5.6 5.3-7.6 1.6-22.3-5.9-23.2-13.2-47.9-15.3-51.3-3.3-5.3-7.3-7.5-30-16.3-12-4.6-21.8-8.6-21.8-8.9s6.6-2.7 14.8-5.4c16.2-5.3 19.9-7.5 23.8-14.3 3.4-5.6 3.7-13.7.8-20-1.9-4.2-32.4-37.2-52.7-57.1-9-8.8-9.6-9.2-13.8-9.2-2.4.1-5.4.6-6.5 1.3-1.8 1-17.1 16.5-46 46.6l-7.2 7.5-3.3-3.5c-7.4-7.7-11.5-9.6-79.6-35.9-9-3.5-16.3-6.7-16.3-7.1s12.5-4.8 27.8-9.8c16.3-5.3 29.6-10.2 32.2-11.9 6-3.8 13.3-11.8 16.3-17.8 7-13.9 5.4-33.5-3.8-45.3-7.2-9.1-103-109.8-110.2-115.7-5.8-4.8-13.2-6.7-19.6-5.3m34.8 84.4c5.5 1.4 12.2 3.3 14.9 4.2l4.8 1.5-.6 4.6c-1 7.4-11.3 36.9-16.3 46.8-2.5 5.1-7.6 13.4-11.3 18.5-5.4 7.6-7.7 9.9-12 12.1-6.8 3.6-12.8 3.7-19.7.3-5.8-2.9-9.3-6.8-18.2-20.5-8.2-12.5-13.2-23.1-17.5-37.1-5.1-17-6.4-23.8-4.6-24.9.8-.5 7.9-2.5 15.9-4.4 8.1-1.9 15.5-3.8 16.6-4 1.1-.3 10.1-.3 20-.1 15.1.4 19.6.8 28 3m-76.1 88.4 46.9 23.5 51.8-25.9c28.5-14.3 52.1-25.7 52.4-25.3.8.8-1.8 7-3.6 8.4-3.9 3.1-93.1 50.5-98.6 52.5-3.1 1-4.2.6-19-7.1-23.6-12.4-66.7-35.6-75.5-40.7-7.6-4.4-11.8-8.5-11.8-11.6 0-2.4 4.5-.3 57.4 26.2M418.5 318c12 1.2 19.5 3.5 19.5 5.9 0 3.7-7.2 22.7-11 29.2-5.4 9.1-9.9 12.9-15.2 12.9-3.7 0-4.7-.6-8.7-4.8-5.3-5.5-12-17.7-15-27.6-3.2-10.5-3.1-11.3 3.2-13.1 12.1-3.5 15-3.8 27.2-2.5M88.6 354.5c1.4 3.2 2.4 7.5 2.4 10.1 0 6-14 102.3-15.7 107.8-.5 1.8-.6 1.8-1.5.1-1.4-2.4-7.8-23.3-7.8-25.4-.1-3.8 18.5-98.1 19.2-98.1.5 0 2 2.5 3.4 5.5m239.8 43.3c5.3 26.8 9.6 49.4 9.6 50.1 0 2.1-9.2 28.1-9.9 28.1-.4 0-1.9-7.8-3.4-17.3-1.4-9.4-5.4-34.7-8.7-56l-6-38.8 3.4-7.4c1.9-4.1 3.9-7.5 4.4-7.5s5.3 21.9 10.6 48.8m136.5-43.3c-3 2.9-50.1 27.5-52.5 27.5-1.1 0-8.6-3.6-16.9-8.1-8.2-4.4-18.9-10.1-23.7-12.6-8-4.2-10.8-6.7-9.3-8.2.3-.3 11.7 5 25.3 11.8l24.7 12.3 27-13.5c25.2-12.6 31.2-14.8 25.4-9.2m-86.6 25.1c4.3 1.4 7.7 2.8 7.5 3s-3.4 1.5-7.1 2.9l-6.6 2.5-1.6-5.2c-.8-2.8-1.5-5.3-1.5-5.5 0-.6 1.7-.2 9.3 2.3m100.1 62.8 4.5 23.4-2.3 6.9c-2.9 8.4-2.5 9.8-7.6-24.5-3.7-25.3-3.8-26.5-2.2-29.8 1.5-3.2 1.7-3.3 2.4-1.5.4 1.1 2.7 12.6 5.2 25.5" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ const Poison = ({
|
||||
{...props}
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path d="M261.6 32.1 228 57.2v60.5l-6.7 1.2c-16.1 2.9-39.8 10.8-54.6 18.2-9.7 4.9-27.4 17-36.5 24.9-24.3 21.3-40.6 49-46.3 79-1.6 8.3-1.6 33.5 0 42 4.3 22.8 16.3 46.9 32.3 64.6 26 28.9 60 47.5 104 56.9l7.8 1.6.2 55.8.3 55.7 34-25.2 34-25.2.5-30.8.5-30.8 10.5-2.2c27-5.6 54.2-17.8 75.5-33.8 77.9-58.4 77.4-158.4-1.2-216.5-22.5-16.7-46.6-27.2-77-33.7l-8.3-1.7V62.3c0-30.8-.4-55.3-.9-55.3s-16 11.3-34.5 25.1zM228 262v89l-2.7-.6c-5.3-1.3-14.8-5.1-23.8-9.7-31-15.5-50.5-41.7-53.4-71.4-2.5-25.1 6.9-48.5 27-67.8 9.4-9 15.7-13.4 27.6-19.4 7.8-3.9 21.4-9 24.1-9.1.9 0 1.2 18.5 1.2 89zm76.1-86.9c33.2 10.8 58.9 34.5 68.6 63.4 2.5 7.4 2.7 9.2 2.7 23.5 0 14.2-.3 16.2-2.8 23.5-6.7 19.6-18.7 35-37.3 47.8-7.1 4.9-25.9 14-33 16l-5.3 1.5v-88.9c0-48.9.2-88.9.3-88.9.2 0 3.3.9 6.8 2.1z" />
|
||||
<path d="M261.6 32.1 228 57.2v60.5l-6.7 1.2c-16.1 2.9-39.8 10.8-54.6 18.2-9.7 4.9-27.4 17-36.5 24.9-24.3 21.3-40.6 49-46.3 79-1.6 8.3-1.6 33.5 0 42 4.3 22.8 16.3 46.9 32.3 64.6 26 28.9 60 47.5 104 56.9l7.8 1.6.2 55.8.3 55.7 34-25.2 34-25.2.5-30.8.5-30.8 10.5-2.2c27-5.6 54.2-17.8 75.5-33.8 77.9-58.4 77.4-158.4-1.2-216.5-22.5-16.7-46.6-27.2-77-33.7l-8.3-1.7V62.3c0-30.8-.4-55.3-.9-55.3s-16 11.3-34.5 25.1M228 262v89l-2.7-.6c-5.3-1.3-14.8-5.1-23.8-9.7-31-15.5-50.5-41.7-53.4-71.4-2.5-25.1 6.9-48.5 27-67.8 9.4-9 15.7-13.4 27.6-19.4 7.8-3.9 21.4-9 24.1-9.1.9 0 1.2 18.5 1.2 89m76.1-86.9c33.2 10.8 58.9 34.5 68.6 63.4 2.5 7.4 2.7 9.2 2.7 23.5 0 14.2-.3 16.2-2.8 23.5-6.7 19.6-18.7 35-37.3 47.8-7.1 4.9-25.9 14-33 16l-5.3 1.5v-88.9c0-48.9.2-88.9.3-88.9.2 0 3.3.9 6.8 2.1" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ const ResetGame = ({
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M129.3 50.7C105.7 81.6 95 95.8 82.6 113c-14.3 19.7-16.7 25.2-14.6 33.2 2.5 9.4 9 14.2 21.3 15.8 8.2 1.1 116.4 3.7 117.2 2.8.3-.3-3.3-8.8-8-18.8s-8.8-19.3-9.1-20.5c-.5-2.1-.1-2.3 8.3-3.4 4.9-.6 20.3-1.6 34.2-2.2 65.4-2.7 102.7 6.4 133.2 32.4 31.4 26.8 48.8 75.9 44.9 126.8-6.7 87.6-61.2 133.4-155.3 130.6-45.4-1.3-78.1-13.8-103.7-39.6-23.5-23.8-39-60.5-41.9-99.4-.9-12-2-15.4-6.7-20-5.2-5.2-7.9-5.7-29.3-5.6-24 .1-27.9 1.2-32.1 9.5-1.6 3-2 5.9-2 13.9 0 35.9 12.4 76.8 32.8 108 34.1 52.5 88.1 87.3 152.2 98.2 16.3 2.8 57.2 2.5 73.5-.5 46.1-8.4 84.5-28.3 116.4-60.3 42.5-42.7 65-104 60.3-164.1-4.2-52.8-25-98.7-61.2-134.8-38.8-38.8-87.2-59.7-145-62.6-24.6-1.2-73.1 2.8-99.1 8.2-2.5.5-2.9-.2-10.9-17.1-4.6-9.6-8.7-17.5-9.1-17.5-.3 0-9.1 11.1-19.6 24.7z"
|
||||
d="M129.3 50.7C105.7 81.6 95 95.8 82.6 113c-14.3 19.7-16.7 25.2-14.6 33.2 2.5 9.4 9 14.2 21.3 15.8 8.2 1.1 116.4 3.7 117.2 2.8.3-.3-3.3-8.8-8-18.8s-8.8-19.3-9.1-20.5c-.5-2.1-.1-2.3 8.3-3.4 4.9-.6 20.3-1.6 34.2-2.2 65.4-2.7 102.7 6.4 133.2 32.4 31.4 26.8 48.8 75.9 44.9 126.8-6.7 87.6-61.2 133.4-155.3 130.6-45.4-1.3-78.1-13.8-103.7-39.6-23.5-23.8-39-60.5-41.9-99.4-.9-12-2-15.4-6.7-20-5.2-5.2-7.9-5.7-29.3-5.6-24 .1-27.9 1.2-32.1 9.5-1.6 3-2 5.9-2 13.9 0 35.9 12.4 76.8 32.8 108 34.1 52.5 88.1 87.3 152.2 98.2 16.3 2.8 57.2 2.5 73.5-.5 46.1-8.4 84.5-28.3 116.4-60.3 42.5-42.7 65-104 60.3-164.1-4.2-52.8-25-98.7-61.2-134.8-38.8-38.8-87.2-59.7-145-62.6-24.6-1.2-73.1 2.8-99.1 8.2-2.5.5-2.9-.2-10.9-17.1-4.6-9.6-8.7-17.5-9.1-17.5-.3 0-9.1 11.1-19.6 24.7"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -21,8 +21,8 @@ const Skull = ({
|
||||
>
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<g fill="currentColor">
|
||||
<path d="M237.2 37.1c-30.6 2.9-64.8 15-89.4 31.6-12.2 8.2-31.7 23.4-38.3 30-15.2 14.9-24.6 33.8-27.5 55.1-4.5 32.9 10.8 64.5 38.7 79.8 16.3 8.9 22.3 12.7 28.1 18 15 13.5 23.5 31.4 24.9 52.3.8 11.5 3.2 17.9 8.9 23.1 8.6 7.9 4.4 7.5 73.4 7.5 60.6 0 61.6 0 66-2.1 10-4.8 14.7-12.3 16-25.7 1.3-12.5 1.8-15.2 4.2-22.7 3.9-12.1 11.9-24.4 21.2-32.7 5.5-4.9 8.1-6.5 25.3-16 16.4-9.1 26.1-19.1 33.9-34.8 5.6-11.4 7.4-18.5 8.1-30.8 1.5-26.6-9.6-54.2-29.4-72.7-8.8-8.3-27.3-22.7-38.3-29.8-35.8-23.3-82.1-34.3-125.8-30.1zm-46 72c15 3.2 26.2 13.8 28.7 27.3 1.7 9.2-2.6 18.2-14 29.7-14.1 14.1-28.2 21.9-40.9 22.6-6.6.4-7.9.2-11-1.9-7.5-5-10.9-17.2-11-39 0-14.7 1.9-20.6 8.9-27.6 10.1-10 24.7-14.2 39.3-11.1zm145 0c11.6 2.5 22.7 10.8 26.9 20.2 2.2 4.8 2.4 6.4 2.3 20.7-.1 22.2-3.1 32.2-11 37.1-2.9 1.8-4.6 2.1-10.8 1.7-6.2-.3-8.6-1-15.9-4.6-15.2-7.5-30.9-21.8-36.5-33.2-11.3-23.1 15.6-48.1 45-41.9zm-73.5 102.8c4.7 3.4 11.8 13.7 13.3 19.3 2 7.3-2 13.6-11.5 17.9-12.1 5.6-29.5-2.7-29.5-14.1 0-6.8 7.2-19 13.9-23.6 4.8-3.2 8.9-3.1 13.8.5z" />
|
||||
<path d="M56.8 304.7c-1.4 1-3.6 3.1-4.9 4.6-5.1 6.6-8.2 25.8-4.7 29.3 2.9 2.9 19.8 7.1 67.8 16.9 36.1 7.4 79 17.5 79 18.7 0 .4-.6.8-1.4.8-2.3 0-73.5 23.6-95.6 31.7-20.8 7.6-40.7 16.4-44.8 19.9-1.6 1.3-2.7 4.1-3.8 9.4-2.9 14.3.2 20.8 12.5 25.5 6.3 2.4 7.3 2.5 11.7 1.4 6.2-1.6 18.9-6.3 48.4-18.2 56.7-22.9 114.7-42.6 140.7-47.7l5.8-1.2 24.5 8.5c13.5 4.7 45.2 16 70.5 25.2 78.6 28.6 95.9 34 101.1 31.6 3.2-1.4 5.4-6.7 5.4-12.8 0-9.6-3.3-16.3-10.8-22-4.8-3.6-8.7-4.9-27.7-8.8-7.1-1.5-15.9-3.8-19.5-5.2-3.6-1.3-17.1-6.5-30-11.5-12.9-4.9-30.4-11.4-38.8-14.4-8.4-2.9-15.8-5.7-16.4-6-.6-.4 4.2-2.2 10.8-4.1 11.6-3.3 27-7.7 58.3-16.9 17.6-5.2 48.9-16.6 54.1-19.6 8.8-5.2 14.8-13.3 17.4-23.3 1.3-5.3 1.4-6.2.1-8.2-2-3-5.3-3.7-13.4-2.9-19.7 1.8-89.3 19.4-175.4 44l-29.8 8.6-18.2-5.1c-20.2-5.6-63.5-18.8-91.2-27.9-18.1-5.9-52.3-16.5-62.5-19.4-9.6-2.7-16.1-3-19.2-.9z" />
|
||||
<path d="M237.2 37.1c-30.6 2.9-64.8 15-89.4 31.6-12.2 8.2-31.7 23.4-38.3 30-15.2 14.9-24.6 33.8-27.5 55.1-4.5 32.9 10.8 64.5 38.7 79.8 16.3 8.9 22.3 12.7 28.1 18 15 13.5 23.5 31.4 24.9 52.3.8 11.5 3.2 17.9 8.9 23.1 8.6 7.9 4.4 7.5 73.4 7.5 60.6 0 61.6 0 66-2.1 10-4.8 14.7-12.3 16-25.7 1.3-12.5 1.8-15.2 4.2-22.7 3.9-12.1 11.9-24.4 21.2-32.7 5.5-4.9 8.1-6.5 25.3-16 16.4-9.1 26.1-19.1 33.9-34.8 5.6-11.4 7.4-18.5 8.1-30.8 1.5-26.6-9.6-54.2-29.4-72.7-8.8-8.3-27.3-22.7-38.3-29.8-35.8-23.3-82.1-34.3-125.8-30.1m-46 72c15 3.2 26.2 13.8 28.7 27.3 1.7 9.2-2.6 18.2-14 29.7-14.1 14.1-28.2 21.9-40.9 22.6-6.6.4-7.9.2-11-1.9-7.5-5-10.9-17.2-11-39 0-14.7 1.9-20.6 8.9-27.6 10.1-10 24.7-14.2 39.3-11.1m145 0c11.6 2.5 22.7 10.8 26.9 20.2 2.2 4.8 2.4 6.4 2.3 20.7-.1 22.2-3.1 32.2-11 37.1-2.9 1.8-4.6 2.1-10.8 1.7-6.2-.3-8.6-1-15.9-4.6-15.2-7.5-30.9-21.8-36.5-33.2-11.3-23.1 15.6-48.1 45-41.9m-73.5 102.8c4.7 3.4 11.8 13.7 13.3 19.3 2 7.3-2 13.6-11.5 17.9-12.1 5.6-29.5-2.7-29.5-14.1 0-6.8 7.2-19 13.9-23.6 4.8-3.2 8.9-3.1 13.8.5" />
|
||||
<path d="M56.8 304.7c-1.4 1-3.6 3.1-4.9 4.6-5.1 6.6-8.2 25.8-4.7 29.3 2.9 2.9 19.8 7.1 67.8 16.9 36.1 7.4 79 17.5 79 18.7 0 .4-.6.8-1.4.8-2.3 0-73.5 23.6-95.6 31.7-20.8 7.6-40.7 16.4-44.8 19.9-1.6 1.3-2.7 4.1-3.8 9.4-2.9 14.3.2 20.8 12.5 25.5 6.3 2.4 7.3 2.5 11.7 1.4 6.2-1.6 18.9-6.3 48.4-18.2 56.7-22.9 114.7-42.6 140.7-47.7l5.8-1.2 24.5 8.5c13.5 4.7 45.2 16 70.5 25.2 78.6 28.6 95.9 34 101.1 31.6 3.2-1.4 5.4-6.7 5.4-12.8 0-9.6-3.3-16.3-10.8-22-4.8-3.6-8.7-4.9-27.7-8.8-7.1-1.5-15.9-3.8-19.5-5.2-3.6-1.3-17.1-6.5-30-11.5-12.9-4.9-30.4-11.4-38.8-14.4-8.4-2.9-15.8-5.7-16.4-6-.6-.4 4.2-2.2 10.8-4.1 11.6-3.3 27-7.7 58.3-16.9 17.6-5.2 48.9-16.6 54.1-19.6 8.8-5.2 14.8-13.3 17.4-23.3 1.3-5.3 1.4-6.2.1-8.2-2-3-5.3-3.7-13.4-2.9-19.7 1.8-89.3 19.4-175.4 44l-29.8 8.6-18.2-5.1c-20.2-5.6-63.5-18.8-91.2-27.9-18.1-5.9-52.3-16.5-62.5-19.4-9.6-2.7-16.1-3-19.2-.9" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -23,23 +23,23 @@ const BuyMeCoffee = ({
|
||||
{title ? <title id={titleId}>{title}</title> : null}
|
||||
<path
|
||||
fill="#0D0C22"
|
||||
d="m791.109 297.518-.878-.516-2.03-.619a4.833 4.833 0 0 0 2.908 1.135ZM803.896 388.891l-.98.275.98-.275ZM791.484 297.377a1.773 1.773 0 0 1-.366-.087 1.42 1.42 0 0 0 0 .244.738.738 0 0 0 .366-.157Z"
|
||||
d="m791.109 297.518-.878-.516-2.03-.619a4.83 4.83 0 0 0 2.908 1.135M803.896 388.891l-.98.275zM791.484 297.377a1.8 1.8 0 0 1-.366-.087 1.4 1.4 0 0 0 0 .244.74.74 0 0 0 .366-.157"
|
||||
/>
|
||||
<path
|
||||
fill="#0D0C22"
|
||||
d="M791.113 297.529h.131v-.082l-.131.082ZM803.111 388.726l1.48-.843.551-.31.499-.533a8.447 8.447 0 0 0-2.53 1.686ZM793.669 299.515l-1.446-1.377-.98-.533a4.077 4.077 0 0 0 2.426 1.91ZM430.019 1186.18a7.55 7.55 0 0 0-2.943 2.27l.912-.58c.62-.57 1.497-1.24 2.031-1.69ZM641.187 1144.63c0-1.3-.636-1.06-.482 3.58 0-.37.155-.75.224-1.11.086-.83.155-1.64.258-2.47ZM619.284 1186.18a7.546 7.546 0 0 0-2.942 2.27l.912-.58c.619-.57 1.497-1.24 2.03-1.69ZM281.304 1196.06a6.299 6.299 0 0 0-3.097-1.45c.929.45 1.858.9 2.477 1.24l.62.21ZM247.841 1164.01a9.895 9.895 0 0 0-1.222-3.85c.474 1.23.87 2.5 1.187 3.78l.035.07Z"
|
||||
d="M791.113 297.529h.131v-.082zM803.111 388.726l1.48-.843.551-.31.499-.533a8.5 8.5 0 0 0-2.53 1.686M793.669 299.515l-1.446-1.377-.98-.533a4.08 4.08 0 0 0 2.426 1.91M430.019 1186.18a7.55 7.55 0 0 0-2.943 2.27l.912-.58c.62-.57 1.497-1.24 2.031-1.69M641.187 1144.63c0-1.3-.636-1.06-.482 3.58 0-.37.155-.75.224-1.11.086-.83.155-1.64.258-2.47M619.284 1186.18a7.55 7.55 0 0 0-2.942 2.27l.912-.58c.619-.57 1.497-1.24 2.03-1.69M281.304 1196.06a6.3 6.3 0 0 0-3.097-1.45c.929.45 1.858.9 2.477 1.24zM247.841 1164.01a9.9 9.9 0 0 0-1.222-3.85c.474 1.23.87 2.5 1.187 3.78z"
|
||||
/>
|
||||
<path
|
||||
fill="#FD0"
|
||||
d="M472.623 590.836c-45.941 19.667-98.077 41.966-165.647 41.966a313.577 313.577 0 0 1-83.623-11.528l46.733 479.806a80.166 80.166 0 0 0 25.593 52.38 80.18 80.18 0 0 0 54.313 21.19s66.262 3.44 88.373 3.44c23.796 0 95.151-3.44 95.151-3.44 20.12 0 39.503-7.57 54.303-21.2a80.149 80.149 0 0 0 25.587-52.37l50.053-530.204c-22.368-7.639-44.943-12.715-70.391-12.715-44.014-.017-79.477 15.142-120.445 32.675Z"
|
||||
d="M472.623 590.836c-45.941 19.667-98.077 41.966-165.647 41.966a313.6 313.6 0 0 1-83.623-11.528l46.733 479.806a80.17 80.17 0 0 0 25.593 52.38 80.18 80.18 0 0 0 54.313 21.19s66.262 3.44 88.373 3.44c23.796 0 95.151-3.44 95.151-3.44 20.12 0 39.503-7.57 54.303-21.2a80.15 80.15 0 0 0 25.587-52.37l50.053-530.204c-22.368-7.639-44.943-12.715-70.391-12.715-44.014-.017-79.477 15.142-120.445 32.675"
|
||||
/>
|
||||
<path
|
||||
fill="#0D0C22"
|
||||
d="m78.689 386.132.79.74.517.31a7.95 7.95 0 0 0-1.307-1.05Z"
|
||||
d="m78.689 386.132.79.74.517.31a8 8 0 0 0-1.307-1.05"
|
||||
/>
|
||||
<path
|
||||
fill="#0D0C22"
|
||||
d="m879.567 341.849-7.037-35.497c-6.315-31.849-20.648-61.943-53.34-73.454-10.479-3.683-22.369-5.265-30.404-12.888-8.035-7.622-10.41-19.46-12.268-30.438-3.442-20.149-6.676-40.315-10.204-60.429-3.045-17.293-5.454-36.719-13.386-52.583-10.324-21.302-31.746-33.76-53.048-42.001a305.493 305.493 0 0 0-33.363-10.324C613.297 10.195 557.342 5.033 502.591 2.09a1376.266 1376.266 0 0 0-197.169 3.27c-48.797 4.439-100.193 9.807-146.564 26.687-16.948 6.177-34.413 13.593-47.3 26.687-15.813 16.088-20.975 40.969-9.43 61.031 8.208 14.247 22.111 24.313 36.857 30.972a298.948 298.948 0 0 0 59.844 19.478c57.297 12.664 116.642 17.636 175.178 19.753a1333.99 1333.99 0 0 0 194.433-6.35 1106.995 1106.995 0 0 0 47.817-6.314c18.738-2.874 30.765-27.376 25.242-44.445-6.608-20.406-24.365-28.321-44.444-25.241-2.96.464-5.902.894-8.862 1.324l-2.133.31c-6.803.861-13.605 1.663-20.407 2.409a1083.055 1083.055 0 0 1-42.259 3.717c-31.626 2.202-63.337 3.217-95.031 3.269-31.144 0-62.305-.878-93.38-2.925a1187.382 1187.382 0 0 1-42.431-3.545 1019.94 1019.94 0 0 1-19.219-2.168l-6.092-.774-1.324-.189-6.315-.912c-12.905-1.945-25.81-4.181-38.577-6.883a5.8 5.8 0 0 1 0-11.322h.241c11.064-2.357 22.213-4.37 33.397-6.125 3.729-.585 7.468-1.159 11.219-1.72h.103c7.003-.465 14.041-1.722 21.009-2.547A1336.183 1336.183 0 0 1 469.538 73.1c29.577.86 59.138 2.599 88.578 5.593a979.44 979.44 0 0 1 18.927 2.116c2.409.293 4.835.636 7.262.93l4.886.705a678.058 678.058 0 0 1 42.517 7.725c20.889 4.543 47.714 6.022 57.005 28.907 2.96 7.261 4.302 15.331 5.936 22.953l2.082 9.722c.055.174.095.353.121.533 4.921 22.942 9.848 45.884 14.78 68.826a12.608 12.608 0 0 1-2.006 9.871 12.612 12.612 0 0 1-8.593 5.254h-.138l-3.011.413-2.976.395c-9.43 1.228-18.87 2.375-28.322 3.442a1829.308 1829.308 0 0 1-55.938 5.506 1957.204 1957.204 0 0 1-111.55 6.074c-18.984.504-37.963.74-56.936.705a1975.736 1975.736 0 0 1-225.989-13.146c-8.122-.963-16.243-1.996-24.365-3.045 6.298.809-4.577-.62-6.779-.929a1447.245 1447.245 0 0 1-15.486-2.254c-17.327-2.599-34.55-5.799-51.843-8.604-20.906-3.441-40.9-1.72-59.81 8.604a86.994 86.994 0 0 0-36.012 37.338c-8.156 16.862-10.582 35.221-14.23 53.34C4 342.193-1.678 361.688.473 380.288 5.1 420.431 33.165 453.054 73.53 460.35c37.975 6.882 76.156 12.457 114.44 17.206a2114.804 2114.804 0 0 0 489.988 2.822 25.814 25.814 0 0 1 21.003 7.339 25.806 25.806 0 0 1 7.491 20.948l-3.82 37.132-23.091 225.077a178840.62 178840.62 0 0 1-31.126 302.866c-2.203 21.84-2.512 44.36-6.659 65.94-6.539 33.93-29.509 54.77-63.027 62.39a439.172 439.172 0 0 1-93.569 10.94c-34.912.19-69.806-1.36-104.718-1.17-37.27.21-82.918-3.23-111.687-30.97-25.277-24.36-28.77-62.51-32.211-95.5-4.588-43.67-9.136-87.331-13.645-130.989l-25.293-242.766-16.363-157.077c-.276-2.598-.551-5.162-.809-7.778-1.962-18.737-15.228-37.079-36.134-36.133-17.894.791-38.232 16.002-36.133 36.133l12.13 116.454 25.087 240.89a378681.11 378681.11 0 0 1 21.388 205.306c1.377 13.11 2.667 26.26 4.112 39.37 7.864 71.65 62.58 110.26 130.339 121.13 39.575 6.37 80.113 7.68 120.273 8.33 51.482.83 103.48 2.81 154.118-6.52 75.038-13.77 131.337-63.87 139.372-141.59 2.295-22.44 4.589-44.88 6.883-67.33 7.628-74.241 15.245-148.487 22.85-222.739l24.881-242.61 11.408-111.188a25.812 25.812 0 0 1 20.785-22.696c21.456-4.181 41.967-11.322 57.229-27.651 24.295-25.998 29.13-59.895 20.544-94.067ZM72.43 365.835c.327-.155-.275 2.649-.533 3.957-.052-1.979.051-3.734.533-3.957Zm2.082 16.105c.172-.121.688.568 1.222 1.394-.809-.758-1.325-1.325-1.24-1.394h.018Zm2.048 2.701c.74 1.256 1.135 2.048 0 0Zm4.112 3.338h.103c0 .121.19.241.258.362a2.666 2.666 0 0 0-.378-.362h.017Zm720.124-4.99c-7.708 7.33-19.323 10.737-30.8 12.441-128.704 19.099-259.283 28.769-389.399 24.502-93.121-3.183-185.261-13.525-277.453-26.55-9.034-1.273-18.824-2.925-25.036-9.584-11.7-12.561-5.953-37.854-2.908-53.03 2.788-13.903 8.122-32.434 24.657-34.413 25.81-3.028 55.783 7.863 81.318 11.735a1539.798 1539.798 0 0 0 92.57 11.27c132.18 12.045 266.58 10.169 398.175-7.45a1661.346 1661.346 0 0 0 71.699-11.236c21.216-3.803 44.737-10.943 57.556 11.029 8.792 14.97 9.962 34.998 8.603 51.912a28.942 28.942 0 0 1-8.999 19.374h.017Z"
|
||||
d="m879.567 341.849-7.037-35.497c-6.315-31.849-20.648-61.943-53.34-73.454-10.479-3.683-22.369-5.265-30.404-12.888-8.035-7.622-10.41-19.46-12.268-30.438-3.442-20.149-6.676-40.315-10.204-60.429-3.045-17.293-5.454-36.719-13.386-52.583-10.324-21.302-31.746-33.76-53.048-42.001a306 306 0 0 0-33.363-10.324C613.297 10.195 557.342 5.033 502.591 2.09a1376 1376 0 0 0-197.169 3.27c-48.797 4.439-100.193 9.807-146.564 26.687-16.948 6.177-34.413 13.593-47.3 26.687-15.813 16.088-20.975 40.969-9.43 61.031 8.208 14.247 22.111 24.313 36.857 30.972a299 299 0 0 0 59.844 19.478c57.297 12.664 116.642 17.636 175.178 19.753a1334 1334 0 0 0 194.433-6.35 1107 1107 0 0 0 47.817-6.314c18.738-2.874 30.765-27.376 25.242-44.445-6.608-20.406-24.365-28.321-44.444-25.241-2.96.464-5.902.894-8.862 1.324l-2.133.31q-10.204 1.29-20.407 2.409a1083 1083 0 0 1-42.259 3.717c-31.626 2.202-63.337 3.217-95.031 3.269-31.144 0-62.305-.878-93.38-2.925a1187 1187 0 0 1-42.431-3.545 1020 1020 0 0 1-19.219-2.168l-6.092-.774-1.324-.189-6.315-.912c-12.905-1.945-25.81-4.181-38.577-6.883a5.8 5.8 0 0 1 0-11.322h.241c11.064-2.357 22.213-4.37 33.397-6.125q5.593-.878 11.219-1.72h.103c7.003-.465 14.041-1.722 21.009-2.547A1336 1336 0 0 1 469.538 73.1c29.577.86 59.138 2.599 88.578 5.593a979 979 0 0 1 18.927 2.116c2.409.293 4.835.636 7.262.93l4.886.705a678 678 0 0 1 42.517 7.725c20.889 4.543 47.714 6.022 57.005 28.907 2.96 7.261 4.302 15.331 5.936 22.953l2.082 9.722q.082.262.121.533 7.382 34.413 14.78 68.826a12.6 12.6 0 0 1-2.006 9.871 12.61 12.61 0 0 1-8.593 5.254h-.138l-3.011.413-2.976.395q-14.144 1.842-28.322 3.442a1829 1829 0 0 1-55.938 5.506 1957 1957 0 0 1-111.55 6.074q-28.476.757-56.936.705a1976 1976 0 0 1-225.989-13.146c-8.122-.963-16.243-1.996-24.365-3.045 6.298.809-4.577-.62-6.779-.929a1447 1447 0 0 1-15.486-2.254c-17.327-2.599-34.55-5.799-51.843-8.604-20.906-3.441-40.9-1.72-59.81 8.604a87 87 0 0 0-36.012 37.338c-8.156 16.862-10.582 35.221-14.23 53.34C4 342.193-1.678 361.688.473 380.288 5.1 420.431 33.165 453.054 73.53 460.35c37.975 6.882 76.156 12.457 114.44 17.206a2114.8 2114.8 0 0 0 489.988 2.822 25.81 25.81 0 0 1 21.003 7.339 25.8 25.8 0 0 1 7.491 20.948l-3.82 37.132-23.091 225.077a178841 178841 0 0 1-31.126 302.866c-2.203 21.84-2.512 44.36-6.659 65.94-6.539 33.93-29.509 54.77-63.027 62.39a439 439 0 0 1-93.569 10.94c-34.912.19-69.806-1.36-104.718-1.17-37.27.21-82.918-3.23-111.687-30.97-25.277-24.36-28.77-62.51-32.211-95.5q-6.882-65.504-13.645-130.989l-25.293-242.766-16.363-157.077c-.276-2.598-.551-5.162-.809-7.778-1.962-18.737-15.228-37.079-36.134-36.133-17.894.791-38.232 16.002-36.133 36.133l12.13 116.454 25.087 240.89a378681 378681 0 0 1 21.388 205.306c1.377 13.11 2.667 26.26 4.112 39.37 7.864 71.65 62.58 110.26 130.339 121.13 39.575 6.37 80.113 7.68 120.273 8.33 51.482.83 103.48 2.81 154.118-6.52 75.038-13.77 131.337-63.87 139.372-141.59 2.295-22.44 4.589-44.88 6.883-67.33q11.442-111.361 22.85-222.739l24.881-242.61 11.408-111.188a25.812 25.812 0 0 1 20.785-22.696c21.456-4.181 41.967-11.322 57.229-27.651 24.295-25.998 29.13-59.895 20.544-94.067M72.43 365.835c.327-.155-.275 2.649-.533 3.957-.052-1.979.051-3.734.533-3.957m2.082 16.105c.172-.121.688.568 1.222 1.394-.809-.758-1.325-1.325-1.24-1.394zm2.048 2.701c.74 1.256 1.135 2.048 0 0m4.112 3.338h.103c0 .121.19.241.258.362a2.7 2.7 0 0 0-.378-.362zm720.124-4.99c-7.708 7.33-19.323 10.737-30.8 12.441-128.704 19.099-259.283 28.769-389.399 24.502-93.121-3.183-185.261-13.525-277.453-26.55-9.034-1.273-18.824-2.925-25.036-9.584-11.7-12.561-5.953-37.854-2.908-53.03 2.788-13.903 8.122-32.434 24.657-34.413 25.81-3.028 55.783 7.863 81.318 11.735a1540 1540 0 0 0 92.57 11.27c132.18 12.045 266.58 10.169 398.175-7.45a1661 1661 0 0 0 71.699-11.236c21.216-3.803 44.737-10.943 57.556 11.029 8.792 14.97 9.962 34.998 8.603 51.912a28.94 28.94 0 0 1-8.999 19.374z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -31,14 +31,14 @@ const KoFi = ({
|
||||
<use x={97} y={83} href="#a" />
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="m521.5 52.4 410 .2 12.5 2.1c56.6 9.6 99.9 28 143.5 61.2 11.7 8.9 33.5 30.2 42.5 41.6 31 39.2 50.6 86.9 59.2 143.8 3 19.5 3.2 65 .5 83.2-7.3 48.4-24.3 89.7-52.3 127.3-10.5 13.9-35.9 39.8-49.4 50.2-52.3 40.3-116.3 63.2-188.8 67.6-10.4.6-11.3.8-11.6 2.8-.3 1.1-1.1 7.5-2 14.1-7.1 54-32.5 98.7-70.7 124.1-16.3 10.9-38.6 20.3-58.8 25-9.9 2.3-102.7 3.2-354.1 3.6-230.9.3-217.6.6-239.5-4.9-41.1-10.2-73.8-34.9-91.3-69-10.6-20.6-14.9-39-16.2-68.3-1.8-38.7-3.2-261.9-2.7-402 .5-138.6.6-141.7 2.6-149.2 7.2-27.3 27.3-47.5 52.6-52.8 2.2-.4 188.5-.7 414-.6zm-4.6 57.6H117.3l-2 2.2c-4.9 5.4-4.7-1.7-5.1 148.8-.4 142.7 1.1 364 2.8 395.5.7 13.5 1.4 18.8 3.5 26 8.7 29.8 29 48 63.2 56.7l8.8 2.3 216-.3c118.8-.2 243.9-.7 278-1.1l62-.8 8.5-2.8c40.5-13.2 64.2-41.6 73.5-87.9 2.5-12.7 4.5-32.6 4.5-45.1 0-13.1 5-22.4 15.1-28l5.4-3 28-.6c16.4-.4 33-1.4 40-2.3 64.9-8.9 116.3-33.4 156-74.7 32.8-34.1 52.5-77.3 57.6-126.8 1.5-14.3.6-46.8-1.6-61.1-8.5-55.1-29.1-98-62.6-130.6-11.8-11.4-17.7-16-33.9-26.7-33.1-21.6-66.1-33.5-106-38.2-10.8-1.3-67.3-1.5-412.1-1.5z"
|
||||
d="m521.5 52.4 410 .2 12.5 2.1c56.6 9.6 99.9 28 143.5 61.2 11.7 8.9 33.5 30.2 42.5 41.6 31 39.2 50.6 86.9 59.2 143.8 3 19.5 3.2 65 .5 83.2-7.3 48.4-24.3 89.7-52.3 127.3-10.5 13.9-35.9 39.8-49.4 50.2-52.3 40.3-116.3 63.2-188.8 67.6-10.4.6-11.3.8-11.6 2.8-.3 1.1-1.1 7.5-2 14.1-7.1 54-32.5 98.7-70.7 124.1-16.3 10.9-38.6 20.3-58.8 25-9.9 2.3-102.7 3.2-354.1 3.6-230.9.3-217.6.6-239.5-4.9-41.1-10.2-73.8-34.9-91.3-69-10.6-20.6-14.9-39-16.2-68.3-1.8-38.7-3.2-261.9-2.7-402 .5-138.6.6-141.7 2.6-149.2 7.2-27.3 27.3-47.5 52.6-52.8 2.2-.4 188.5-.7 414-.6m-4.6 57.6H117.3l-2 2.2c-4.9 5.4-4.7-1.7-5.1 148.8-.4 142.7 1.1 364 2.8 395.5.7 13.5 1.4 18.8 3.5 26 8.7 29.8 29 48 63.2 56.7l8.8 2.3 216-.3c118.8-.2 243.9-.7 278-1.1l62-.8 8.5-2.8c40.5-13.2 64.2-41.6 73.5-87.9 2.5-12.7 4.5-32.6 4.5-45.1 0-13.1 5-22.4 15.1-28l5.4-3 28-.6c16.4-.4 33-1.4 40-2.3 64.9-8.9 116.3-33.4 156-74.7 32.8-34.1 52.5-77.3 57.6-126.8 1.5-14.3.6-46.8-1.6-61.1-8.5-55.1-29.1-98-62.6-130.6-11.8-11.4-17.7-16-33.9-26.7-33.1-21.6-66.1-33.5-106-38.2-10.8-1.3-67.3-1.5-412.1-1.5"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M939.5 185.4c33.5 6.1 61.7 21.9 83.2 46.5 17.6 20.1 27.6 40.3 33.4 67 4.2 19.7 3.7 56.3-1.3 79.1-10.6 49.7-36.5 83.1-81.3 105-15.9 7.8-27.3 11.6-38.6 13-14.1 1.8-71.1 2.5-78.1 1.1-11-2.3-19.3-10.4-22.3-21.7-2.3-8.8-2.3-261 0-269.8 2.8-10.8 10-18.1 20.8-21.1 7.6-2.2 71.2-1.5 84.2.9zM903.8 241H891v199h9.3c5 0 14.3-.5 20.6-1 9.5-.9 12.8-1.7 20.6-4.9 41.1-16.9 59.5-47.6 59.5-99.2 0-23.9-3.7-38.9-13.3-53.7-14.5-22.4-36.2-36-62.7-39.2-4.6-.5-14.2-1-21.2-1z"
|
||||
d="M939.5 185.4c33.5 6.1 61.7 21.9 83.2 46.5 17.6 20.1 27.6 40.3 33.4 67 4.2 19.7 3.7 56.3-1.3 79.1-10.6 49.7-36.5 83.1-81.3 105-15.9 7.8-27.3 11.6-38.6 13-14.1 1.8-71.1 2.5-78.1 1.1-11-2.3-19.3-10.4-22.3-21.7-2.3-8.8-2.3-261 0-269.8 2.8-10.8 10-18.1 20.8-21.1 7.6-2.2 71.2-1.5 84.2.9M903.8 241H891v199h9.3c5 0 14.3-.5 20.6-1 9.5-.9 12.8-1.7 20.6-4.9 41.1-16.9 59.5-47.6 59.5-99.2 0-23.9-3.7-38.9-13.3-53.7-14.5-22.4-36.2-36-62.7-39.2-4.6-.5-14.2-1-21.2-1"
|
||||
/>
|
||||
<path
|
||||
d="M561.8 245.6c-28.7 5.2-60.3 22.1-83.5 44.7l-6.2 6-9.8-9.4c-20.6-19.7-46.1-33.2-74.3-39.4-11.6-2.5-36.4-3.1-49-1.1-41.8 6.6-73 31-84.8 66.1-6 17.6-7.4 42.4-3.8 63 4.9 27.5 17.3 56.3 32.4 75.3C302 475 359.3 531.2 433 598c37.5 34 35.1 32.4 42 29.3 7.5-3.4 96.9-88.3 144.9-137.7 38.7-39.7 49.3-52.6 59-71.7 11.8-23.2 16.7-44.3 15.8-68.7-.7-22.4-6.3-40.4-17.7-57.1-16.1-23.8-44.3-41.1-75.7-46.6-10.5-1.8-29.2-1.8-39.5.1z"
|
||||
d="M561.8 245.6c-28.7 5.2-60.3 22.1-83.5 44.7l-6.2 6-9.8-9.4c-20.6-19.7-46.1-33.2-74.3-39.4-11.6-2.5-36.4-3.1-49-1.1-41.8 6.6-73 31-84.8 66.1-6 17.6-7.4 42.4-3.8 63 4.9 27.5 17.3 56.3 32.4 75.3C302 475 359.3 531.2 433 598c37.5 34 35.1 32.4 42 29.3 7.5-3.4 96.9-88.3 144.9-137.7 38.7-39.7 49.3-52.6 59-71.7 11.8-23.2 16.7-44.3 15.8-68.7-.7-22.4-6.3-40.4-17.7-57.1-16.1-23.8-44.3-41.1-75.7-46.6-10.5-1.8-29.2-1.8-39.5.1"
|
||||
style={{
|
||||
fill: '#ff504f',
|
||||
}}
|
||||
|
||||
@@ -3,12 +3,16 @@ import { useWakeLock } from 'react-screen-wake-lock';
|
||||
import {
|
||||
GlobalSettingsContext,
|
||||
GlobalSettingsContextType,
|
||||
SavedGame,
|
||||
} from '../Contexts/GlobalSettingsContext';
|
||||
import { useAnalytics } from '../Hooks/useAnalytics';
|
||||
import {
|
||||
InitialGameSettings,
|
||||
InitialGameSettingsSchema,
|
||||
Settings,
|
||||
defaultInitialGameSettings,
|
||||
defaultSettings,
|
||||
initialGameSettingsSchema,
|
||||
settingsSchema,
|
||||
} from '../Types/Settings';
|
||||
|
||||
export const GlobalSettingsProvider = ({
|
||||
@@ -18,60 +22,131 @@ export const GlobalSettingsProvider = ({
|
||||
}) => {
|
||||
const analytics = useAnalytics();
|
||||
|
||||
const savedShowPlay = localStorage.getItem('showPlay');
|
||||
const savedGameSettings = localStorage.getItem('initialGameSettings');
|
||||
const savedSettings = localStorage.getItem('settings');
|
||||
const localSavedGame = localStorage.getItem('savedGame');
|
||||
const [savedGame, setCurrentGame] = useState<SavedGame>(
|
||||
localSavedGame ? JSON.parse(localSavedGame) : null
|
||||
);
|
||||
const setCurrentGameAndLocalStorage = (savedGame: SavedGame) => {
|
||||
if (!savedGame) {
|
||||
setCurrentGame(savedGame);
|
||||
localStorage.removeItem('savedGame');
|
||||
return;
|
||||
}
|
||||
setCurrentGame(savedGame);
|
||||
localStorage.setItem('savedGame', JSON.stringify(savedGame));
|
||||
};
|
||||
|
||||
const savedPlaying = localStorage.getItem('playing');
|
||||
const [playing, setPlaying] = useState<boolean>(
|
||||
savedPlaying ? savedPlaying === 'true' : false
|
||||
);
|
||||
const setPlayingAndLocalStorage = (playing: boolean) => {
|
||||
setPlaying(playing);
|
||||
localStorage.setItem('playing', String(playing));
|
||||
};
|
||||
|
||||
const savedPreStartComplete = localStorage.getItem('preStartComplete');
|
||||
const [preStartCompleted, setPreStartCompleted] = useState<boolean>(
|
||||
savedPreStartComplete ? savedPreStartComplete === 'true' : false
|
||||
);
|
||||
|
||||
const savedShowPlay = localStorage.getItem('showPlay');
|
||||
const [showPlay, setShowPlay] = useState<boolean>(
|
||||
savedShowPlay ? savedShowPlay === 'true' : false
|
||||
);
|
||||
const setShowPlayAndLocalStorage = (showPlay: boolean) => {
|
||||
setShowPlay(showPlay);
|
||||
localStorage.setItem('showPlay', String(showPlay));
|
||||
};
|
||||
|
||||
const savedSettings = localStorage.getItem('settings');
|
||||
const [randomizingPlayer, setRandomizingPlayer] = useState<boolean>(
|
||||
savedSettings
|
||||
? Boolean(JSON.parse(savedSettings).preStartMode === 'random-king')
|
||||
: true
|
||||
);
|
||||
const [settings, setSettings] = useState<Settings>(
|
||||
savedSettings ? JSON.parse(savedSettings) : defaultSettings
|
||||
);
|
||||
|
||||
const setSettingsAndLocalStorage = (settings: Settings) => {
|
||||
setSettings(settings);
|
||||
localStorage.setItem('settings', JSON.stringify(settings));
|
||||
};
|
||||
|
||||
const savedGameSettings = localStorage.getItem('initialGameSettings');
|
||||
|
||||
const [initialGameSettings, setInitialGameSettings] =
|
||||
useState<InitialGameSettings | null>(
|
||||
savedGameSettings ? JSON.parse(savedGameSettings) : null
|
||||
useState<InitialGameSettings>(
|
||||
savedGameSettings
|
||||
? JSON.parse(savedGameSettings)
|
||||
: defaultInitialGameSettings
|
||||
);
|
||||
|
||||
const [settings, setSettings] = useState<Settings>(
|
||||
savedSettings
|
||||
? JSON.parse(savedSettings)
|
||||
: { goFullscreenOnStart: true, keepAwake: true, showStartingPlayer: true }
|
||||
);
|
||||
const setInitialGameSettingsAndLocalStorage = (
|
||||
initialGameSettings: InitialGameSettings
|
||||
) => {
|
||||
setInitialGameSettings(initialGameSettings);
|
||||
localStorage.setItem(
|
||||
'initialGameSettings',
|
||||
JSON.stringify(initialGameSettings)
|
||||
);
|
||||
};
|
||||
|
||||
const removeLocalStorage = async () => {
|
||||
localStorage.removeItem('initialGameSettings');
|
||||
localStorage.removeItem('players');
|
||||
localStorage.removeItem('playing');
|
||||
localStorage.removeItem('showPlay');
|
||||
localStorage.removeItem('preStartComplete');
|
||||
|
||||
setPlaying(false);
|
||||
setShowPlay(false);
|
||||
setPreStartCompleted(false);
|
||||
};
|
||||
|
||||
// Set settings if they are not valid
|
||||
useEffect(() => {
|
||||
if (savedGameSettings && JSON.parse(savedGameSettings).gridAreas) {
|
||||
removeLocalStorage();
|
||||
window.location.reload();
|
||||
// If there are no saved settings, set default settings
|
||||
if (!savedSettings) {
|
||||
setSettingsAndLocalStorage(defaultSettings);
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedSettings = settingsSchema.safeParse(JSON.parse(savedSettings));
|
||||
|
||||
// If saved settings are not valid, remove them
|
||||
if (!parsedSettings.success) {
|
||||
console.error('invalid settings, resetting to default settings');
|
||||
setSettingsAndLocalStorage(defaultSettings);
|
||||
return;
|
||||
}
|
||||
localStorage.setItem('settings', JSON.stringify(parsedSettings.data));
|
||||
}, [settings, savedSettings]);
|
||||
|
||||
// Set initial game settings if they are not valid
|
||||
useEffect(() => {
|
||||
if (!savedGameSettings) {
|
||||
setInitialGameSettingsAndLocalStorage(defaultInitialGameSettings);
|
||||
return;
|
||||
}
|
||||
|
||||
//parse existing game settings with zod schema
|
||||
const parsedInitialGameSettings =
|
||||
InitialGameSettingsSchema.safeParse(initialGameSettings);
|
||||
initialGameSettingsSchema.safeParse(initialGameSettings);
|
||||
|
||||
if (!parsedInitialGameSettings.success) {
|
||||
removeLocalStorage();
|
||||
window.location.reload();
|
||||
console.error('invalid game settings, resetting to default settings');
|
||||
setInitialGameSettingsAndLocalStorage(defaultInitialGameSettings);
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.setItem(
|
||||
'initialGameSettings',
|
||||
JSON.stringify(initialGameSettings)
|
||||
JSON.stringify(parsedInitialGameSettings.data)
|
||||
);
|
||||
}, [initialGameSettings, savedGameSettings]);
|
||||
|
||||
useEffect(() => {
|
||||
localStorage.setItem('settings', JSON.stringify(settings));
|
||||
}, [settings]);
|
||||
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -87,6 +162,11 @@ export const GlobalSettingsProvider = ({
|
||||
};
|
||||
}, []);
|
||||
|
||||
const [isLatestVersion, setIsLatestVersion] = useState(false);
|
||||
const [remoteVersion, setRemoteVersion] = useState<string | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
const { isSupported, release, released, request, type } = useWakeLock();
|
||||
|
||||
const active = settings.keepAwake;
|
||||
@@ -135,6 +215,51 @@ export const GlobalSettingsProvider = ({
|
||||
}
|
||||
};
|
||||
|
||||
const setPreStartCompletedAndLocalStorage = (preStartComplete: boolean) => {
|
||||
setPreStartCompleted(preStartComplete);
|
||||
localStorage.setItem('playing', String(playing));
|
||||
};
|
||||
|
||||
async function checkForNewVersion(source: 'settings' | 'start_menu') {
|
||||
try {
|
||||
const result = await fetch(
|
||||
'https://api.github.com/repos/Vikeo/LifeTrinket/releases/latest',
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${
|
||||
import.meta.env.VITE_REPO_READ_ACCESS_TOKEN
|
||||
}`,
|
||||
Accept: 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version': '2022-11-28',
|
||||
},
|
||||
}
|
||||
);
|
||||
const data = await result.json();
|
||||
|
||||
if (!data.name) {
|
||||
setRemoteVersion(undefined);
|
||||
setIsLatestVersion(false);
|
||||
return;
|
||||
}
|
||||
|
||||
setRemoteVersion(data.name);
|
||||
|
||||
if (data.name === import.meta.env.VITE_APP_VERSION) {
|
||||
setIsLatestVersion(true);
|
||||
return;
|
||||
}
|
||||
|
||||
analytics.trackEvent(`${source}_has_new_version`, {
|
||||
remoteVersion: data.name,
|
||||
installedVersion: import.meta.env.VITE_APP_VERSION,
|
||||
});
|
||||
|
||||
setIsLatestVersion(false);
|
||||
} catch (error) {
|
||||
console.error('error getting latest version string', error);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
fullscreen: { isFullscreen, enableFullscreen, disableFullscreen },
|
||||
wakeLock: {
|
||||
@@ -147,24 +272,45 @@ export const GlobalSettingsProvider = ({
|
||||
},
|
||||
goToStart,
|
||||
showPlay,
|
||||
setShowPlay,
|
||||
setShowPlay: setShowPlayAndLocalStorage,
|
||||
playing,
|
||||
setPlaying: setPlayingAndLocalStorage,
|
||||
initialGameSettings,
|
||||
setInitialGameSettings,
|
||||
settings,
|
||||
setSettings,
|
||||
setSettings: setSettingsAndLocalStorage,
|
||||
randomizingPlayer,
|
||||
setRandomizingPlayer,
|
||||
isPWA: window?.matchMedia('(display-mode: standalone)').matches,
|
||||
preStartCompleted,
|
||||
setPreStartCompleted: setPreStartCompletedAndLocalStorage,
|
||||
savedGame,
|
||||
saveCurrentGame: setCurrentGameAndLocalStorage,
|
||||
|
||||
version: {
|
||||
installedVersion: import.meta.env.VITE_APP_VERSION,
|
||||
remoteVersion,
|
||||
isLatest: isLatestVersion,
|
||||
checkForNewVersion,
|
||||
},
|
||||
};
|
||||
}, [
|
||||
active,
|
||||
analytics,
|
||||
initialGameSettings,
|
||||
isFullscreen,
|
||||
isSupported,
|
||||
release,
|
||||
active,
|
||||
request,
|
||||
settings,
|
||||
showPlay,
|
||||
type,
|
||||
showPlay,
|
||||
playing,
|
||||
initialGameSettings,
|
||||
settings,
|
||||
randomizingPlayer,
|
||||
preStartCompleted,
|
||||
savedGame,
|
||||
remoteVersion,
|
||||
isLatestVersion,
|
||||
analytics,
|
||||
]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -7,6 +7,17 @@ import { InitialGameSettings } from '../Types/Settings';
|
||||
export const PlayersProvider = ({ children }: { children: ReactNode }) => {
|
||||
const savedPlayers = localStorage.getItem('players');
|
||||
|
||||
const savedStartingPlayerIndex = localStorage.getItem('startingPlayerIndex');
|
||||
|
||||
const [startingPlayerIndex, setStartingPlayerIndex] = useState<number>(
|
||||
savedStartingPlayerIndex ? parseInt(savedStartingPlayerIndex) : -1
|
||||
);
|
||||
|
||||
const setStartingPlayerIndexAndLocalStorage = (index: number) => {
|
||||
setStartingPlayerIndex(index);
|
||||
localStorage.setItem('startingPlayerIndex', String(index));
|
||||
};
|
||||
|
||||
const [players, setPlayers] = useState<Player[]>(
|
||||
savedPlayers ? JSON.parse(savedPlayers) : []
|
||||
);
|
||||
@@ -50,9 +61,7 @@ export const PlayersProvider = ({ children }: { children: ReactNode }) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const startingPlayerIndex = Math.floor(
|
||||
Math.random() * initialGameSettings.numberOfPlayers
|
||||
);
|
||||
const newStartingPlayerIndex = Math.floor(Math.random() * players.length);
|
||||
|
||||
players.forEach((player: Player) => {
|
||||
player.commanderDamage.map((damage) => {
|
||||
@@ -65,16 +74,9 @@ export const PlayersProvider = ({ children }: { children: ReactNode }) => {
|
||||
});
|
||||
|
||||
player.lifeTotal = initialGameSettings.startingLifeTotal;
|
||||
|
||||
player.hasLost = false;
|
||||
|
||||
const isStartingPlayer = player.index === startingPlayerIndex;
|
||||
|
||||
player.isStartingPlayer = isStartingPlayer;
|
||||
|
||||
if (player.isStartingPlayer) {
|
||||
player.showStartingPlayer = true;
|
||||
}
|
||||
player.isStartingPlayer = newStartingPlayerIndex === player.index;
|
||||
|
||||
updatePlayer(player);
|
||||
});
|
||||
@@ -87,8 +89,10 @@ export const PlayersProvider = ({ children }: { children: ReactNode }) => {
|
||||
updatePlayer,
|
||||
updateLifeTotal,
|
||||
resetCurrentGame,
|
||||
startingPlayerIndex,
|
||||
setStartingPlayerIndex: setStartingPlayerIndexAndLocalStorage,
|
||||
};
|
||||
}, [players]);
|
||||
}, [players, startingPlayerIndex]);
|
||||
|
||||
return (
|
||||
<PlayersContext.Provider value={ctxValue}>
|
||||
|
||||
@@ -6,17 +6,17 @@ export type Player = {
|
||||
commanderDamage: CommanderDamage[];
|
||||
extraCounters: ExtraCounter[];
|
||||
isStartingPlayer: boolean;
|
||||
showStartingPlayer: boolean;
|
||||
hasLost: boolean;
|
||||
isSide: boolean;
|
||||
};
|
||||
|
||||
export type PlayerSettings = {
|
||||
rotation: Rotation;
|
||||
useCommanderDamage: boolean;
|
||||
usePartner?: boolean;
|
||||
usePoison?: boolean;
|
||||
useEnergy?: boolean;
|
||||
useExperience?: boolean;
|
||||
usePartner: boolean;
|
||||
usePoison: boolean;
|
||||
useEnergy: boolean;
|
||||
useExperience: boolean;
|
||||
};
|
||||
|
||||
type ExtraCounter = {
|
||||
|
||||
@@ -12,10 +12,19 @@ export enum GameFormat {
|
||||
TwoHeadedGiant = 'two-headed-giant',
|
||||
}
|
||||
|
||||
export enum PreStartMode {
|
||||
None = 'none',
|
||||
RandomKing = 'random-king',
|
||||
FingerGame = 'finger-game',
|
||||
Trivia = 'trivia',
|
||||
}
|
||||
|
||||
export type Settings = {
|
||||
keepAwake: boolean;
|
||||
showStartingPlayer: boolean;
|
||||
showPlayerMenuCog: boolean;
|
||||
goFullscreenOnStart: boolean;
|
||||
preStartMode: PreStartMode;
|
||||
};
|
||||
|
||||
export type InitialGameSettings = {
|
||||
@@ -26,10 +35,34 @@ export type InitialGameSettings = {
|
||||
orientation: Orientation;
|
||||
};
|
||||
|
||||
export const InitialGameSettingsSchema = z.object({
|
||||
startingLifeTotal: z.number().min(1).max(200).default(20),
|
||||
useCommanderDamage: z.boolean().default(false),
|
||||
gameFormat: z.nativeEnum(GameFormat).optional(),
|
||||
numberOfPlayers: z.number().min(1).max(6).default(2),
|
||||
orientation: z.nativeEnum(Orientation).default(Orientation.Landscape),
|
||||
export const initialGameSettingsSchema = z.object({
|
||||
startingLifeTotal: z.number().min(1).max(200),
|
||||
useCommanderDamage: z.boolean(),
|
||||
gameFormat: z.nativeEnum(GameFormat),
|
||||
numberOfPlayers: z.number().min(1).max(6),
|
||||
orientation: z.nativeEnum(Orientation),
|
||||
});
|
||||
|
||||
export const defaultInitialGameSettings = {
|
||||
numberOfPlayers: 4,
|
||||
startingLifeTotal: 40,
|
||||
useCommanderDamage: true,
|
||||
orientation: Orientation.Landscape,
|
||||
gameFormat: GameFormat.Commander,
|
||||
};
|
||||
|
||||
export const settingsSchema = z.object({
|
||||
keepAwake: z.boolean(),
|
||||
showStartingPlayer: z.boolean(),
|
||||
showPlayerMenuCog: z.boolean(),
|
||||
goFullscreenOnStart: z.boolean(),
|
||||
preStartMode: z.nativeEnum(PreStartMode),
|
||||
});
|
||||
|
||||
export const defaultSettings: Settings = {
|
||||
goFullscreenOnStart: true,
|
||||
keepAwake: true,
|
||||
showStartingPlayer: true,
|
||||
showPlayerMenuCog: true,
|
||||
preStartMode: PreStartMode.None,
|
||||
};
|
||||
|
||||
87
src/Utils/checkContrast.ts
Normal file
87
src/Utils/checkContrast.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
type RGBA = {
|
||||
red: number;
|
||||
green: number;
|
||||
blue: number;
|
||||
alpha: number;
|
||||
};
|
||||
|
||||
export const hexToRgb = (hex: string): RGBA => {
|
||||
hex = hex.replace(/^#/, '');
|
||||
let alpha = 255;
|
||||
|
||||
if (hex.length === 8) {
|
||||
alpha = parseInt(hex.slice(6, 8), 16);
|
||||
hex = hex.substring(0, 6);
|
||||
}
|
||||
|
||||
if (hex.length === 4) {
|
||||
alpha = parseInt(hex.slice(3, 4).repeat(2), 16);
|
||||
hex = hex.substring(0, 3);
|
||||
}
|
||||
|
||||
if (hex.length === 3) {
|
||||
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
||||
}
|
||||
|
||||
const num = parseInt(hex, 16);
|
||||
const red = num >> 16;
|
||||
const green = (num >> 8) & 255;
|
||||
const blue = num & 255;
|
||||
|
||||
return { red, green, blue, alpha };
|
||||
};
|
||||
|
||||
export const luminance = (a: number, b: number) => {
|
||||
const l1 = Math.max(a, b);
|
||||
const l2 = Math.min(a, b);
|
||||
return (l1 + 0.05) / (l2 + 0.05);
|
||||
};
|
||||
|
||||
export const rgbContrast = (a: RGBA, b: RGBA) => {
|
||||
return luminance(relativeLuminance(a), relativeLuminance(b));
|
||||
};
|
||||
|
||||
// calculate the color contrast ratio
|
||||
export const checkContrast = (hexC1: string, hexC2: string) => {
|
||||
const color1rgb = hexToRgb(hexC1);
|
||||
const color2rgb = hexToRgb(hexC2);
|
||||
|
||||
const contrast = rgbContrast(color1rgb, color2rgb);
|
||||
|
||||
if (contrast >= 7) {
|
||||
return 'AAA';
|
||||
}
|
||||
|
||||
if (contrast >= 4.5) {
|
||||
return 'AA';
|
||||
}
|
||||
|
||||
if (contrast >= 3) {
|
||||
return 'AA Large';
|
||||
}
|
||||
|
||||
return 'Fail';
|
||||
};
|
||||
|
||||
// red, green, and blue coefficients
|
||||
const rc = 0.2126;
|
||||
const gc = 0.7152;
|
||||
const bc = 0.0722;
|
||||
// low-gamma adjust coefficient
|
||||
const lowc = 1 / 12.92;
|
||||
|
||||
function adjustGamma(input: number) {
|
||||
return Math.pow((input + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
export const relativeLuminance = (rgb: RGBA) => {
|
||||
const rsrgb = rgb.red / 255;
|
||||
const gsrgb = rgb.green / 255;
|
||||
const bsrgb = rgb.blue / 255;
|
||||
|
||||
const r = rsrgb <= 0.03928 ? rsrgb * lowc : adjustGamma(rsrgb);
|
||||
const g = gsrgb <= 0.03928 ? gsrgb * lowc : adjustGamma(gsrgb);
|
||||
const b = bsrgb <= 0.03928 ? bsrgb * lowc : adjustGamma(bsrgb);
|
||||
|
||||
return r * rc + g * gc + b * bc;
|
||||
};
|
||||
@@ -2,8 +2,18 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
html {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background-color: theme('colors.background.default');
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
@@ -21,6 +31,37 @@ code {
|
||||
monospace;
|
||||
}
|
||||
|
||||
// hide scrollbar globally
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* width */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
/* Track */
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: theme('colors.background.default');
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: theme('colors.primary.dark');
|
||||
border-radius: 32px;
|
||||
}
|
||||
|
||||
/* Handle on hover */
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: theme('colors.primary.main');
|
||||
}
|
||||
|
||||
* {
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.pointer-events-all {
|
||||
pointer-events: all;
|
||||
@@ -33,4 +74,9 @@ code {
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
.show-scrollbar {
|
||||
scrollbar-width: auto;
|
||||
-ms-overflow-style: auto;
|
||||
}
|
||||
}
|
||||
|
||||
10
src/vite-env.d.ts
vendored
10
src/vite-env.d.ts
vendored
@@ -1 +1,11 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_APP_VERSION: string;
|
||||
readonly VITE_REPO_READ_ACCESS_TOKEN: string;
|
||||
readonly VITE_FIREBASE_ANALYTICS_API_KEY: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
|
||||
@@ -2,79 +2,91 @@
|
||||
import tailwindcssGridAreas from '@savvywombat/tailwindcss-grid-areas';
|
||||
import type { Config } from 'tailwindcss';
|
||||
|
||||
export const baseColors = {
|
||||
primary: {
|
||||
main: '#3E7D78',
|
||||
dark: '#2D5F5B',
|
||||
},
|
||||
secondary: {
|
||||
main: '#284F4C',
|
||||
dark: '#1B3B38',
|
||||
},
|
||||
background: {
|
||||
default: '#08253B',
|
||||
backdrop: 'rgba(0, 0, 0, 0.3)',
|
||||
settings: 'rgba(20, 20, 0, 0.9)',
|
||||
},
|
||||
icons: {
|
||||
dark: '#00000080',
|
||||
light: '#ffffff4f',
|
||||
},
|
||||
text: {
|
||||
primary: '#F5F5F5',
|
||||
secondary: '#76A6A5',
|
||||
},
|
||||
action: {
|
||||
disabled: '#234A47',
|
||||
},
|
||||
common: {
|
||||
white: '#F9FFE3',
|
||||
black: '#000000',
|
||||
},
|
||||
lifeCounter: {
|
||||
text: 'rgba(0, 0, 0, 0.4)',
|
||||
lostWrapper: '#000000',
|
||||
},
|
||||
interface: {
|
||||
loseButton: {
|
||||
background: '#43434380',
|
||||
},
|
||||
recentDifference: {
|
||||
background: 'rgba(255, 255, 255, 0.6);',
|
||||
text: '#333333',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const twGridTemplateAreas = {
|
||||
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 player1 player1 player2 player2 player2 player2 player2 player2 player3',
|
||||
'player0 player4 player4 player4 player4 player4 player4 player5 player5 player5 player5 player5 player5 player3',
|
||||
],
|
||||
};
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||
theme: {
|
||||
screens: {
|
||||
modalSm: '548px',
|
||||
},
|
||||
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',
|
||||
],
|
||||
},
|
||||
colors: {
|
||||
primary: {
|
||||
main: '#7F9172',
|
||||
dark: '#57654F',
|
||||
},
|
||||
secondary: {
|
||||
main: '#5E714C',
|
||||
},
|
||||
background: {
|
||||
default: '#495E35',
|
||||
backdrop: 'rgba(0, 0, 0, 0.3)',
|
||||
settings: 'rgba(20, 20, 0, 0.9)',
|
||||
},
|
||||
text: {
|
||||
primary: '#F5F5F5',
|
||||
secondary: '#b3b39b',
|
||||
},
|
||||
action: {
|
||||
disabled: '#5E714C',
|
||||
},
|
||||
common: {
|
||||
white: '#F9FFE3',
|
||||
black: '#000000',
|
||||
},
|
||||
lifeCounter: {
|
||||
text: 'rgba(0, 0, 0, 0.4)',
|
||||
lostWrapper: '#00000070',
|
||||
},
|
||||
interface: {
|
||||
loseButton: {
|
||||
background: '#43434380',
|
||||
},
|
||||
recentDifference: {
|
||||
background: 'rgba(255, 255, 255, 0.6);',
|
||||
text: '#333333',
|
||||
},
|
||||
},
|
||||
},
|
||||
gridTemplateAreas: twGridTemplateAreas,
|
||||
colors: baseColors,
|
||||
keyframes: {
|
||||
fadeOut: {
|
||||
'0%': {
|
||||
@@ -91,19 +103,11 @@ export default {
|
||||
animation: {
|
||||
fadeOut: 'fadeOut 3s 1s ease-out forwards',
|
||||
},
|
||||
fontSize: {
|
||||
xxs: ['0.625rem', '1rem'],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [tailwindcssGridAreas],
|
||||
} satisfies Config;
|
||||
|
||||
// const fadeOut = keyframes`
|
||||
// 0% {
|
||||
// opacity: 1;
|
||||
// }
|
||||
// 33% {
|
||||
// opacity: 0.6;
|
||||
// }
|
||||
// 100% {
|
||||
// opacity: 0;
|
||||
// }
|
||||
// `;
|
||||
// #98FF98
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react-swc';
|
||||
import { VitePWA } from 'vite-plugin-pwa';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
plugins: [
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
workbox: {
|
||||
clientsClaim: true,
|
||||
skipWaiting: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
build: {
|
||||
minify: 'esbuild',
|
||||
rollupOptions: {
|
||||
@@ -11,7 +19,14 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
define: {
|
||||
APP_VERSION: JSON.stringify(process.env.npm_package_version),
|
||||
REPO_READ_ACCESS_TOKEN: JSON.stringify(process.env.REPO_READ_ACCESS_TOKEN),
|
||||
'import.meta.env.VITE_APP_VERSION': JSON.stringify(
|
||||
process.env.npm_package_version
|
||||
),
|
||||
VITE_REPO_READ_ACCESS_TOKEN: JSON.stringify(
|
||||
process.env.VITE_REPO_READ_ACCESS_TOKEN
|
||||
),
|
||||
VITE_FIREBASE_ANALYTICS_API_KEY: JSON.stringify(
|
||||
process.env.VITE_FIREBASE_ANALYTICS_API_KEY
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user