Compare commits
108 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
739048044c | ||
|
|
4656757554 | ||
|
|
9a6bfe49a1 | ||
|
|
e6e562a0c6 | ||
|
|
3e38332a68 | ||
|
|
c23509ae26 | ||
|
|
9f1cc35eab | ||
|
|
fe43e464de | ||
|
|
b074499c1f | ||
|
|
5953cf6b49 | ||
|
|
acefbb8846 | ||
|
|
adb79bf0e8 | ||
|
|
92be2e56d4 | ||
|
|
854ca81a40 | ||
|
|
9119ca5518 | ||
|
|
2837bb59b3 | ||
|
|
623aec29f8 | ||
|
|
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 | ||
|
|
e55ea6a83a | ||
|
|
481196de9b | ||
|
|
a136dbd3f9 | ||
|
|
8d23349dac | ||
|
|
a7caa46156 |
@@ -1,8 +1,12 @@
|
|||||||
robots.txt,1693082171694,391d14b3c2f8c9143a27a28c7399585142228d4d1bdbe2c87ac946de411fa9a2
|
index.html,1711905710499,4b604b23faec8d63a58e07b96d724a1aea56a7c86d57c9af791832ce87a552e7
|
||||||
manifest.json,1693082171694,91ce94afb71f33a477f5d8d48c3f98bd7de422279c74f17b6500eec72003ac1a
|
manifest.webmanifest,1711905710499,f2bf253209f6e292a6b0dbfa06fb4ac188eb5f2dba568c3ad5511b9ed52c1f51
|
||||||
assets/index-5265c558.css,1693082171837,08c4451946bbdf520fe337edb365417a8bbf91914c018b83866723ef52d57b43
|
manifest.json,1711905710294,7ff5111aa04a42adff3b38924ec467b6f345ed0309dba1486dc9b783b60c2a9d
|
||||||
index.html,1693082171837,09e1919fbaaa3a0bf08f43eb46c29136d62a7747b41f8b5d0f4a7ed23337c344
|
sw.js,1711905711506,1ef2f4f40ec8dca15cc42d547462ade1e84314ea9722276f5994ccee7bbdf80f
|
||||||
logo192.png,1693082171693,4309255bccbdbb341b5ab88708677e3d43b9e171d2666528ff932295a8257e4e
|
robots.txt,1711905710294,391d14b3c2f8c9143a27a28c7399585142228d4d1bdbe2c87ac946de411fa9a2
|
||||||
favicon.ico,1693082171692,48d8c1b9714dbc9bcb012d9c9f04112d229f20e6c889bda588ac159f973e6a8d
|
registerSW.js,1711905710499,5b6445b5215737c53ef0d379c151d57de165a056de2d1c5812ed614f158ebcbd
|
||||||
logo512.png,1693082171694,92c7c05dc98170596d04f48e5e60eaae9535f409bcaeff129fd98fef8aba9f4e
|
workbox-3e911b1d.js,1711905711507,d5dbc868a5c07af633d29de7ba3ffe37542aaaabdf33713b4298df31f92f11ff
|
||||||
assets/index-5023e89e.js,1693082171838,8a6177168e95e1ca90e5ad8774252a8a02a9a78765bd329b7deae729c01aedf3
|
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
|
||||||
|
|||||||
55
.github/workflows/firebase-release.yml
vendored
@@ -4,37 +4,44 @@ name: Deploy to Firebase Hosting
|
|||||||
tags:
|
tags:
|
||||||
- '*'
|
- '*'
|
||||||
jobs:
|
jobs:
|
||||||
# build_and_deploy:
|
build_and_deploy:
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# env:
|
env:
|
||||||
# REPO_READ_ACCESS_TOKEN: ${{ secrets.REPO_READ_ACCESS_TOKEN }}
|
VITE_REPO_READ_ACCESS_TOKEN: ${{ secrets.REPO_READ_ACCESS_TOKEN }}
|
||||||
# steps:
|
VITE_FIREBASE_ANALYTICS_API_KEY: ${{ secrets.FIREBASE_ANALYTICS_API_KEY }}
|
||||||
# - name: Checkout repository
|
steps:
|
||||||
# uses: actions/checkout@v3
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
# - name: Setup bun
|
- name: Setup bun
|
||||||
# uses: oven-sh/setup-bun@v1
|
uses: oven-sh/setup-bun@v1
|
||||||
|
|
||||||
# - name: Build, lint, and deploy
|
- name: Build, lint, and deploy
|
||||||
# run: |
|
run: |
|
||||||
# bun install
|
bun install
|
||||||
# bun run build
|
bun run build
|
||||||
# bun run lint
|
bun run lint
|
||||||
# - name: Deploy to Firebase Hosting
|
- name: Deploy to Firebase Hosting
|
||||||
# uses: FirebaseExtended/action-hosting-deploy@v0
|
uses: FirebaseExtended/action-hosting-deploy@v0
|
||||||
# with:
|
with:
|
||||||
# repoToken: '${{ secrets.GITHUB_TOKEN }}'
|
repoToken: '${{ secrets.GITHUB_TOKEN }}'
|
||||||
# firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_LIFE_TRINKET }}'
|
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_LIFE_TRINKET }}'
|
||||||
# channelId: live
|
channelId: live
|
||||||
# projectId: life-trinket
|
projectId: life-trinket
|
||||||
|
|
||||||
release:
|
release:
|
||||||
# needs: build_and_deploy
|
needs: build_and_deploy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
working-directory: ${{ github.workspace }}
|
||||||
steps:
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: get version
|
- name: get version
|
||||||
id: version
|
id: version
|
||||||
uses: notiz-dev/github-action-json-property@release
|
uses: notiz-dev/github-action-json-property@v0.2.0
|
||||||
|
|
||||||
with:
|
with:
|
||||||
path: 'package.json'
|
path: 'package.json'
|
||||||
prop_path: 'version'
|
prop_path: 'version'
|
||||||
@@ -46,7 +53,7 @@ jobs:
|
|||||||
- name: Create Release
|
- name: Create Release
|
||||||
uses: ncipollo/release-action@v1.13.0
|
uses: ncipollo/release-action@v1.13.0
|
||||||
with:
|
with:
|
||||||
body: release_note.txt
|
bodyFile: release_note.txt
|
||||||
commit: ${{ github.sha }}
|
commit: ${{ github.sha }}
|
||||||
tag: '${{ steps.version.outputs.prop }}'
|
tag: '${{ steps.version.outputs.prop }}'
|
||||||
token: ${{ secrets.RELEASE_TOKEN }}
|
token: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
|||||||
47
package.json
@@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "life-trinket",
|
"name": "life-trinket",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.5.2",
|
"version": "0.9.92",
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18",
|
"node": ">=20",
|
||||||
"npm": "please use bun or yarn :) "
|
"yarn": "use pnpm",
|
||||||
|
"npm": "please use pnpm"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -13,38 +14,42 @@
|
|||||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"generate-icons": "npx @svgr/cli src/Icons/svgs",
|
"generate-icons": "npx @svgr/cli src/Icons/svgs",
|
||||||
"deploy": "bun build && firebase deploy --only hosting"
|
"deploy": "bun run build && firebase deploy --only hosting"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mui/material": "^5.13.6",
|
|
||||||
"firebase": "^10.3.0",
|
"firebase": "^10.3.0",
|
||||||
"ga-4-react": "^0.1.281",
|
"ga-4-react": "^0.1.281",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-screen-wake-lock": "^3.0.2",
|
"react-screen-wake-lock": "^3.0.2",
|
||||||
|
"react-swipeable": "^7.0.1",
|
||||||
"react-twc": "^1.3.0",
|
"react-twc": "^1.3.0",
|
||||||
|
"semver": "^7.6.2",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@emotion/react": "^11.11.1",
|
"@emotion/react": "^11.11.4",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.5",
|
||||||
"@savvywombat/tailwindcss-grid-areas": "^3.1.0",
|
"@savvywombat/tailwindcss-grid-areas": "^4.0.0",
|
||||||
"@svgr/cli": "^8.1.0",
|
"@svgr/cli": "^8.1.0",
|
||||||
"@types/react": "^18.2.15",
|
"@types/react": "^18.3.1",
|
||||||
"@types/react-dom": "^18.2.7",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
"@types/semver": "^7.5.8",
|
||||||
"@typescript-eslint/parser": "^6.0.0",
|
"@typescript-eslint/eslint-plugin": "^7.8.0",
|
||||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
"@typescript-eslint/parser": "^7.8.0",
|
||||||
"autoprefixer": "^10.4.16",
|
"@vitejs/plugin-react-swc": "^3.6.0",
|
||||||
|
"autoprefixer": "^10.4.19",
|
||||||
"eslint": "^8.45.0",
|
"eslint": "^8.45.0",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.2",
|
||||||
"eslint-plugin-react-refresh": "^0.4.3",
|
"eslint-plugin-react-refresh": "^0.4.6",
|
||||||
"firebase-tools": "^12.5.2",
|
"firebase-tools": "^13.7.5",
|
||||||
"install": "^0.13.0",
|
"install": "^0.13.0",
|
||||||
"postcss": "^8.4.32",
|
"postcss": "^8.4.38",
|
||||||
"prettier": "2.8.8",
|
"prettier": "2.8.8",
|
||||||
"tailwindcss": "^3.4.0",
|
"prop-types": "^15.8.1",
|
||||||
"typescript": "^5.0.2",
|
"tailwindcss": "^3.4.3",
|
||||||
"vite": "^4.4.5"
|
"typescript": "^5.4.5",
|
||||||
|
"vite": "^5.2.10",
|
||||||
|
"vite-plugin-pwa": "^0.20.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10506
pnpm-lock.yaml
generated
Normal file
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 43 KiB |
14
src/App.tsx
@@ -1,18 +1,14 @@
|
|||||||
import { ThemeProvider } from '@mui/material';
|
|
||||||
import { LifeTrinket } from './Components/LifeTrinket';
|
import { LifeTrinket } from './Components/LifeTrinket';
|
||||||
import { theme } from './Data/theme';
|
|
||||||
import { GlobalSettingsProvider } from './Providers/GlobalSettingsProvider';
|
import { GlobalSettingsProvider } from './Providers/GlobalSettingsProvider';
|
||||||
import { PlayersProvider } from './Providers/PlayersProvider';
|
import { PlayersProvider } from './Providers/PlayersProvider';
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<PlayersProvider>
|
||||||
<PlayersProvider>
|
<GlobalSettingsProvider>
|
||||||
<GlobalSettingsProvider>
|
<LifeTrinket />
|
||||||
<LifeTrinket />
|
</GlobalSettingsProvider>
|
||||||
</GlobalSettingsProvider>
|
</PlayersProvider>
|
||||||
</PlayersProvider>
|
|
||||||
</ThemeProvider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ export type RotationButtonProps = TwcComponentProps<'button'> & {
|
|||||||
$rotation?: number;
|
$rotation?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const MAX_TAP_MOVE_DISTANCE = 20;
|
||||||
|
|
||||||
const CommanderDamageContainer = twc.div<RotationDivProps>((props) => [
|
const CommanderDamageContainer = twc.div<RotationDivProps>((props) => [
|
||||||
'flex flex-grow',
|
'flex flex-grow',
|
||||||
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
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',
|
'bg-black',
|
||||||
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||||
? 'w-full h-px'
|
? 'w-full h-px'
|
||||||
@@ -54,6 +56,7 @@ type CommanderDamageButtonComponentProps = {
|
|||||||
type InputProps = {
|
type InputProps = {
|
||||||
opponentIndex: number;
|
opponentIndex: number;
|
||||||
isPartner: boolean;
|
isPartner: boolean;
|
||||||
|
event: React.PointerEvent<HTMLButtonElement>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CommanderDamage = ({
|
export const CommanderDamage = ({
|
||||||
@@ -63,12 +66,8 @@ export const CommanderDamage = ({
|
|||||||
}: CommanderDamageButtonComponentProps) => {
|
}: CommanderDamageButtonComponentProps) => {
|
||||||
const { updatePlayer } = usePlayers();
|
const { updatePlayer } = usePlayers();
|
||||||
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||||
const [timeoutFinished, setTimeoutFinished] = useState(false);
|
const [downLongPressed, setDownLongPressed] = useState(false);
|
||||||
const [hasPressedDown, setHasPressedDown] = useState(false);
|
const downPositionRef = useRef({ x: 0, y: 0 });
|
||||||
|
|
||||||
const isSide =
|
|
||||||
player.settings.rotation === Rotation.Side ||
|
|
||||||
player.settings.rotation === Rotation.SideFlipped;
|
|
||||||
|
|
||||||
const handleCommanderDamageChange = (
|
const handleCommanderDamageChange = (
|
||||||
index: number,
|
index: number,
|
||||||
@@ -107,34 +106,47 @@ export const CommanderDamage = ({
|
|||||||
handleLifeChange(player.lifeTotal - increment);
|
handleLifeChange(player.lifeTotal - increment);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDownInput = ({ opponentIndex, isPartner }: InputProps) => {
|
const handleDownInput = ({ opponentIndex, isPartner, event }: InputProps) => {
|
||||||
setTimeoutFinished(false);
|
downPositionRef.current = { x: event.clientX, y: event.clientY };
|
||||||
setHasPressedDown(true);
|
setDownLongPressed(false);
|
||||||
|
|
||||||
timeoutRef.current = setTimeout(() => {
|
timeoutRef.current = setTimeout(() => {
|
||||||
setTimeoutFinished(true);
|
setDownLongPressed(true);
|
||||||
handleCommanderDamageChange(opponentIndex, -1, isPartner);
|
handleCommanderDamageChange(opponentIndex, -1, isPartner);
|
||||||
}, decrementTimeoutMs);
|
}, decrementTimeoutMs);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpInput = ({ opponentIndex, isPartner }: InputProps) => {
|
const handleUpInput = ({ opponentIndex, isPartner, event }: InputProps) => {
|
||||||
if (!(hasPressedDown && !timeoutFinished)) {
|
if (downLongPressed) {
|
||||||
return;
|
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);
|
clearTimeout(timeoutRef.current);
|
||||||
|
|
||||||
handleCommanderDamageChange(opponentIndex, 1, isPartner);
|
handleCommanderDamageChange(opponentIndex, 1, isPartner);
|
||||||
setHasPressedDown(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLeaveInput = () => {
|
const handleLeaveInput = () => {
|
||||||
setTimeoutFinished(true);
|
setDownLongPressed(true);
|
||||||
clearTimeout(timeoutRef.current);
|
clearTimeout(timeoutRef.current);
|
||||||
setHasPressedDown(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const opponentIndex = opponent.index;
|
const opponentIndex = opponent.index;
|
||||||
const fontSize = isSide ? '4vmax' : '7vmin';
|
const fontSize = player.isSide ? '4vmax' : '7vmin';
|
||||||
const fontWeight = 'bold';
|
const fontWeight = 'bold';
|
||||||
const strokeWidth = isSide ? '0.4vmax' : '0.7vmin';
|
const strokeWidth = player.isSide ? '0.4vmax' : '0.7vmin';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommanderDamageContainer
|
<CommanderDamageContainer
|
||||||
@@ -145,10 +157,12 @@ export const CommanderDamage = ({
|
|||||||
<CommanderDamageButton
|
<CommanderDamageButton
|
||||||
key={opponentIndex}
|
key={opponentIndex}
|
||||||
$rotation={player.settings.rotation}
|
$rotation={player.settings.rotation}
|
||||||
onPointerDown={() =>
|
onPointerDown={(e) =>
|
||||||
handleDownInput({ opponentIndex, isPartner: false })
|
handleDownInput({ opponentIndex, isPartner: false, event: e })
|
||||||
|
}
|
||||||
|
onPointerUp={(e) =>
|
||||||
|
handleUpInput({ opponentIndex, isPartner: false, event: e })
|
||||||
}
|
}
|
||||||
onPointerUp={() => handleUpInput({ opponentIndex, isPartner: false })}
|
|
||||||
onPointerLeave={handleLeaveInput}
|
onPointerLeave={handleLeaveInput}
|
||||||
onContextMenu={(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
onContextMenu={(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -171,15 +185,15 @@ export const CommanderDamage = ({
|
|||||||
|
|
||||||
{opponent.settings.usePartner && (
|
{opponent.settings.usePartner && (
|
||||||
<>
|
<>
|
||||||
<PartnerDamageSeperator $rotation={player.settings.rotation} />
|
<PartnerDamageSeparator $rotation={player.settings.rotation} />
|
||||||
<CommanderDamageButton
|
<CommanderDamageButton
|
||||||
key={opponentIndex}
|
key={opponentIndex}
|
||||||
$rotation={player.settings.rotation}
|
$rotation={player.settings.rotation}
|
||||||
onPointerDown={() =>
|
onPointerDown={(e) =>
|
||||||
handleDownInput({ opponentIndex, isPartner: true })
|
handleDownInput({ opponentIndex, isPartner: true, event: e })
|
||||||
}
|
}
|
||||||
onPointerUp={() =>
|
onPointerUp={(e) =>
|
||||||
handleUpInput({ opponentIndex, isPartner: true })
|
handleUpInput({ opponentIndex, isPartner: true, event: e })
|
||||||
}
|
}
|
||||||
onPointerLeave={handleLeaveInput}
|
onPointerLeave={handleLeaveInput}
|
||||||
onContextMenu={(
|
onContextMenu={(
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { twc } from 'react-twc';
|
|||||||
import { decrementTimeoutMs } from '../../Data/constants';
|
import { decrementTimeoutMs } from '../../Data/constants';
|
||||||
import { CounterType, Rotation } from '../../Types/Player';
|
import { CounterType, Rotation } from '../../Types/Player';
|
||||||
import { OutlinedText } from '../Misc/OutlinedText';
|
import { OutlinedText } from '../Misc/OutlinedText';
|
||||||
import { RotationDivProps } from './CommanderDamage';
|
import { MAX_TAP_MOVE_DISTANCE, RotationDivProps } from './CommanderDamage';
|
||||||
|
|
||||||
const ExtraCounterContainer = twc.div`
|
const ExtraCounterContainer = twc.div`
|
||||||
flex
|
flex
|
||||||
@@ -47,6 +47,7 @@ type ExtraCounterProps = {
|
|||||||
type: CounterType;
|
type: CounterType;
|
||||||
setCounterTotal: (updatedCounterTotal: number, type: CounterType) => void;
|
setCounterTotal: (updatedCounterTotal: number, type: CounterType) => void;
|
||||||
rotation: number;
|
rotation: number;
|
||||||
|
isSide: boolean;
|
||||||
playerIndex: number;
|
playerIndex: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -56,14 +57,13 @@ const ExtraCounter = ({
|
|||||||
setCounterTotal,
|
setCounterTotal,
|
||||||
type,
|
type,
|
||||||
rotation,
|
rotation,
|
||||||
|
isSide,
|
||||||
playerIndex,
|
playerIndex,
|
||||||
}: ExtraCounterProps) => {
|
}: ExtraCounterProps) => {
|
||||||
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||||
const [timeoutFinished, setTimeoutFinished] = useState(false);
|
const [timeoutFinished, setTimeoutFinished] = useState(false);
|
||||||
const [hasPressedDown, setHasPressedDown] = useState(false);
|
const [hasPressedDown, setHasPressedDown] = useState(false);
|
||||||
|
const downPositionRef = useRef({ x: 0, y: 0 });
|
||||||
const isSide =
|
|
||||||
rotation === Rotation.Side || rotation === Rotation.SideFlipped;
|
|
||||||
|
|
||||||
const handleCountChange = (increment: number) => {
|
const handleCountChange = (increment: number) => {
|
||||||
if (!counterTotal) {
|
if (!counterTotal) {
|
||||||
@@ -73,7 +73,8 @@ const ExtraCounter = ({
|
|||||||
setCounterTotal(counterTotal + increment, type);
|
setCounterTotal(counterTotal + increment, type);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDownInput = () => {
|
const handleDownInput = (event: React.PointerEvent<HTMLButtonElement>) => {
|
||||||
|
downPositionRef.current = { x: event.clientX, y: event.clientY };
|
||||||
setTimeoutFinished(false);
|
setTimeoutFinished(false);
|
||||||
setHasPressedDown(true);
|
setHasPressedDown(true);
|
||||||
timeoutRef.current = setTimeout(() => {
|
timeoutRef.current = setTimeout(() => {
|
||||||
@@ -82,10 +83,23 @@ const ExtraCounter = ({
|
|||||||
}, decrementTimeoutMs);
|
}, decrementTimeoutMs);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpInput = () => {
|
const handleUpInput = (event: React.PointerEvent<HTMLButtonElement>) => {
|
||||||
if (!(hasPressedDown && !timeoutFinished)) {
|
if (!(hasPressedDown && !timeoutFinished)) {
|
||||||
return;
|
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);
|
clearTimeout(timeoutRef.current);
|
||||||
handleCountChange(1);
|
handleCountChange(1);
|
||||||
setHasPressedDown(false);
|
setHasPressedDown(false);
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { TwcComponentProps, twc } from 'react-twc';
|
import { TwcComponentProps, twc } from 'react-twc';
|
||||||
import { lifeLongPressMultiplier } from '../../Data/constants';
|
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'> & {
|
type RotationButtonProps = TwcComponentProps<'div'> & {
|
||||||
$align?: string;
|
$align?: string;
|
||||||
@@ -12,7 +14,6 @@ const LifeCounterButtonTwc = twc.button`
|
|||||||
h-full
|
h-full
|
||||||
w-full
|
w-full
|
||||||
flex
|
flex
|
||||||
text-lifeCounter-text
|
|
||||||
font-semibold
|
font-semibold
|
||||||
bg-transparent
|
bg-transparent
|
||||||
border-none
|
border-none
|
||||||
@@ -39,29 +40,41 @@ const TextContainer = twc.div<RotationButtonProps>((props) => [
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
type LifeCounterButtonProps = {
|
type LifeCounterButtonProps = {
|
||||||
lifeTotal: number;
|
player: Player;
|
||||||
setLifeTotal: (lifeTotal: number) => void;
|
setLifeTotal: (lifeTotal: number) => void;
|
||||||
rotation: number;
|
|
||||||
operation: 'add' | 'subtract';
|
operation: 'add' | 'subtract';
|
||||||
increment: number;
|
increment: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const LifeCounterButton = ({
|
const LifeCounterButton = ({
|
||||||
lifeTotal,
|
player,
|
||||||
setLifeTotal,
|
setLifeTotal,
|
||||||
rotation,
|
|
||||||
operation,
|
operation,
|
||||||
increment,
|
increment,
|
||||||
}: LifeCounterButtonProps) => {
|
}: LifeCounterButtonProps) => {
|
||||||
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||||
const [timeoutFinished, setTimeoutFinished] = useState(false);
|
const [timeoutFinished, setTimeoutFinished] = useState(false);
|
||||||
const [hasPressedDown, setHasPressedDown] = 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) => {
|
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);
|
setTimeoutFinished(false);
|
||||||
setHasPressedDown(true);
|
setHasPressedDown(true);
|
||||||
timeoutRef.current = setTimeout(() => {
|
timeoutRef.current = setTimeout(() => {
|
||||||
@@ -70,10 +83,23 @@ const LifeCounterButton = ({
|
|||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpInput = () => {
|
const handleUpInput = (event: React.PointerEvent<HTMLButtonElement>) => {
|
||||||
if (!(hasPressedDown && !timeoutFinished)) {
|
if (!(hasPressedDown && !timeoutFinished)) {
|
||||||
return;
|
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);
|
clearTimeout(timeoutRef.current);
|
||||||
handleLifeChange(operation === 'add' ? 1 : -1);
|
handleLifeChange(operation === 'add' ? 1 : -1);
|
||||||
setHasPressedDown(false);
|
setHasPressedDown(false);
|
||||||
@@ -86,7 +112,8 @@ const LifeCounterButton = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fontSize =
|
const fontSize =
|
||||||
rotation === Rotation.SideFlipped || rotation === Rotation.Side
|
player.settings.rotation === Rotation.SideFlipped ||
|
||||||
|
player.settings.rotation === Rotation.Side
|
||||||
? '8vmax'
|
? '8vmax'
|
||||||
: '12vmin';
|
: '12vmin';
|
||||||
|
|
||||||
@@ -102,8 +129,11 @@ const LifeCounterButton = ({
|
|||||||
aria-label={`${operation === 'add' ? 'Add' : 'Subtract'} life`}
|
aria-label={`${operation === 'add' ? 'Add' : 'Subtract'} life`}
|
||||||
>
|
>
|
||||||
<TextContainer
|
<TextContainer
|
||||||
$rotation={rotation}
|
$rotation={player.settings.rotation}
|
||||||
$align={operation === 'add' ? 'right' : 'left'}
|
$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'}
|
{operation === 'add' ? '\u002B' : '\u2212'}
|
||||||
</TextContainer>
|
</TextContainer>
|
||||||
|
|||||||
@@ -4,13 +4,11 @@ import { Rotation } from '../../Types/Player';
|
|||||||
import { RotationDivProps } from './CommanderDamage';
|
import { RotationDivProps } from './CommanderDamage';
|
||||||
|
|
||||||
const LoseButton = twc.div<RotationDivProps>((props) => [
|
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
|
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||||
? `right-auto top-[15%] left-[27%]`
|
? `left-[21%]`
|
||||||
: props.$rotation === Rotation.Side
|
: 'top-[21%]',
|
||||||
? `right-auto top-[15%] left-[27%]`
|
|
||||||
: 'right-[15%] top-1/4',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
type LoseButtonProps = {
|
type LoseButtonProps = {
|
||||||
@@ -24,6 +22,8 @@ export const LoseGameButton = ({ rotation, onClick }: LoseButtonProps) => {
|
|||||||
? rotation
|
? rotation
|
||||||
: rotation === Rotation.Side
|
: rotation === Rotation.Side
|
||||||
? rotation - 180
|
? rotation - 180
|
||||||
|
: rotation === Rotation.Flipped
|
||||||
|
? rotation - 180
|
||||||
: rotation;
|
: rotation;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -33,7 +33,7 @@ export const LoseGameButton = ({ rotation, onClick }: LoseButtonProps) => {
|
|||||||
aria-label={`Lose Game`}
|
aria-label={`Lose Game`}
|
||||||
style={{ rotate: `${calcRotation}deg` }}
|
style={{ rotate: `${calcRotation}deg` }}
|
||||||
>
|
>
|
||||||
<Skull size="5vmin" color="black" opacity={0.5} />
|
<Skull size="8vmin" color="black" opacity={0.5} />
|
||||||
</LoseButton>
|
</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 { CounterType, Player, Rotation } from '../../Types/Player';
|
||||||
import { RotationDivProps } from '../Buttons/CommanderDamage';
|
import { RotationDivProps } from '../Buttons/CommanderDamage';
|
||||||
import ExtraCounter from '../Buttons/ExtraCounter';
|
import ExtraCounter from '../Buttons/ExtraCounter';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { checkContrast } from '../../Utils/checkContrast';
|
||||||
|
|
||||||
const Container = twc.div<RotationDivProps>((props) => [
|
const Container = twc.div<RotationDivProps>((props) => [
|
||||||
'flex',
|
'flex',
|
||||||
@@ -19,9 +21,9 @@ const Container = twc.div<RotationDivProps>((props) => [
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
export const ExtraCountersGrid = 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
|
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',
|
: 'w-full bottom-0',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -31,6 +33,17 @@ type ExtraCountersBarProps = {
|
|||||||
|
|
||||||
const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
||||||
const { updatePlayer } = usePlayers();
|
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 = (
|
const handleCounterChange = (
|
||||||
updatedCounterTotal: number,
|
updatedCounterTotal: number,
|
||||||
@@ -93,13 +106,20 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
|||||||
{useCommanderDamage && (
|
{useCommanderDamage && (
|
||||||
<ExtraCounter
|
<ExtraCounter
|
||||||
rotation={player.settings.rotation}
|
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}
|
type={CounterType.CommanderTax}
|
||||||
counterTotal={
|
counterTotal={
|
||||||
player.extraCounters?.find(
|
player.extraCounters?.find(
|
||||||
(counter) => counter.type === 'commanderTax'
|
(counter) => counter.type === 'commanderTax'
|
||||||
)?.value
|
)?.value
|
||||||
}
|
}
|
||||||
|
isSide={player.isSide}
|
||||||
setCounterTotal={handleCounterChange}
|
setCounterTotal={handleCounterChange}
|
||||||
playerIndex={player.index}
|
playerIndex={player.index}
|
||||||
/>
|
/>
|
||||||
@@ -107,13 +127,20 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
|||||||
{Boolean(useCommanderDamage && usePartner) && (
|
{Boolean(useCommanderDamage && usePartner) && (
|
||||||
<ExtraCounter
|
<ExtraCounter
|
||||||
rotation={player.settings.rotation}
|
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}
|
type={CounterType.PartnerTax}
|
||||||
counterTotal={
|
counterTotal={
|
||||||
player.extraCounters?.find(
|
player.extraCounters?.find(
|
||||||
(counter) => counter.type === 'partnerTax'
|
(counter) => counter.type === 'partnerTax'
|
||||||
)?.value
|
)?.value
|
||||||
}
|
}
|
||||||
|
isSide={player.isSide}
|
||||||
setCounterTotal={handleCounterChange}
|
setCounterTotal={handleCounterChange}
|
||||||
playerIndex={player.index}
|
playerIndex={player.index}
|
||||||
/>
|
/>
|
||||||
@@ -121,12 +148,19 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
|||||||
{usePoison && (
|
{usePoison && (
|
||||||
<ExtraCounter
|
<ExtraCounter
|
||||||
rotation={player.settings.rotation}
|
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}
|
type={CounterType.Poison}
|
||||||
counterTotal={
|
counterTotal={
|
||||||
player.extraCounters?.find((counter) => counter.type === 'poison')
|
player.extraCounters?.find((counter) => counter.type === 'poison')
|
||||||
?.value
|
?.value
|
||||||
}
|
}
|
||||||
|
isSide={player.isSide}
|
||||||
setCounterTotal={handleCounterChange}
|
setCounterTotal={handleCounterChange}
|
||||||
playerIndex={player.index}
|
playerIndex={player.index}
|
||||||
/>
|
/>
|
||||||
@@ -134,12 +168,19 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
|||||||
{useEnergy && (
|
{useEnergy && (
|
||||||
<ExtraCounter
|
<ExtraCounter
|
||||||
rotation={player.settings.rotation}
|
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}
|
type={CounterType.Energy}
|
||||||
counterTotal={
|
counterTotal={
|
||||||
player.extraCounters?.find((counter) => counter.type === 'energy')
|
player.extraCounters?.find((counter) => counter.type === 'energy')
|
||||||
?.value
|
?.value
|
||||||
}
|
}
|
||||||
|
isSide={player.isSide}
|
||||||
setCounterTotal={handleCounterChange}
|
setCounterTotal={handleCounterChange}
|
||||||
playerIndex={player.index}
|
playerIndex={player.index}
|
||||||
/>
|
/>
|
||||||
@@ -147,13 +188,20 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
|
|||||||
{useExperience && (
|
{useExperience && (
|
||||||
<ExtraCounter
|
<ExtraCounter
|
||||||
rotation={player.settings.rotation}
|
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}
|
type={CounterType.Experience}
|
||||||
counterTotal={
|
counterTotal={
|
||||||
player.extraCounters?.find(
|
player.extraCounters?.find(
|
||||||
(counter) => counter.type === 'experience'
|
(counter) => counter.type === 'experience'
|
||||||
)?.value
|
)?.value
|
||||||
}
|
}
|
||||||
|
isSide={player.isSide}
|
||||||
setCounterTotal={handleCounterChange}
|
setCounterTotal={handleCounterChange}
|
||||||
playerIndex={player.index}
|
playerIndex={player.index}
|
||||||
/>
|
/>
|
||||||
|
|||||||
64
src/Components/Dialogs/Dialog.tsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { Close } 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 my-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-background-default rounded-full"
|
||||||
|
>
|
||||||
|
<Close className="text-primary-main size-full" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div className="bg-background-default rounded-2xl max-w-[548px] max-h-[80vh] flex flex-col">
|
||||||
|
{title && (
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
};
|
||||||
106
src/Components/Dialogs/InfoDialog.tsx
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import { useAnalytics } from '../../Hooks/useAnalytics';
|
||||||
|
import { BuyMeCoffee } from '../../Icons/generated/Support';
|
||||||
|
import { Separator } from '../Misc/Separator';
|
||||||
|
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="Info" dialogRef={dialogRef}>
|
||||||
|
<div className=" text-text-primary">
|
||||||
|
<h2 className="text-md underline">Contributors</h2>
|
||||||
|
<div className="flex flex-row items-center gap-1 text-sm">
|
||||||
|
{/* <Trinket className="size-4" /> */}
|
||||||
|
<a href="#">Elin:</a> Icon design
|
||||||
|
</div>
|
||||||
|
<Separator height="1px" />
|
||||||
|
</div>
|
||||||
|
<div className="text-text-primary mt-4">
|
||||||
|
<div className="text">
|
||||||
|
<h2 className="text-xl">📋 Usage Guide</h2>
|
||||||
|
<Separator height="1px" />
|
||||||
|
</div>
|
||||||
|
<div className="text-text-primary">
|
||||||
|
<Paragraph className="mb-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>
|
||||||
|
|
||||||
|
<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
@@ -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-secondary-main border-none outline-none text-text-primary rounded-md p-1 text-xs disabled:saturate-50 font-semibold"
|
||||||
|
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 font-bold"
|
||||||
|
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 LifeCounterButton from '../Buttons/LifeCounterButton';
|
||||||
import { OutlinedText } from '../Misc/OutlinedText';
|
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',
|
'flex flex-grow relative w-full h-full justify-between items-center',
|
||||||
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||||
? 'flex-col-reverse'
|
? 'flex-col-reverse'
|
||||||
@@ -49,28 +49,13 @@ type HealthProps = {
|
|||||||
|
|
||||||
const Health = ({
|
const Health = ({
|
||||||
player,
|
player,
|
||||||
rotation,
|
|
||||||
handleLifeChange,
|
handleLifeChange,
|
||||||
differenceKey,
|
differenceKey,
|
||||||
recentDifference,
|
recentDifference,
|
||||||
}: HealthProps) => {
|
}: HealthProps) => {
|
||||||
const [showStartingPlayer, setShowStartingPlayer] = useState(
|
|
||||||
localStorage.getItem('playing') === 'true'
|
|
||||||
);
|
|
||||||
const [fontSize, setFontSize] = useState(16);
|
const [fontSize, setFontSize] = useState(16);
|
||||||
const textContainerRef = useRef<HTMLDivElement | null>(null);
|
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(() => {
|
useEffect(() => {
|
||||||
if (!textContainerRef.current) {
|
if (!textContainerRef.current) {
|
||||||
return;
|
return;
|
||||||
@@ -99,12 +84,13 @@ const Health = ({
|
|||||||
}, [textContainerRef]);
|
}, [textContainerRef]);
|
||||||
|
|
||||||
const calculateFontSize = (container: HTMLDivElement) => {
|
const calculateFontSize = (container: HTMLDivElement) => {
|
||||||
const isSide =
|
const widthRatio = player.isSide
|
||||||
rotation === Rotation.SideFlipped || rotation === Rotation.Side;
|
? container.clientHeight
|
||||||
|
: container.clientWidth;
|
||||||
|
|
||||||
const widthRatio = isSide ? container.clientHeight : container.clientWidth;
|
const heightRatio = player.isSide
|
||||||
|
? container.clientWidth
|
||||||
const heightRatio = isSide ? container.clientWidth : container.clientHeight;
|
: container.clientHeight;
|
||||||
|
|
||||||
const minRatio = Math.min(widthRatio, heightRatio);
|
const minRatio = Math.min(widthRatio, heightRatio);
|
||||||
|
|
||||||
@@ -116,11 +102,10 @@ const Health = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LifeCountainer $rotation={player.settings.rotation}>
|
<LifeContainer $rotation={player.settings.rotation}>
|
||||||
<LifeCounterButton
|
<LifeCounterButton
|
||||||
lifeTotal={player.lifeTotal}
|
player={player}
|
||||||
setLifeTotal={handleLifeChange}
|
setLifeTotal={handleLifeChange}
|
||||||
rotation={player.settings.rotation}
|
|
||||||
operation="subtract"
|
operation="subtract"
|
||||||
increment={-1}
|
increment={-1}
|
||||||
/>
|
/>
|
||||||
@@ -148,13 +133,12 @@ const Health = ({
|
|||||||
</LifeCounterTextContainer>
|
</LifeCounterTextContainer>
|
||||||
</TextWrapper>
|
</TextWrapper>
|
||||||
<LifeCounterButton
|
<LifeCounterButton
|
||||||
lifeTotal={player.lifeTotal}
|
player={player}
|
||||||
setLifeTotal={handleLifeChange}
|
setLifeTotal={handleLifeChange}
|
||||||
rotation={player.settings.rotation}
|
|
||||||
operation="add"
|
operation="add"
|
||||||
increment={1}
|
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 { twc } from 'react-twc';
|
||||||
|
import { useAnalytics } from '../../Hooks/useAnalytics';
|
||||||
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
|
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
|
||||||
import { usePlayers } from '../../Hooks/usePlayers';
|
import { usePlayers } from '../../Hooks/usePlayers';
|
||||||
|
import { Cog } from '../../Icons/generated';
|
||||||
import { Player, Rotation } from '../../Types/Player';
|
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 { LoseGameButton } from '../Buttons/LoseButton';
|
||||||
import SettingsButton from '../Buttons/SettingsButton';
|
|
||||||
import CommanderDamageBar from '../Counters/CommanderDamageBar';
|
import CommanderDamageBar from '../Counters/CommanderDamageBar';
|
||||||
import ExtraCountersBar from '../Counters/ExtraCountersBar';
|
import ExtraCountersBar from '../Counters/ExtraCountersBar';
|
||||||
import PlayerMenu from '../Player/PlayerMenu';
|
import PlayerMenu from '../Players/PlayerMenu';
|
||||||
|
import { StartingPlayerCard } from '../PreStartGame/StartingPlayerCard';
|
||||||
import Health from './Health';
|
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`
|
const LifeCounterContentWrapper = twc.div`
|
||||||
relative flex flex-grow flex-col items-center w-full h-full overflow-hidden`;
|
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`,
|
: `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) => [
|
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
|
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
|
||||||
? `rotate-[${props.$rotation - 90}deg]`
|
? `rotate-[${props.$rotation - 90}deg]`
|
||||||
: '',
|
: '',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const DynamicText = twc.div`text-[8vmin]`;
|
|
||||||
|
|
||||||
const hasCommanderDamageReached21 = (player: Player) => {
|
const hasCommanderDamageReached21 = (player: Player) => {
|
||||||
const commanderDamageTotals = player.commanderDamage.map(
|
const commanderDamageTotals = player.commanderDamage.map(
|
||||||
(commanderDamage) => commanderDamage.damageTotal
|
(commanderDamage) => commanderDamage.damageTotal
|
||||||
@@ -62,36 +106,81 @@ const playerCanLose = (player: Player) => {
|
|||||||
type LifeCounterProps = {
|
type LifeCounterProps = {
|
||||||
player: Player;
|
player: Player;
|
||||||
opponents: Player[];
|
opponents: Player[];
|
||||||
|
isStartingPlayer?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const RECENT_DIFFERENCE_TTL = 3_000;
|
||||||
|
|
||||||
const LifeCounter = ({ player, opponents }: LifeCounterProps) => {
|
const LifeCounter = ({ player, opponents }: LifeCounterProps) => {
|
||||||
const { updatePlayer, updateLifeTotal } = usePlayers();
|
const { updatePlayer, updateLifeTotal } = usePlayers();
|
||||||
const { settings } = useGlobalSettings();
|
const { settings, playing } = useGlobalSettings();
|
||||||
|
const recentDifferenceTimerRef = useRef<NodeJS.Timeout | undefined>(
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
|
||||||
const [showPlayerMenu, setShowPlayerMenu] = useState(false);
|
const [showPlayerMenu, setShowPlayerMenu] = useState(false);
|
||||||
const [recentDifference, setRecentDifference] = useState(0);
|
const [recentDifference, setRecentDifference] = useState(0);
|
||||||
const [differenceKey, setDifferenceKey] = useState(Date.now());
|
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(() => {
|
useEffect(() => {
|
||||||
const timer = setTimeout(() => {
|
if (recentDifference === 0) {
|
||||||
setRecentDifference(0);
|
clearTimeout(recentDifferenceTimerRef.current);
|
||||||
}, 3_000);
|
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]);
|
}, [recentDifference]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (player.showStartingPlayer) {
|
const resizeObserver = new ResizeObserver(() => {
|
||||||
const playingTimer = setTimeout(() => {
|
if (document.body.clientWidth > document.body.clientHeight)
|
||||||
localStorage.setItem('playing', 'true');
|
setIsLandscape(true);
|
||||||
player.showStartingPlayer = false;
|
else setIsLandscape(false);
|
||||||
updatePlayer(player);
|
return () => {
|
||||||
}, 3_000);
|
// 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
|
// 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.SideFlipped ||
|
||||||
player.settings.rotation === Rotation.Side;
|
player.settings.rotation === Rotation.Side;
|
||||||
@@ -113,45 +202,40 @@ const LifeCounter = ({ player, opponents }: LifeCounterProps) => {
|
|||||||
? player.settings.rotation - 90
|
? player.settings.rotation - 90
|
||||||
: player.settings.rotation;
|
: player.settings.rotation;
|
||||||
|
|
||||||
const calcTextRotation =
|
const amountOfPlayers = opponents.length + 1;
|
||||||
player.settings.rotation === Rotation.SideFlipped ||
|
|
||||||
player.settings.rotation === Rotation.Side
|
|
||||||
? player.settings.rotation - 180
|
|
||||||
: player.settings.rotation;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LifeCounterContentWrapper style={{ background: player.color }}>
|
<LifeCounterContentWrapper style={{ background: player.color }}>
|
||||||
<LifeCounterWrapper
|
<LifeCounterWrapper
|
||||||
$rotation={player.settings.rotation}
|
$rotation={player.settings.rotation}
|
||||||
style={{ rotate: `${calcRotation}deg` }}
|
style={{ rotate: `${calcRotation}deg` }}
|
||||||
|
{...handlers}
|
||||||
>
|
>
|
||||||
{settings.showStartingPlayer &&
|
{amountOfPlayers > 1 &&
|
||||||
player.isStartingPlayer &&
|
!playing &&
|
||||||
player.showStartingPlayer && (
|
settings.showStartingPlayer &&
|
||||||
<StartingPlayerNoticeWrapper
|
player.isStartingPlayer && <StartingPlayerCard player={player} />}
|
||||||
style={{ rotate: `${calcRotation}deg` }}
|
|
||||||
>
|
|
||||||
<DynamicText style={{ rotate: `${calcTextRotation}deg` }}>
|
|
||||||
You start!
|
|
||||||
</DynamicText>
|
|
||||||
</StartingPlayerNoticeWrapper>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{player.hasLost && (
|
{player.hasLost && (
|
||||||
<PlayerLostWrapper $rotation={player.settings.rotation} />
|
<PlayerLostWrapper $rotation={player.settings.rotation} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<CommanderDamageBar
|
<CommanderDamageBar
|
||||||
opponents={opponents}
|
opponents={opponents}
|
||||||
player={player}
|
player={player}
|
||||||
key={player.index}
|
key={player.index}
|
||||||
handleLifeChange={handleLifeChange}
|
handleLifeChange={handleLifeChange}
|
||||||
/>
|
/>
|
||||||
<SettingsButton
|
{settings.showPlayerMenuCog && (
|
||||||
onClick={() => {
|
<SettingsButton
|
||||||
setShowPlayerMenu(!showPlayerMenu);
|
onClick={() => {
|
||||||
}}
|
analytics.trackEvent('open_player_menu_button');
|
||||||
rotation={player.settings.rotation}
|
setShowPlayerMenu(!showPlayerMenu);
|
||||||
/>
|
}}
|
||||||
|
rotation={player.settings.rotation}
|
||||||
|
color={player.color}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{playerCanLose(player) && (
|
{playerCanLose(player) && (
|
||||||
<LoseGameButton
|
<LoseGameButton
|
||||||
rotation={player.settings.rotation}
|
rotation={player.settings.rotation}
|
||||||
@@ -166,9 +250,12 @@ const LifeCounter = ({ player, opponents }: LifeCounterProps) => {
|
|||||||
handleLifeChange={handleLifeChange}
|
handleLifeChange={handleLifeChange}
|
||||||
/>
|
/>
|
||||||
<ExtraCountersBar player={player} />
|
<ExtraCountersBar player={player} />
|
||||||
{showPlayerMenu && (
|
|
||||||
<PlayerMenu player={player} setShowPlayerMenu={setShowPlayerMenu} />
|
<PlayerMenu
|
||||||
)}
|
isShown={showPlayerMenu}
|
||||||
|
player={player}
|
||||||
|
setShowPlayerMenu={setShowPlayerMenu}
|
||||||
|
/>
|
||||||
</LifeCounterWrapper>
|
</LifeCounterWrapper>
|
||||||
</LifeCounterContentWrapper>
|
</LifeCounterContentWrapper>
|
||||||
);
|
);
|
||||||
|
|||||||
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 (
|
return (
|
||||||
<div
|
<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 }}
|
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
@@ -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;
|
|
||||||
490
src/Components/Players/PlayerMenu.tsx
Normal file
@@ -0,0 +1,490 @@
|
|||||||
|
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 {
|
||||||
|
Close,
|
||||||
|
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
|
||||||
|
h-full
|
||||||
|
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-2 right-2 z-10"
|
||||||
|
>
|
||||||
|
<Close 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 { 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) => {
|
const getGridArea = (player: PlayerType) => {
|
||||||
switch (player.index) {
|
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 (
|
return (
|
||||||
<PlayerWrapper>
|
<PlayersWrapper>
|
||||||
<div className={`grid w-full h-full gap-1 box-border ${gridClasses} `}>
|
<div className={`grid w-full h-full gap-1 box-border ${gridLayout} `}>
|
||||||
{players.map((player) => {
|
{players.map((player) => {
|
||||||
const gridArea = getGridArea(player);
|
const gridArea = getGridArea(player);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={player.index}
|
key={player.index}
|
||||||
@@ -45,6 +48,6 @@ export const Player = (players: PlayerType[], gridClasses: string) => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</PlayerWrapper>
|
</PlayersWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
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
@@ -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-dark 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-60">
|
||||||
|
{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
@@ -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
@@ -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 { useGlobalSettings } from '../../Hooks/useGlobalSettings';
|
||||||
import { usePlayers } from '../../Hooks/usePlayers';
|
import { usePlayers } from '../../Hooks/usePlayers';
|
||||||
import { Orientation } from '../../Types/Settings';
|
import { Orientation, PreStartMode } from '../../Types/Settings';
|
||||||
import { Player } from '../Player/Player';
|
import { Players } from '../Players/Players';
|
||||||
import { twc } from 'react-twc';
|
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 = () => {
|
export const Play = () => {
|
||||||
const { players } = usePlayers();
|
const { players, setPlayers } = usePlayers();
|
||||||
const { initialGameSettings } = useGlobalSettings();
|
const { initialGameSettings, playing, settings, preStartCompleted } =
|
||||||
|
useGlobalSettings();
|
||||||
|
|
||||||
let Layout: JSX.Element;
|
let gridLayout: GridLayout;
|
||||||
switch (players.length) {
|
switch (players.length) {
|
||||||
case 1:
|
case 1:
|
||||||
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
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;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
switch (initialGameSettings?.orientation) {
|
switch (initialGameSettings?.orientation) {
|
||||||
case Orientation.Portrait:
|
case Orientation.Portrait:
|
||||||
Layout = Player(players, 'grid-areas-twoPlayersOppositePortrait');
|
gridLayout = 'grid-areas-twoPlayersOppositePortrait';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case Orientation.Landscape:
|
case Orientation.Landscape:
|
||||||
Layout = Player(players, 'grid-areas-twoPlayersSameSideLandscape');
|
gridLayout = 'grid-areas-twoPlayersSameSideLandscape';
|
||||||
break;
|
break;
|
||||||
case Orientation.OppositeLandscape:
|
case Orientation.OppositeLandscape:
|
||||||
Layout = Player(players, 'grid-areas-twoPlayersOppositeLandscape');
|
gridLayout = 'grid-areas-twoPlayersOppositeLandscape';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
||||||
Layout = Player(players, 'grid-areas-threePlayersSide');
|
gridLayout = 'grid-areas-threePlayersSide';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Layout = Player(players, 'grid-areas-threePlayers');
|
gridLayout = 'grid-areas-threePlayers';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case 4:
|
case 4:
|
||||||
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
||||||
Layout = Player(players, 'grid-areas-fourPlayerPortrait');
|
gridLayout = 'grid-areas-fourPlayerPortrait';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Layout = Player(players, 'grid-areas-fourPlayer');
|
gridLayout = 'grid-areas-fourPlayer';
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
||||||
Layout = Player(players, 'grid-areas-fivePlayersSide');
|
gridLayout = 'grid-areas-fivePlayersSide';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Layout = Player(players, 'grid-areas-fivePlayers');
|
gridLayout = 'grid-areas-fivePlayers';
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
if (initialGameSettings?.orientation === Orientation.Portrait) {
|
||||||
Layout = Player(players, 'grid-areas-sixPlayersSide');
|
gridLayout = 'grid-areas-sixPlayersSide';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Layout = Player(players, 'grid-areas-sixPlayers');
|
gridLayout = 'grid-areas-sixPlayers';
|
||||||
break;
|
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 { twc } from 'react-twc';
|
||||||
import React from 'react';
|
|
||||||
import { theme } from '../../../Data/theme';
|
|
||||||
import {
|
import {
|
||||||
FivePlayers,
|
FivePlayers,
|
||||||
|
FivePlayersSide,
|
||||||
FourPlayers,
|
FourPlayers,
|
||||||
FourPlayersSide,
|
FourPlayersSide,
|
||||||
OnePlayerPortrait,
|
OnePlayerPortrait,
|
||||||
SixPlayers,
|
SixPlayers,
|
||||||
|
SixPlayersSide,
|
||||||
ThreePlayers,
|
ThreePlayers,
|
||||||
ThreePlayersSide,
|
ThreePlayersSide,
|
||||||
TwoPlayersOppositeLandscape,
|
TwoPlayersOppositeLandscape,
|
||||||
TwoPlayersOppositePortrait,
|
TwoPlayersOppositePortrait,
|
||||||
TwoPlayersSameSide,
|
TwoPlayersSameSide,
|
||||||
} from '../../../Icons/generated/Layouts';
|
} from '../../../Icons/generated/Layouts';
|
||||||
|
|
||||||
import { twc } from 'react-twc';
|
|
||||||
import OnePlayerLandscape from '../../../Icons/generated/Layouts/OnePlayerLandscape';
|
import OnePlayerLandscape from '../../../Icons/generated/Layouts/OnePlayerLandscape';
|
||||||
import { Orientation } from '../../../Types/Settings';
|
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 = {
|
type LayoutOptionsProps = {
|
||||||
numberOfPlayers: number;
|
numberOfPlayers: number;
|
||||||
@@ -26,366 +32,212 @@ type LayoutOptionsProps = {
|
|||||||
onChange: (orientation: Orientation) => void;
|
onChange: (orientation: Orientation) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
export const LayoutOptions = ({
|
||||||
numberOfPlayers,
|
numberOfPlayers,
|
||||||
selectedOrientation,
|
selectedOrientation,
|
||||||
onChange,
|
onChange,
|
||||||
}) => {
|
}: LayoutOptionsProps) => {
|
||||||
const iconHeight = '30vmin';
|
switch (numberOfPlayers) {
|
||||||
const iconWidth = '20vmin';
|
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 = () => {
|
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Portrait}`}>
|
||||||
switch (numberOfPlayers) {
|
<Input
|
||||||
case 1:
|
type="radio"
|
||||||
return (
|
id={`${numberOfPlayers}p-${Orientation.Portrait}`}
|
||||||
<>
|
checked={selectedOrientation === Orientation.Portrait}
|
||||||
<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
|
|
||||||
value={Orientation.Portrait}
|
value={Orientation.Portrait}
|
||||||
control={
|
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||||
<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=""
|
|
||||||
/>
|
/>
|
||||||
</>
|
<IconWrapper>
|
||||||
);
|
<OnePlayerPortrait className="w-full h-full" />
|
||||||
case 2:
|
</IconWrapper>
|
||||||
return (
|
</Label>
|
||||||
<>
|
</LayoutsRadioGroup>
|
||||||
<FormControlLabel
|
);
|
||||||
|
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}
|
value={Orientation.Landscape}
|
||||||
control={
|
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||||
<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=""
|
|
||||||
/>
|
/>
|
||||||
<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}
|
value={Orientation.Portrait}
|
||||||
control={
|
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||||
<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=""
|
|
||||||
/>
|
/>
|
||||||
<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}
|
value={Orientation.OppositeLandscape}
|
||||||
control={
|
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||||
<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=""
|
|
||||||
/>
|
/>
|
||||||
</>
|
<IconWrapper>
|
||||||
);
|
<TwoPlayersOppositeLandscape className="w-full h-full" />
|
||||||
case 3:
|
</IconWrapper>
|
||||||
return (
|
</Label>
|
||||||
<>
|
</LayoutsRadioGroup>
|
||||||
<FormControlLabel
|
);
|
||||||
|
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}
|
value={Orientation.Landscape}
|
||||||
control={
|
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||||
<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=""
|
|
||||||
/>
|
/>
|
||||||
<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}
|
value={Orientation.Portrait}
|
||||||
control={
|
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||||
<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=""
|
|
||||||
/>
|
/>
|
||||||
</>
|
<IconWrapper>
|
||||||
);
|
<ThreePlayersSide className="w-full h-full" />
|
||||||
|
</IconWrapper>
|
||||||
|
</Label>
|
||||||
|
</LayoutsRadioGroup>
|
||||||
|
);
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
return (
|
return (
|
||||||
<>
|
<LayoutsRadioGroup>
|
||||||
<FormControlLabel
|
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Landscape}`}>
|
||||||
|
<Input
|
||||||
|
type="radio"
|
||||||
|
id={`${numberOfPlayers}p-${Orientation.Landscape}`}
|
||||||
|
checked={selectedOrientation === Orientation.Landscape}
|
||||||
value={Orientation.Landscape}
|
value={Orientation.Landscape}
|
||||||
control={
|
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||||
<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=""
|
|
||||||
/>
|
/>
|
||||||
<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}
|
value={Orientation.Portrait}
|
||||||
control={
|
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||||
<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=""
|
|
||||||
/>
|
/>
|
||||||
</>
|
<IconWrapper>
|
||||||
);
|
<FourPlayersSide className="w-full h-full" />
|
||||||
|
</IconWrapper>
|
||||||
|
</Label>
|
||||||
|
</LayoutsRadioGroup>
|
||||||
|
);
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
return (
|
return (
|
||||||
<>
|
<LayoutsRadioGroup>
|
||||||
<FormControlLabel
|
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Landscape}`}>
|
||||||
|
<Input
|
||||||
|
type="radio"
|
||||||
|
id={`${numberOfPlayers}p-${Orientation.Landscape}`}
|
||||||
|
checked={selectedOrientation === Orientation.Landscape}
|
||||||
value={Orientation.Landscape}
|
value={Orientation.Landscape}
|
||||||
control={
|
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||||
<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=""
|
|
||||||
/>
|
/>
|
||||||
{/* <FormControlLabel
|
<IconWrapper>
|
||||||
value={GridTemplateAreas.FivePlayersSide}
|
<FivePlayers className="w-full h-full" />
|
||||||
control={
|
</IconWrapper>
|
||||||
<Radio
|
</Label>
|
||||||
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=""
|
|
||||||
/> */}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
case 6:
|
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Portrait}`}>
|
||||||
return (
|
<Input
|
||||||
<>
|
type="radio"
|
||||||
<FormControlLabel
|
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}
|
value={Orientation.Landscape}
|
||||||
control={
|
onChange={(e) => onChange(e.target.value as Orientation)}
|
||||||
<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=""
|
|
||||||
/>
|
/>
|
||||||
{/* <FormControlLabel
|
<IconWrapper>
|
||||||
value={GridTemplateAreas.SixPlayersSide}
|
<SixPlayers className="w-full h-full" />
|
||||||
control={
|
</IconWrapper>
|
||||||
<Radio
|
</Label>
|
||||||
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=""
|
|
||||||
/> */}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
default:
|
<Label htmlFor={`${numberOfPlayers}p-${Orientation.Portrait}`}>
|
||||||
return null;
|
<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 (
|
default:
|
||||||
<LayoutWrapper>
|
return null;
|
||||||
<RadioGroup
|
}
|
||||||
row
|
|
||||||
onChange={(_e, value) => {
|
|
||||||
onChange(value as Orientation);
|
|
||||||
}}
|
|
||||||
value={selectedOrientation}
|
|
||||||
style={{ justifyContent: 'center' }}
|
|
||||||
>
|
|
||||||
{renderLayoutOptions()}
|
|
||||||
</RadioGroup>
|
|
||||||
</LayoutWrapper>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,80 +1,51 @@
|
|||||||
import { Button, FormControl, FormLabel, Switch } from '@mui/material';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import Slider from '@mui/material/Slider';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { twc } from 'react-twc';
|
import { twc } from 'react-twc';
|
||||||
import { createInitialPlayers } from '../../../Data/getInitialPlayers';
|
import { createInitialPlayers } from '../../../Data/getInitialPlayers';
|
||||||
import { theme } from '../../../Data/theme';
|
|
||||||
import { useAnalytics } from '../../../Hooks/useAnalytics';
|
import { useAnalytics } from '../../../Hooks/useAnalytics';
|
||||||
import { useGlobalSettings } from '../../../Hooks/useGlobalSettings';
|
import { useGlobalSettings } from '../../../Hooks/useGlobalSettings';
|
||||||
import { usePlayers } from '../../../Hooks/usePlayers';
|
import { usePlayers } from '../../../Hooks/usePlayers';
|
||||||
import { Cog, Info } from '../../../Icons/generated';
|
import { Cog, Info, Trinket } from '../../../Icons/generated';
|
||||||
import {
|
import {
|
||||||
GameFormat,
|
|
||||||
InitialGameSettings,
|
InitialGameSettings,
|
||||||
Orientation,
|
Orientation,
|
||||||
|
PreStartMode,
|
||||||
|
defaultInitialGameSettings,
|
||||||
} from '../../../Types/Settings';
|
} from '../../../Types/Settings';
|
||||||
import { InfoModal } from '../../Misc/InfoModal';
|
|
||||||
import { SettingsModal } from '../../Misc/SettingsModal';
|
|
||||||
import { SupportMe } from '../../Misc/SupportMe';
|
|
||||||
import { LayoutOptions } from './LayoutOptions';
|
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`h-fit w-full 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 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 = [
|
let tracked = false;
|
||||||
{
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const Start = () => {
|
const Start = () => {
|
||||||
const { setPlayers } = usePlayers();
|
const { setPlayers } = usePlayers();
|
||||||
@@ -87,27 +58,50 @@ const Start = () => {
|
|||||||
setInitialGameSettings,
|
setInitialGameSettings,
|
||||||
settings,
|
settings,
|
||||||
isPWA,
|
isPWA,
|
||||||
|
setRandomizingPlayer,
|
||||||
|
version,
|
||||||
|
setPlaying,
|
||||||
|
savedGame,
|
||||||
|
saveCurrentGame,
|
||||||
} = useGlobalSettings();
|
} = useGlobalSettings();
|
||||||
|
|
||||||
const [openInfoModal, setOpenInfoModal] = useState(false);
|
const infoDialogRef = useRef<HTMLDialogElement | null>(null);
|
||||||
const [openSettingsModal, setOpenSettingsModal] = useState(false);
|
const settingsDialogRef = useRef<HTMLDialogElement | null>(null);
|
||||||
|
|
||||||
const [playerOptions, setPlayerOptions] = useState<InitialGameSettings>(
|
const [playerOptions, setPlayerOptions] = useState<InitialGameSettings>(
|
||||||
initialGameSettings || {
|
initialGameSettings || defaultInitialGameSettings
|
||||||
numberOfPlayers: 4,
|
|
||||||
startingLifeTotal: 40,
|
|
||||||
useCommanderDamage: true,
|
|
||||||
orientation: Orientation.Portrait,
|
|
||||||
gameFormat: GameFormat.Commander,
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
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) {
|
if (!initialGameSettings) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
analytics.trackEvent('game_started', { ...initialGameSettings });
|
analytics.trackEvent('game_started', {
|
||||||
|
...initialGameSettings,
|
||||||
|
...settings,
|
||||||
|
isPWA,
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (settings.goFullscreenOnStart) {
|
if (settings.goFullscreenOnStart) {
|
||||||
@@ -123,180 +117,238 @@ const Start = () => {
|
|||||||
|
|
||||||
setInitialGameSettings(initialGameSettings);
|
setInitialGameSettings(initialGameSettings);
|
||||||
setPlayers(createInitialPlayers(initialGameSettings));
|
setPlayers(createInitialPlayers(initialGameSettings));
|
||||||
|
setRandomizingPlayer(settings.preStartMode === PreStartMode.RandomKing);
|
||||||
setShowPlay(true);
|
setShowPlay(true);
|
||||||
localStorage.setItem('playing', 'false');
|
setPlaying(false);
|
||||||
localStorage.setItem('showPlay', 'true');
|
tracked = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
const doResumeGame = () => {
|
||||||
setInitialGameSettings(playerOptions);
|
if (!savedGame) {
|
||||||
}, [playerOptions, setInitialGameSettings]);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const valuetext = (value: number) => {
|
analytics.trackEvent('game_resumed', {
|
||||||
return `${value}`;
|
...initialGameSettings,
|
||||||
};
|
...settings,
|
||||||
|
isPWA,
|
||||||
useEffect(() => {
|
|
||||||
setPlayerOptions({
|
|
||||||
...playerOptions,
|
|
||||||
});
|
});
|
||||||
// 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 (
|
return (
|
||||||
<MainWrapper>
|
<>
|
||||||
<Info
|
<InfoDialog dialogRef={infoDialogRef} />
|
||||||
color={theme.palette.primary.light}
|
|
||||||
size="2rem"
|
|
||||||
style={{ position: 'absolute', top: '1rem', left: '1rem' }}
|
|
||||||
onClick={() => {
|
|
||||||
setOpenInfoModal(!openInfoModal);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<InfoModal
|
<SettingsDialog dialogRef={settingsDialogRef} />
|
||||||
closeModal={() => {
|
<div className="flex justify-center items-center w-screen">
|
||||||
setOpenInfoModal(false);
|
<MainWrapper>
|
||||||
}}
|
<Info
|
||||||
isOpen={openInfoModal}
|
className="size-8 absolute top-7 left-4 text-primary-main"
|
||||||
/>
|
onClick={() => {
|
||||||
|
openInfo();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<a href="https://lifetrinket.com/">
|
||||||
|
<Trinket className="absolute w-12 h-12 top-4 right-4" />
|
||||||
|
</a>
|
||||||
|
|
||||||
<SettingsModal
|
<h1 className="relative flex flex-col text-3xl font-bold mt-6 mb-6 text-text-primary justify-center items-center">
|
||||||
closeModal={() => {
|
<div className="flex flex-row items-center">Life Trinket</div>
|
||||||
setOpenSettingsModal(false);
|
<div className="h-[1px] w-[120%] bg-common-white opacity-50" />
|
||||||
}}
|
<div className="flex absolute text-xs font-medium -bottom-4">
|
||||||
isOpen={openSettingsModal}
|
v{version.installedVersion}
|
||||||
/>
|
</div>
|
||||||
|
</h1>
|
||||||
|
|
||||||
<SupportMe />
|
<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: e.target.checked,
|
||||||
|
...standardSettings,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<h1 className="text-3xl block font-bold mt-6 mb-5 text-text-primary">
|
<div className="flex flex-nowrap text-nowrap relative justify-center items-start">
|
||||||
Life Trinket
|
<button
|
||||||
</h1>
|
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 font-bold">
|
||||||
|
<Cog />
|
||||||
|
Game Settings
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<FormControl focused={false} style={{ width: '80vw' }}>
|
<div
|
||||||
<FormLabel>Number of Players</FormLabel>
|
data-not-latest-version={
|
||||||
<Slider
|
!version.isLatest && !!version.remoteVersion
|
||||||
title="Number of Players"
|
}
|
||||||
max={6}
|
className="absolute flex justify-center text-text-primary text-xxs -bottom-5 bg-primary-dark px-2 rounded-md
|
||||||
min={1}
|
opacity-0 transition-all duration-200 delay-500
|
||||||
aria-label="Custom marks"
|
data-[not-latest-version=true]:opacity-100
|
||||||
value={playerOptions?.numberOfPlayers ?? 4}
|
"
|
||||||
getAriaValueText={valuetext}
|
>
|
||||||
step={null}
|
<div className="absolute bg-primary-dark rotate-45 size-2 -top-[2px] z-0" />
|
||||||
marks={playerMarks}
|
<span className="z-10">
|
||||||
onChange={(_e, value) => {
|
v{version.remoteVersion} available!
|
||||||
setPlayerOptions({
|
</span>
|
||||||
...playerOptions,
|
</div>
|
||||||
numberOfPlayers: value as number,
|
</div>
|
||||||
orientation: Orientation.Landscape,
|
</ToggleButtonsWrapper>
|
||||||
});
|
<LabelText className="mt-4">Number of Players</LabelText>
|
||||||
}}
|
<SliderWrapper>
|
||||||
/>
|
<input
|
||||||
<FormLabel className="mt-[0.7rem]">Starting Health</FormLabel>
|
className="accent-primary-main text-primary-dark w-full h-3 rounded-lg cursor-pointer"
|
||||||
<Slider
|
title="Number of Players"
|
||||||
title="Starting Health"
|
type="range"
|
||||||
max={60}
|
max={6}
|
||||||
min={20}
|
min={1}
|
||||||
aria-label="Custom marks"
|
value={playerOptions?.numberOfPlayers ?? 4}
|
||||||
value={playerOptions?.startingLifeTotal ?? 40}
|
onChange={(e) => {
|
||||||
getAriaValueText={valuetext}
|
setPlayerOptions({
|
||||||
step={10}
|
...playerOptions,
|
||||||
marks={healthMarks}
|
numberOfPlayers: Number.parseInt(e.target.value),
|
||||||
onChange={(_e, value) =>
|
orientation: Orientation.Landscape,
|
||||||
setPlayerOptions({
|
});
|
||||||
...playerOptions,
|
}}
|
||||||
startingLifeTotal: value as number,
|
/>
|
||||||
orientation: Orientation.Landscape,
|
<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>
|
||||||
|
|
||||||
<ToggleButtonsWrapper className="mt-4">
|
<LabelText className="mt-4">Starting Health</LabelText>
|
||||||
<ToggleContainer>
|
<SliderWrapper>
|
||||||
<FormLabel>Commander</FormLabel>
|
<input
|
||||||
<Switch
|
className="accent-primary-main text-primary-dark w-full h-3 rounded-lg cursor-pointer"
|
||||||
checked={
|
title="Starting Health"
|
||||||
playerOptions.useCommanderDamage ??
|
type="range"
|
||||||
initialGameSettings?.useCommanderDamage ??
|
max={60}
|
||||||
true
|
min={20}
|
||||||
}
|
aria-label="Custom marks"
|
||||||
onChange={(_e, value) => {
|
value={playerOptions?.startingLifeTotal ?? 40}
|
||||||
if (value) {
|
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({
|
setPlayerOptions({
|
||||||
...playerOptions,
|
...playerOptions,
|
||||||
useCommanderDamage: value,
|
orientation,
|
||||||
numberOfPlayers: 4,
|
|
||||||
startingLifeTotal: 40,
|
|
||||||
orientation: Orientation.Landscape,
|
|
||||||
});
|
});
|
||||||
return;
|
}}
|
||||||
}
|
/>
|
||||||
setPlayerOptions({
|
</div>
|
||||||
...playerOptions,
|
{!isPWA && (
|
||||||
useCommanderDamage: value,
|
<p className="text-center text-xs text-text-primary w-11/12 mt-4">
|
||||||
numberOfPlayers: 2,
|
If you're on iOS, this page works better if you{' '}
|
||||||
startingLifeTotal: 20,
|
<strong>hide the toolbar</strong> or{' '}
|
||||||
orientation: Orientation.Landscape,
|
<strong>add the app to your home screen</strong>.
|
||||||
});
|
</p>
|
||||||
}}
|
)}
|
||||||
/>
|
</div>
|
||||||
</ToggleContainer>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
style={{ height: '2rem' }}
|
|
||||||
onClick={() => {
|
|
||||||
setOpenSettingsModal(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Cog /> Other settings
|
|
||||||
</Button>
|
|
||||||
</ToggleButtonsWrapper>
|
|
||||||
|
|
||||||
<FormLabel>Layout</FormLabel>
|
<StartButtonFooter>
|
||||||
{/* <LayoutOptions
|
<button
|
||||||
numberOfPlayers={playerOptions.numberOfPlayers}
|
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 font-bold"
|
||||||
gridAreas={playerOptions.gridAreas}
|
onClick={doStartNewGame}
|
||||||
onChange={(gridAreas) =>
|
>
|
||||||
setPlayerOptions({
|
NEW GAME
|
||||||
...playerOptions,
|
</button>
|
||||||
gridAreas,
|
|
||||||
//TODO fix the layout selection
|
|
||||||
orientation: Orientation.Portrait,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/> */}
|
|
||||||
<LayoutOptions
|
|
||||||
numberOfPlayers={playerOptions.numberOfPlayers}
|
|
||||||
selectedOrientation={playerOptions.orientation}
|
|
||||||
onChange={(orientation) => {
|
|
||||||
setPlayerOptions({
|
|
||||||
...playerOptions,
|
|
||||||
orientation,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
{!isPWA && (
|
{savedGame && (
|
||||||
<p className="text-center, max-w-[75%] text-xs text-text-primary">
|
<button
|
||||||
If you're on iOS, this page works better if you{' '}
|
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]
|
||||||
<strong>hide the toolbar</strong> or{' '}
|
|
||||||
<strong>add the app to your home screen</strong>.
|
duration-200 ease-in-out shadow-[1px_2px_4px_0px_rgba(0,0,0,0.3)] hover:bg-secondary-dark font-bold"
|
||||||
</p>
|
onClick={doResumeGame}
|
||||||
)}
|
>
|
||||||
|
RESUME
|
||||||
<StartButtonFooter>
|
<span className="text-xs">
|
||||||
<Button
|
({savedGame.players.length}
|
||||||
size="large"
|
{savedGame.players.length > 1 ? 'players' : 'player'})
|
||||||
variant="contained"
|
</span>
|
||||||
onClick={doStartGame}
|
</button>
|
||||||
style={{ width: '90dvw' }}
|
)}
|
||||||
>
|
</StartButtonFooter>
|
||||||
START GAME
|
</MainWrapper>
|
||||||
</Button>
|
</div>
|
||||||
</StartButtonFooter>
|
</>
|
||||||
</MainWrapper>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
import { InitialGameSettings, Settings } from '../Types/Settings';
|
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 = {
|
export type GlobalSettingsContextType = {
|
||||||
fullscreen: {
|
fullscreen: {
|
||||||
@@ -18,11 +31,20 @@ export type GlobalSettingsContextType = {
|
|||||||
goToStart: () => void;
|
goToStart: () => void;
|
||||||
showPlay: boolean;
|
showPlay: boolean;
|
||||||
setShowPlay: (showPlay: boolean) => void;
|
setShowPlay: (showPlay: boolean) => void;
|
||||||
initialGameSettings: InitialGameSettings | null;
|
initialGameSettings: InitialGameSettings;
|
||||||
setInitialGameSettings: (initialGameSettings: InitialGameSettings) => void;
|
setInitialGameSettings: (initialGameSettings: InitialGameSettings) => void;
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
setSettings: (settings: Settings) => void;
|
setSettings: (settings: Settings) => void;
|
||||||
|
playing: boolean;
|
||||||
|
setPlaying: (playing: boolean) => void;
|
||||||
|
randomizingPlayer: boolean;
|
||||||
|
setRandomizingPlayer: (stopRandom: boolean) => void;
|
||||||
isPWA: boolean;
|
isPWA: boolean;
|
||||||
|
preStartCompleted: boolean;
|
||||||
|
setPreStartCompleted: (completed: boolean) => void;
|
||||||
|
version: Version;
|
||||||
|
savedGame: SavedGame;
|
||||||
|
saveCurrentGame: (currentGame: SavedGame) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GlobalSettingsContext =
|
export const GlobalSettingsContext =
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ export type PlayersContextType = {
|
|||||||
updatePlayer: (updatedPlayer: Player) => void;
|
updatePlayer: (updatedPlayer: Player) => void;
|
||||||
updateLifeTotal: (player: Player, updatedLifeTotal: number) => number;
|
updateLifeTotal: (player: Player, updatedLifeTotal: number) => number;
|
||||||
resetCurrentGame: () => void;
|
resetCurrentGame: () => void;
|
||||||
|
startingPlayerIndex: number;
|
||||||
|
setStartingPlayerIndex: (index: number) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PlayersContext = createContext<PlayersContextType | null>(null);
|
export const PlayersContext = createContext<PlayersContextType | null>(null);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Player, Rotation } from '../Types/Player';
|
import { Player, Rotation } from '../Types/Player';
|
||||||
import { InitialGameSettings, Orientation } from '../Types/Settings';
|
import { InitialGameSettings, Orientation } from '../Types/Settings';
|
||||||
|
|
||||||
const presetColors = [
|
export const presetColors = [
|
||||||
'#F06292', // Light Pink
|
'#F06292', // Light Pink
|
||||||
'#4DB6AC', // Teal
|
'#4DB6AC', // Teal
|
||||||
'#FFA726', // Orange
|
'#FFA726', // Orange
|
||||||
@@ -127,15 +127,15 @@ const getOrientationRotations = (
|
|||||||
case Orientation.Portrait:
|
case Orientation.Portrait:
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
return Rotation.Side;
|
return Rotation.Flipped;
|
||||||
case 1:
|
case 1:
|
||||||
return Rotation.Side;
|
return Rotation.Flipped;
|
||||||
case 2:
|
case 2:
|
||||||
return Rotation.SideFlipped;
|
return Rotation.Side;
|
||||||
case 3:
|
case 3:
|
||||||
return Rotation.SideFlipped;
|
return Rotation.Normal;
|
||||||
case 4:
|
case 4:
|
||||||
return Rotation.SideFlipped;
|
return Rotation.Normal;
|
||||||
default:
|
default:
|
||||||
return Rotation.Normal;
|
return Rotation.Normal;
|
||||||
}
|
}
|
||||||
@@ -163,17 +163,17 @@ const getOrientationRotations = (
|
|||||||
case Orientation.Portrait:
|
case Orientation.Portrait:
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
return Rotation.Side;
|
return Rotation.SideFlipped;
|
||||||
case 1:
|
case 1:
|
||||||
return Rotation.Side;
|
return Rotation.Flipped;
|
||||||
case 2:
|
case 2:
|
||||||
return Rotation.Side;
|
return Rotation.Flipped;
|
||||||
case 3:
|
case 3:
|
||||||
return Rotation.SideFlipped;
|
return Rotation.Side;
|
||||||
case 4:
|
case 4:
|
||||||
return Rotation.SideFlipped;
|
return Rotation.Normal;
|
||||||
case 5:
|
case 5:
|
||||||
return Rotation.SideFlipped;
|
return Rotation.Normal;
|
||||||
default:
|
default:
|
||||||
return Rotation.Normal;
|
return Rotation.Normal;
|
||||||
}
|
}
|
||||||
@@ -191,10 +191,8 @@ export const createInitialPlayers = ({
|
|||||||
}: InitialGameSettings): Player[] => {
|
}: InitialGameSettings): Player[] => {
|
||||||
const players: Player[] = [];
|
const players: Player[] = [];
|
||||||
const availableColors = [...presetColors]; // Create a copy of the colors array
|
const availableColors = [...presetColors]; // Create a copy of the colors array
|
||||||
const firstPlayerIndex = Math.floor(Math.random() * numberOfPlayers);
|
|
||||||
|
|
||||||
for (let i = 0; i <= numberOfPlayers - 1; i++) {
|
for (let i = 0; i <= numberOfPlayers - 1; i++) {
|
||||||
const isStartingPlayer = i === firstPlayerIndex;
|
|
||||||
const colorIndex = Math.floor(Math.random() * availableColors.length);
|
const colorIndex = Math.floor(Math.random() * availableColors.length);
|
||||||
const color = availableColors[colorIndex];
|
const color = availableColors[colorIndex];
|
||||||
|
|
||||||
@@ -224,11 +222,11 @@ export const createInitialPlayers = ({
|
|||||||
usePoison: false,
|
usePoison: false,
|
||||||
rotation,
|
rotation,
|
||||||
},
|
},
|
||||||
isStartingPlayer,
|
|
||||||
showStartingPlayer: isStartingPlayer,
|
|
||||||
extraCounters: [],
|
extraCounters: [],
|
||||||
commanderDamage,
|
commanderDamage,
|
||||||
hasLost: false,
|
hasLost: false,
|
||||||
|
isStartingPlayer: false,
|
||||||
|
isSide: rotation === Rotation.Side || rotation === Rotation.SideFlipped,
|
||||||
};
|
};
|
||||||
|
|
||||||
players.push(player);
|
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,
|
eventName: string,
|
||||||
eventParams?: { [key: string]: unknown }
|
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 };
|
return { trackEvent };
|
||||||
|
|||||||
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 };
|
||||||
|
}
|
||||||
45
src/Icons/generated/Close.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { SVGProps } from 'react';
|
||||||
|
interface SVGRProps {
|
||||||
|
title?: string;
|
||||||
|
titleId?: string;
|
||||||
|
size?: string;
|
||||||
|
}
|
||||||
|
const Close = ({
|
||||||
|
title,
|
||||||
|
titleId,
|
||||||
|
...props
|
||||||
|
}: SVGProps<SVGSVGElement> & SVGRProps) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={props.size || 16}
|
||||||
|
height={props.size || 16}
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 52 52"
|
||||||
|
aria-labelledby={titleId}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M26 48c12.15 0 22-9.85 22-22S38.15 4 26 4 4 13.85 4 26s9.85 22 22 22m0 4c14.36 0 26-11.64 26-26S40.36 0 26 0 0 11.64 0 26s11.64 26 26 26"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M15.586 15.586a2 2 0 0 1 2.828 0l18 18a2 2 0 1 1-2.828 2.828l-18-18a2 2 0 0 1 0-2.828"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M36.414 15.586a2 2 0 0 1 0 2.828l-18 18a2 2 0 1 1-2.828-2.828l18-18a2 2 0 0 1 2.828 0"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
Close.propTypes = {
|
||||||
|
title: PropTypes.string,
|
||||||
|
};
|
||||||
|
export default Close;
|
||||||
@@ -22,7 +22,7 @@ const Cog = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const CommanderTax = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const Cross = ({
|
|||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
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>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const Energy = ({
|
|||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
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>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ const Exit = ({
|
|||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<g fill="currentColor">
|
<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="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-.6z" />
|
<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>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const Experience = ({
|
|||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<g fill="currentColor">
|
<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>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const FullscreenOff = ({
|
|||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<g fill="currentColor">
|
<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>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const FullscreenOn = ({
|
|||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<g fill="currentColor">
|
<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>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -15,15 +15,17 @@ const Info = ({
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width={props.size || 16}
|
width={props.size || 16}
|
||||||
height={props.size || 16}
|
height={props.size || 16}
|
||||||
viewBox="0 0 524 524"
|
fill="currentColor"
|
||||||
|
viewBox="0 0 52 52"
|
||||||
aria-labelledby={titleId}
|
aria-labelledby={titleId}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<g fill="currentColor">
|
<path
|
||||||
<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" />
|
fillRule="evenodd"
|
||||||
<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" />
|
d="M26 48c12.15 0 22-9.85 22-22S38.15 4 26 4 4 13.85 4 26s9.85 22 22 22m0 4c14.36 0 26-11.64 26-26S40.36 0 26 0 0 11.64 0 26s11.64 26 26 26m-4.191-36.87-.264.172c-2.513 1.644-2.671 5.27-.31 7.125a2 2 0 1 1-2.47 3.146c-4.514-3.547-4.213-10.477.591-13.619l.264-.172a11.66 11.66 0 0 1 12.76 0l.77.503c4.556 2.98 4.841 9.551.561 12.914-.422.332-.877.62-1.357.86l-.54.27A6.9 6.9 0 0 0 28 32.5a2 2 0 1 1-4 0 10.9 10.9 0 0 1 6.025-9.748l.54-.27q.36-.18.675-.428c2.128-1.672 1.986-4.94-.28-6.421l-.769-.503a7.66 7.66 0 0 0-8.382 0M26 42a3 3 0 1 0 0-6 3 3 0 0 0 0 6"
|
||||||
</g>
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const FivePlayers = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.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="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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const FivePlayersSide = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.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="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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const FourPlayers = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.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="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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const FourPlayersSide = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.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="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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const OnePlayerLandscape = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.5z" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const OnePlayerPortrait = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.7z" />
|
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const SixPlayers = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.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="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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const SixPlayersSide = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.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="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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const ThreePlayers = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.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="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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const ThreePlayersSide = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.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="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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const TwoPlayersOppositeLandscape = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.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="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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const TwoPlayersOppositePortrait = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.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="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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ const TwoPlayersSameSide = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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="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.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="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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ const LittleGuy = ({
|
|||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<g fill="currentColor">
|
<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="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.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="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>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const Logo = ({
|
|||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<path
|
<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={{
|
style={{
|
||||||
stroke: '#590713',
|
stroke: '#590713',
|
||||||
strokeWidth: 0,
|
strokeWidth: 0,
|
||||||
@@ -39,7 +39,7 @@ const Logo = ({
|
|||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
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={{
|
style={{
|
||||||
stroke: '#000',
|
stroke: '#000',
|
||||||
strokeWidth: 4,
|
strokeWidth: 4,
|
||||||
@@ -52,12 +52,12 @@ const Logo = ({
|
|||||||
fillRule: 'nonzero',
|
fillRule: 'nonzero',
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
}}
|
}}
|
||||||
transform="rotate(1 -17129.538 10072.475) scale(2.11279)"
|
transform="rotate(1 -17129.538 10072.475)scale(2.11279)"
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
fill="none"
|
fill="none"
|
||||||
strokeLinecap="round"
|
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={{
|
style={{
|
||||||
stroke: '#000',
|
stroke: '#000',
|
||||||
strokeWidth: 6,
|
strokeWidth: 6,
|
||||||
@@ -76,7 +76,7 @@ const Logo = ({
|
|||||||
<path
|
<path
|
||||||
fill="none"
|
fill="none"
|
||||||
strokeLinecap="round"
|
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={{
|
style={{
|
||||||
stroke: '#000',
|
stroke: '#000',
|
||||||
strokeWidth: 6,
|
strokeWidth: 6,
|
||||||
@@ -95,7 +95,7 @@ const Logo = ({
|
|||||||
<path
|
<path
|
||||||
fill="none"
|
fill="none"
|
||||||
strokeLinecap="round"
|
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={{
|
style={{
|
||||||
stroke: '#000',
|
stroke: '#000',
|
||||||
strokeWidth: 6,
|
strokeWidth: 6,
|
||||||
@@ -114,7 +114,7 @@ const Logo = ({
|
|||||||
<path
|
<path
|
||||||
fill="none"
|
fill="none"
|
||||||
strokeLinecap="round"
|
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={{
|
style={{
|
||||||
stroke: '#000',
|
stroke: '#000',
|
||||||
strokeWidth: 6,
|
strokeWidth: 6,
|
||||||
@@ -133,7 +133,7 @@ const Logo = ({
|
|||||||
<path
|
<path
|
||||||
fill="none"
|
fill="none"
|
||||||
strokeLinecap="round"
|
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={{
|
style={{
|
||||||
stroke: '#000',
|
stroke: '#000',
|
||||||
strokeWidth: 6,
|
strokeWidth: 6,
|
||||||
@@ -152,7 +152,7 @@ const Logo = ({
|
|||||||
<path
|
<path
|
||||||
fill="none"
|
fill="none"
|
||||||
strokeLinecap="round"
|
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={{
|
style={{
|
||||||
stroke: '#000',
|
stroke: '#000',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
@@ -166,11 +166,11 @@ const Logo = ({
|
|||||||
fillRule: 'nonzero',
|
fillRule: 'nonzero',
|
||||||
opacity: 1,
|
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
|
<path
|
||||||
strokeLinecap="round"
|
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={{
|
style={{
|
||||||
stroke: '#000',
|
stroke: '#000',
|
||||||
strokeWidth: 6,
|
strokeWidth: 6,
|
||||||
@@ -225,7 +225,7 @@ const Logo = ({
|
|||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
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={{
|
style={{
|
||||||
stroke: '#000',
|
stroke: '#000',
|
||||||
strokeWidth: 6,
|
strokeWidth: 6,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const PartnerTax = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const Poison = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{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>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const ResetGame = ({
|
|||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
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>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ const Skull = ({
|
|||||||
>
|
>
|
||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<g fill="currentColor">
|
<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="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-.9z" />
|
<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>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -23,23 +23,23 @@ const BuyMeCoffee = ({
|
|||||||
{title ? <title id={titleId}>{title}</title> : null}
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
<path
|
<path
|
||||||
fill="#0D0C22"
|
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
|
<path
|
||||||
fill="#0D0C22"
|
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
|
<path
|
||||||
fill="#FD0"
|
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
|
<path
|
||||||
fill="#0D0C22"
|
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
|
<path
|
||||||
fill="#0D0C22"
|
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>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ const KoFi = ({
|
|||||||
<use x={97} y={83} href="#a" />
|
<use x={97} y={83} href="#a" />
|
||||||
<path
|
<path
|
||||||
fillRule="evenodd"
|
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
|
<path
|
||||||
fillRule="evenodd"
|
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
|
<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={{
|
style={{
|
||||||
fill: '#ff504f',
|
fill: '#ff504f',
|
||||||
}}
|
}}
|
||||||
|
|||||||
51
src/Icons/generated/Trinket.tsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { SVGProps } from 'react';
|
||||||
|
interface SVGRProps {
|
||||||
|
title?: string;
|
||||||
|
titleId?: string;
|
||||||
|
size?: string;
|
||||||
|
}
|
||||||
|
const Trinket = ({
|
||||||
|
title,
|
||||||
|
titleId,
|
||||||
|
...props
|
||||||
|
}: SVGProps<SVGSVGElement> & SVGRProps) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={props.size || 16}
|
||||||
|
height={props.size || 16}
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 364 472"
|
||||||
|
aria-labelledby={titleId}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{title ? <title id={titleId}>{title}</title> : null}
|
||||||
|
<path
|
||||||
|
fill="#78A083"
|
||||||
|
d="M40.536 302.159c-6.366-1.843-13.102 1.822-14.118 8.371-1.599 10.309-1.49 20.912.345 31.493 2.538 14.638 8.327 28.947 17.037 42.11s18.895 21.898 32.45 31.582 32.017 14.639 48.355 19.37 34.674 9.982 51.306 9.04c16.633-.942 29.437-2.571 43.833-9.043s26.935-15.473 36.901-26.49c7.205-7.964 12.964-16.868 17.121-26.436 2.641-6.078-1.095-12.775-7.461-14.619L153.42 334.848zM323.254 168.504c6.37 1.832 13.099-1.846 14.102-8.397 1.579-10.312 1.449-20.915-.405-31.493-2.566-14.633-8.382-28.93-17.117-42.077s-18.937-21.862-32.511-31.52-32.044-14.578-48.391-19.278-34.693-9.916-51.324-8.942-29.432 2.626-43.815 9.126-26.905 15.525-36.851 26.56c-7.19 7.978-12.93 16.893-17.07 26.468-2.629 6.084 1.12 12.774 7.489 14.605l112.946 32.474z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="url(#a)"
|
||||||
|
d="M75.577 127.413c2.38-5.473 3.57-8.209 5.537-9.963a12 12 0 0 1 6.168-2.906c2.604-.399 5.472.425 11.207 2.074l216.593 62.274c5.73 1.648 8.595 2.471 10.588 4.191a12 12 0 0 1 3.683 5.732c.736 2.528.295 5.476-.588 11.372l-10.644 71.096c-.14.937-.211 1.405-.317 1.865q-.141.614-.347 1.209c-.154.446-.343.881-.721 1.749l-28.861 66.269c-2.382 5.469-3.573 8.204-5.538 9.956a12 12 0 0 1-6.168 2.904c-2.603.398-5.469-.426-11.202-2.074L48.371 290.886c-5.732-1.648-8.597-2.472-10.59-4.191a12 12 0 0 1-3.684-5.735c-.735-2.527-.293-5.476.592-11.374l10.654-71.027c.14-.934.21-1.401.316-1.86q.142-.612.346-1.206c.153-.445.342-.878.718-1.744z"
|
||||||
|
/>
|
||||||
|
<defs>
|
||||||
|
<radialGradient
|
||||||
|
id="a"
|
||||||
|
cx={0}
|
||||||
|
cy={0}
|
||||||
|
r={1}
|
||||||
|
gradientTransform="matrix(-25.05324 87.13566 -130.70377 -37.57994 181.959 234.953)"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<stop stopColor="#FFF4BE" />
|
||||||
|
<stop offset={1} stopColor="#FFC374" />
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
Trinket.propTypes = {
|
||||||
|
title: PropTypes.string,
|
||||||
|
};
|
||||||
|
export default Trinket;
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export { default as Close } from './Close';
|
||||||
export { default as Cog } from './Cog';
|
export { default as Cog } from './Cog';
|
||||||
export { default as CommanderTax } from './CommanderTax';
|
export { default as CommanderTax } from './CommanderTax';
|
||||||
export { default as Cross } from './Cross';
|
export { default as Cross } from './Cross';
|
||||||
@@ -13,3 +14,4 @@ export { default as PartnerTax } from './PartnerTax';
|
|||||||
export { default as Poison } from './Poison';
|
export { default as Poison } from './Poison';
|
||||||
export { default as ResetGame } from './ResetGame';
|
export { default as ResetGame } from './ResetGame';
|
||||||
export { default as Skull } from './Skull';
|
export { default as Skull } from './Skull';
|
||||||
|
export { default as Trinket } from './Trinket';
|
||||||
|
|||||||
5
src/Icons/svgs/Close.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg width="52" height="52" viewBox="0 0 52 52" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M26 48C38.1503 48 48 38.1503 48 26C48 13.8497 38.1503 4 26 4C13.8497 4 4 13.8497 4 26C4 38.1503 13.8497 48 26 48ZM26 52C40.3594 52 52 40.3594 52 26C52 11.6406 40.3594 0 26 0C11.6406 0 0 11.6406 0 26C0 40.3594 11.6406 52 26 52Z" fill="currentColor"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.5858 15.5858C16.3668 14.8047 17.6332 14.8047 18.4142 15.5858L36.4142 33.5858C37.1953 34.3668 37.1953 35.6332 36.4142 36.4142C35.6332 37.1953 34.3668 37.1953 33.5858 36.4142L15.5858 18.4142C14.8047 17.6332 14.8047 16.3668 15.5858 15.5858Z" fill="currentColor"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M36.4142 15.5858C37.1953 16.3668 37.1953 17.6332 36.4142 18.4142L18.4142 36.4142C17.6332 37.1953 16.3668 37.1953 15.5858 36.4142C14.8047 35.6332 14.8047 34.3668 15.5858 33.5858L33.5858 15.5858C34.3668 14.8047 35.6332 14.8047 36.4142 15.5858Z" fill="currentColor"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -1,30 +1,3 @@
|
|||||||
<?xml version="1.0" standalone="no"?>
|
<svg width="52" height="52" viewBox="0 0 52 52" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M26 48C38.1503 48 48 38.1503 48 26C48 13.8497 38.1503 4 26 4C13.8497 4 4 13.8497 4 26C4 38.1503 13.8497 48 26 48ZM26 52C40.3594 52 52 40.3594 52 26C52 11.6406 40.3594 0 26 0C11.6406 0 0 11.6406 0 26C0 40.3594 11.6406 52 26 52ZM21.8089 15.1299L21.5454 15.3022C19.0317 16.9458 18.874 20.5718 21.2356 22.4274C22.1042 23.1098 22.2551 24.3671 21.5726 25.2356C20.8902 26.1042 19.6329 26.2551 18.7644 25.5726C14.2506 22.0261 14.5519 15.0957 19.3564 11.9543L19.62 11.782C23.4958 9.24777 28.5042 9.24777 32.3801 11.782L33.1496 12.2851C37.7056 15.2641 37.9913 21.8361 33.711 25.1992C33.2888 25.5309 32.834 25.8191 32.3537 26.0592L31.8138 26.3292C29.4764 27.4978 28 29.8868 28 32.5C28 33.6046 27.1046 34.5 26 34.5C24.8954 34.5 24 33.6046 24 32.5C24 28.3717 26.3325 24.5977 30.0249 22.7515L30.5649 22.4815C30.8037 22.3621 31.0298 22.2188 31.2397 22.0539C33.3679 20.3817 33.2258 17.1141 30.9606 15.633L30.1911 15.1299C27.645 13.4651 24.355 13.4651 21.8089 15.1299ZM26 42C27.6569 42 29 40.6569 29 39C29 37.3431 27.6569 36 26 36C24.3431 36 23 37.3431 23 39C23 40.6569 24.3431 42 26 42Z" fill="currentColor"/>
|
||||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
|
||||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="524.000000pt" height="524.000000pt" viewBox="0 0 524.000000 524.000000"
|
|
||||||
preserveAspectRatio="xMidYMid meet">
|
|
||||||
|
|
||||||
<g transform="translate(0.000000,524.000000) scale(0.100000,-0.100000)"
|
|
||||||
fill="currentColor" stroke="none">
|
|
||||||
<path d="M2367 4905 c-288 -36 -514 -102 -754 -220 -686 -337 -1151 -972
|
|
||||||
-1269 -1735 -25 -160 -25 -500 0 -660 116 -750 572 -1383 1241 -1722 329 -167
|
|
||||||
652 -243 1035 -243 221 0 342 14 545 62 311 73 654 243 908 452 91 74 270 255
|
|
||||||
343 346 250 313 418 701 480 1110 25 164 25 483 0 650 -114 762 -586 1408
|
|
||||||
-1269 1740 -232 112 -421 171 -677 210 -145 22 -447 28 -583 10z m573 -454
|
|
||||||
c746 -132 1336 -702 1496 -1444 86 -403 35 -820 -146 -1193 -385 -794 -1264
|
|
||||||
-1204 -2125 -993 -887 218 -1488 1076 -1394 1990 73 715 567 1338 1244 1568
|
|
||||||
122 41 271 74 405 91 118 14 388 4 520 -19z"/>
|
|
||||||
<path d="M2465 4120 c-208 -20 -362 -86 -485 -211 -115 -116 -193 -264 -275
|
|
||||||
-520 -34 -106 -36 -119 -24 -144 20 -41 58 -65 114 -71 74 -9 92 10 178 190
|
|
||||||
149 308 257 419 460 473 84 23 298 22 386 -1 212 -55 346 -195 359 -376 8
|
|
||||||
-111 -23 -164 -205 -352 -260 -268 -380 -456 -442 -692 -30 -113 -46 -316 -36
|
|
||||||
-460 7 -113 9 -121 35 -148 26 -25 35 -28 95 -28 57 0 69 3 90 25 14 13 25 32
|
|
||||||
26 42 1 10 2 99 3 198 2 203 16 281 71 402 76 166 237 360 425 513 224 182
|
|
||||||
281 279 280 478 -1 198 -61 354 -179 465 -86 81 -148 118 -266 157 -165 54
|
|
||||||
-413 78 -610 60z"/>
|
|
||||||
<path d="M2524 1511 c-42 -18 -54 -50 -54 -139 0 -46 5 -92 10 -103 18 -33 64
|
|
||||||
-49 140 -49 126 0 155 33 149 169 -6 113 -19 125 -137 128 -48 2 -97 -1 -108
|
|
||||||
-6z"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.2 KiB |
11
src/Icons/svgs/Trinket.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<svg width="364" height="472" viewBox="0 0 364 472" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M40.5356 302.159C34.1697 300.316 27.4337 303.981 26.418 310.53C24.8192 320.839 24.9288 331.442 26.7633 342.023C29.3011 356.661 35.0901 370.97 43.7998 384.133C52.5096 397.296 62.695 406.031 76.2507 415.715C89.8064 425.399 108.267 430.354 124.605 435.085C140.943 439.816 159.279 445.067 175.911 444.125C192.544 443.183 205.348 441.554 219.744 435.082C234.14 428.61 246.679 419.609 256.645 408.592C263.85 400.628 269.609 391.724 273.766 382.156C276.407 376.078 272.671 369.381 266.305 367.537L153.42 334.848L40.5356 302.159Z" fill="#78A083"/>
|
||||||
|
<path d="M323.254 168.504C329.624 170.336 336.353 166.658 337.356 160.107C338.935 149.795 338.805 139.192 336.951 128.614C334.385 113.981 328.569 99.6837 319.834 86.5374C311.099 73.3911 300.897 64.6755 287.323 55.0171C273.749 45.3588 255.279 40.4391 238.932 35.7391C222.585 31.0391 204.239 25.8229 187.608 26.7968C170.977 27.7707 158.176 29.4234 143.793 35.923C129.41 42.4225 116.888 51.4477 106.942 62.4834C99.7528 70.4607 94.0113 79.3756 89.8724 88.9514C87.2431 95.035 90.9911 101.725 97.3605 103.556L210.307 136.03L323.254 168.504Z" fill="#78A083"/>
|
||||||
|
<path d="M75.5773 127.413C77.9577 121.94 79.1479 119.204 81.1136 117.45C82.8455 115.905 84.9883 114.896 87.2823 114.544C89.8859 114.145 92.7537 114.969 98.4892 116.618L315.082 178.892C320.812 180.54 323.677 181.363 325.67 183.083C327.426 184.597 328.705 186.589 329.353 188.815C330.089 191.343 329.648 194.291 328.765 200.187L318.121 271.283C317.981 272.22 317.91 272.688 317.804 273.148C317.71 273.557 317.594 273.961 317.457 274.357C317.303 274.803 317.114 275.238 316.736 276.106L287.875 342.375C285.493 347.844 284.302 350.579 282.337 352.331C280.605 353.875 278.462 354.883 276.169 355.235C273.566 355.633 270.7 354.809 264.967 353.161L48.371 290.886C42.6395 289.238 39.7737 288.414 37.7805 286.695C36.0242 285.179 34.7448 283.188 34.097 280.96C33.3618 278.433 33.8042 275.484 34.6888 269.586L45.3425 198.559C45.4826 197.625 45.5527 197.158 45.6588 196.699C45.753 196.291 45.8686 195.889 46.0048 195.493C46.1582 195.048 46.3466 194.615 46.7235 193.749L75.5773 127.413Z" fill="url(#paint0_radial_14799_77884)"/>
|
||||||
|
<defs>
|
||||||
|
<radialGradient id="paint0_radial_14799_77884" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(181.959 234.953) rotate(106.041) scale(90.6658 135.999)">
|
||||||
|
<stop stop-color="#FFF4BE"/>
|
||||||
|
<stop offset="1" stop-color="#FFC374"/>
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -3,13 +3,18 @@ import { useWakeLock } from 'react-screen-wake-lock';
|
|||||||
import {
|
import {
|
||||||
GlobalSettingsContext,
|
GlobalSettingsContext,
|
||||||
GlobalSettingsContextType,
|
GlobalSettingsContextType,
|
||||||
|
SavedGame,
|
||||||
} from '../Contexts/GlobalSettingsContext';
|
} from '../Contexts/GlobalSettingsContext';
|
||||||
import { useAnalytics } from '../Hooks/useAnalytics';
|
import { useAnalytics } from '../Hooks/useAnalytics';
|
||||||
import {
|
import {
|
||||||
InitialGameSettings,
|
InitialGameSettings,
|
||||||
InitialGameSettingsSchema,
|
|
||||||
Settings,
|
Settings,
|
||||||
|
defaultInitialGameSettings,
|
||||||
|
defaultSettings,
|
||||||
|
initialGameSettingsSchema,
|
||||||
|
settingsSchema,
|
||||||
} from '../Types/Settings';
|
} from '../Types/Settings';
|
||||||
|
import { gte as semverGreaterThanOrEqual } from 'semver';
|
||||||
|
|
||||||
export const GlobalSettingsProvider = ({
|
export const GlobalSettingsProvider = ({
|
||||||
children,
|
children,
|
||||||
@@ -18,60 +23,131 @@ export const GlobalSettingsProvider = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const analytics = useAnalytics();
|
const analytics = useAnalytics();
|
||||||
|
|
||||||
const savedShowPlay = localStorage.getItem('showPlay');
|
const localSavedGame = localStorage.getItem('savedGame');
|
||||||
const savedGameSettings = localStorage.getItem('initialGameSettings');
|
const [savedGame, setCurrentGame] = useState<SavedGame>(
|
||||||
const savedSettings = localStorage.getItem('settings');
|
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>(
|
const [showPlay, setShowPlay] = useState<boolean>(
|
||||||
savedShowPlay ? savedShowPlay === 'true' : false
|
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] =
|
const [initialGameSettings, setInitialGameSettings] =
|
||||||
useState<InitialGameSettings | null>(
|
useState<InitialGameSettings>(
|
||||||
savedGameSettings ? JSON.parse(savedGameSettings) : null
|
savedGameSettings
|
||||||
|
? JSON.parse(savedGameSettings)
|
||||||
|
: defaultInitialGameSettings
|
||||||
);
|
);
|
||||||
|
|
||||||
const [settings, setSettings] = useState<Settings>(
|
const setInitialGameSettingsAndLocalStorage = (
|
||||||
savedSettings
|
initialGameSettings: InitialGameSettings
|
||||||
? JSON.parse(savedSettings)
|
) => {
|
||||||
: { goFullscreenOnStart: true, keepAwake: true, showStartingPlayer: true }
|
setInitialGameSettings(initialGameSettings);
|
||||||
);
|
localStorage.setItem(
|
||||||
|
'initialGameSettings',
|
||||||
|
JSON.stringify(initialGameSettings)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const removeLocalStorage = async () => {
|
const removeLocalStorage = async () => {
|
||||||
localStorage.removeItem('initialGameSettings');
|
localStorage.removeItem('initialGameSettings');
|
||||||
localStorage.removeItem('players');
|
localStorage.removeItem('players');
|
||||||
localStorage.removeItem('playing');
|
localStorage.removeItem('playing');
|
||||||
localStorage.removeItem('showPlay');
|
localStorage.removeItem('showPlay');
|
||||||
|
localStorage.removeItem('preStartComplete');
|
||||||
|
|
||||||
|
setPlaying(false);
|
||||||
setShowPlay(false);
|
setShowPlay(false);
|
||||||
|
setPreStartCompleted(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Set settings if they are not valid
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (savedGameSettings && JSON.parse(savedGameSettings).gridAreas) {
|
// If there are no saved settings, set default settings
|
||||||
removeLocalStorage();
|
if (!savedSettings) {
|
||||||
window.location.reload();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//parse existing game settings with zod schema
|
//parse existing game settings with zod schema
|
||||||
const parsedInitialGameSettings =
|
const parsedInitialGameSettings =
|
||||||
InitialGameSettingsSchema.safeParse(initialGameSettings);
|
initialGameSettingsSchema.safeParse(initialGameSettings);
|
||||||
|
|
||||||
if (!parsedInitialGameSettings.success) {
|
if (!parsedInitialGameSettings.success) {
|
||||||
removeLocalStorage();
|
console.error('invalid game settings, resetting to default settings');
|
||||||
window.location.reload();
|
setInitialGameSettingsAndLocalStorage(defaultInitialGameSettings);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'initialGameSettings',
|
'initialGameSettings',
|
||||||
JSON.stringify(initialGameSettings)
|
JSON.stringify(parsedInitialGameSettings.data)
|
||||||
);
|
);
|
||||||
}, [initialGameSettings, savedGameSettings]);
|
}, [initialGameSettings, savedGameSettings]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
localStorage.setItem('settings', JSON.stringify(settings));
|
|
||||||
}, [settings]);
|
|
||||||
|
|
||||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -87,6 +163,11 @@ export const GlobalSettingsProvider = ({
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const [isLatestVersion, setIsLatestVersion] = useState(false);
|
||||||
|
const [remoteVersion, setRemoteVersion] = useState<string | undefined>(
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
|
||||||
const { isSupported, release, released, request, type } = useWakeLock();
|
const { isSupported, release, released, request, type } = useWakeLock();
|
||||||
|
|
||||||
const active = settings.keepAwake;
|
const active = settings.keepAwake;
|
||||||
@@ -135,6 +216,56 @@ 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);
|
||||||
|
|
||||||
|
const isLatest = semverGreaterThanOrEqual(
|
||||||
|
import.meta.env.VITE_APP_VERSION,
|
||||||
|
data.name
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isLatest) {
|
||||||
|
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 {
|
return {
|
||||||
fullscreen: { isFullscreen, enableFullscreen, disableFullscreen },
|
fullscreen: { isFullscreen, enableFullscreen, disableFullscreen },
|
||||||
wakeLock: {
|
wakeLock: {
|
||||||
@@ -147,24 +278,45 @@ export const GlobalSettingsProvider = ({
|
|||||||
},
|
},
|
||||||
goToStart,
|
goToStart,
|
||||||
showPlay,
|
showPlay,
|
||||||
setShowPlay,
|
setShowPlay: setShowPlayAndLocalStorage,
|
||||||
|
playing,
|
||||||
|
setPlaying: setPlayingAndLocalStorage,
|
||||||
initialGameSettings,
|
initialGameSettings,
|
||||||
setInitialGameSettings,
|
setInitialGameSettings,
|
||||||
settings,
|
settings,
|
||||||
setSettings,
|
setSettings: setSettingsAndLocalStorage,
|
||||||
|
randomizingPlayer,
|
||||||
|
setRandomizingPlayer,
|
||||||
isPWA: window?.matchMedia('(display-mode: standalone)').matches,
|
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,
|
isFullscreen,
|
||||||
isSupported,
|
isSupported,
|
||||||
release,
|
release,
|
||||||
|
active,
|
||||||
request,
|
request,
|
||||||
settings,
|
|
||||||
showPlay,
|
|
||||||
type,
|
type,
|
||||||
|
showPlay,
|
||||||
|
playing,
|
||||||
|
initialGameSettings,
|
||||||
|
settings,
|
||||||
|
randomizingPlayer,
|
||||||
|
preStartCompleted,
|
||||||
|
savedGame,
|
||||||
|
remoteVersion,
|
||||||
|
isLatestVersion,
|
||||||
|
analytics,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -7,6 +7,17 @@ import { InitialGameSettings } from '../Types/Settings';
|
|||||||
export const PlayersProvider = ({ children }: { children: ReactNode }) => {
|
export const PlayersProvider = ({ children }: { children: ReactNode }) => {
|
||||||
const savedPlayers = localStorage.getItem('players');
|
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[]>(
|
const [players, setPlayers] = useState<Player[]>(
|
||||||
savedPlayers ? JSON.parse(savedPlayers) : []
|
savedPlayers ? JSON.parse(savedPlayers) : []
|
||||||
);
|
);
|
||||||
@@ -50,9 +61,7 @@ export const PlayersProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const startingPlayerIndex = Math.floor(
|
const newStartingPlayerIndex = Math.floor(Math.random() * players.length);
|
||||||
Math.random() * initialGameSettings.numberOfPlayers
|
|
||||||
);
|
|
||||||
|
|
||||||
players.forEach((player: Player) => {
|
players.forEach((player: Player) => {
|
||||||
player.commanderDamage.map((damage) => {
|
player.commanderDamage.map((damage) => {
|
||||||
@@ -65,16 +74,9 @@ export const PlayersProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
player.lifeTotal = initialGameSettings.startingLifeTotal;
|
player.lifeTotal = initialGameSettings.startingLifeTotal;
|
||||||
|
|
||||||
player.hasLost = false;
|
player.hasLost = false;
|
||||||
|
|
||||||
const isStartingPlayer = player.index === startingPlayerIndex;
|
player.isStartingPlayer = newStartingPlayerIndex === player.index;
|
||||||
|
|
||||||
player.isStartingPlayer = isStartingPlayer;
|
|
||||||
|
|
||||||
if (player.isStartingPlayer) {
|
|
||||||
player.showStartingPlayer = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePlayer(player);
|
updatePlayer(player);
|
||||||
});
|
});
|
||||||
@@ -87,8 +89,10 @@ export const PlayersProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
updatePlayer,
|
updatePlayer,
|
||||||
updateLifeTotal,
|
updateLifeTotal,
|
||||||
resetCurrentGame,
|
resetCurrentGame,
|
||||||
|
startingPlayerIndex,
|
||||||
|
setStartingPlayerIndex: setStartingPlayerIndexAndLocalStorage,
|
||||||
};
|
};
|
||||||
}, [players]);
|
}, [players, startingPlayerIndex]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PlayersContext.Provider value={ctxValue}>
|
<PlayersContext.Provider value={ctxValue}>
|
||||||
|
|||||||
@@ -6,17 +6,17 @@ export type Player = {
|
|||||||
commanderDamage: CommanderDamage[];
|
commanderDamage: CommanderDamage[];
|
||||||
extraCounters: ExtraCounter[];
|
extraCounters: ExtraCounter[];
|
||||||
isStartingPlayer: boolean;
|
isStartingPlayer: boolean;
|
||||||
showStartingPlayer: boolean;
|
|
||||||
hasLost: boolean;
|
hasLost: boolean;
|
||||||
|
isSide: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PlayerSettings = {
|
export type PlayerSettings = {
|
||||||
rotation: Rotation;
|
rotation: Rotation;
|
||||||
useCommanderDamage: boolean;
|
useCommanderDamage: boolean;
|
||||||
usePartner?: boolean;
|
usePartner: boolean;
|
||||||
usePoison?: boolean;
|
usePoison: boolean;
|
||||||
useEnergy?: boolean;
|
useEnergy: boolean;
|
||||||
useExperience?: boolean;
|
useExperience: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ExtraCounter = {
|
type ExtraCounter = {
|
||||||
|
|||||||
@@ -12,10 +12,19 @@ export enum GameFormat {
|
|||||||
TwoHeadedGiant = 'two-headed-giant',
|
TwoHeadedGiant = 'two-headed-giant',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum PreStartMode {
|
||||||
|
None = 'none',
|
||||||
|
RandomKing = 'random-king',
|
||||||
|
FingerGame = 'finger-game',
|
||||||
|
Trivia = 'trivia',
|
||||||
|
}
|
||||||
|
|
||||||
export type Settings = {
|
export type Settings = {
|
||||||
keepAwake: boolean;
|
keepAwake: boolean;
|
||||||
showStartingPlayer: boolean;
|
showStartingPlayer: boolean;
|
||||||
|
showPlayerMenuCog: boolean;
|
||||||
goFullscreenOnStart: boolean;
|
goFullscreenOnStart: boolean;
|
||||||
|
preStartMode: PreStartMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type InitialGameSettings = {
|
export type InitialGameSettings = {
|
||||||
@@ -26,10 +35,34 @@ export type InitialGameSettings = {
|
|||||||
orientation: Orientation;
|
orientation: Orientation;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const InitialGameSettingsSchema = z.object({
|
export const initialGameSettingsSchema = z.object({
|
||||||
startingLifeTotal: z.number().min(1).max(200).default(20),
|
startingLifeTotal: z.number().min(1).max(200),
|
||||||
useCommanderDamage: z.boolean().default(false),
|
useCommanderDamage: z.boolean(),
|
||||||
gameFormat: z.nativeEnum(GameFormat).optional(),
|
gameFormat: z.nativeEnum(GameFormat),
|
||||||
numberOfPlayers: z.number().min(1).max(6).default(2),
|
numberOfPlayers: z.number().min(1).max(6),
|
||||||
orientation: z.nativeEnum(Orientation).default(Orientation.Landscape),
|
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
@@ -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 components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
html {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
background-color: theme('colors.background.default');
|
background-color: theme('colors.background.default');
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
@@ -21,6 +31,37 @@ code {
|
|||||||
monospace;
|
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 {
|
@layer utilities {
|
||||||
.pointer-events-all {
|
.pointer-events-all {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
@@ -33,4 +74,9 @@ code {
|
|||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.show-scrollbar {
|
||||||
|
scrollbar-width: auto;
|
||||||
|
-ms-overflow-style: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/vite-env.d.ts
vendored
@@ -1 +1,11 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <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,88 @@
|
|||||||
import tailwindcssGridAreas from '@savvywombat/tailwindcss-grid-areas';
|
import tailwindcssGridAreas from '@savvywombat/tailwindcss-grid-areas';
|
||||||
import type { Config } from 'tailwindcss';
|
import type { Config } from 'tailwindcss';
|
||||||
|
|
||||||
|
export const baseColors = {
|
||||||
|
primary: {
|
||||||
|
main: '#78A083',
|
||||||
|
dark: '#608069',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: '#5D7965',
|
||||||
|
dark: '#4a6151',
|
||||||
|
},
|
||||||
|
background: {
|
||||||
|
default: '#35374B',
|
||||||
|
backdrop: 'rgba(0, 0, 0, 0.3)',
|
||||||
|
settings: 'rgba(0, 0, 0, 0.8)',
|
||||||
|
},
|
||||||
|
icons: {
|
||||||
|
dark: '#00000080',
|
||||||
|
light: '#F9FFE34f',
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: '#F9FFE3',
|
||||||
|
secondary: '#c7ccb6',
|
||||||
|
},
|
||||||
|
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} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
export default {
|
export default {
|
||||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||||
theme: {
|
theme: {
|
||||||
|
screens: {
|
||||||
|
modalSm: '548px',
|
||||||
|
},
|
||||||
extend: {
|
extend: {
|
||||||
gridTemplateAreas: {
|
gridTemplateAreas: twGridTemplateAreas,
|
||||||
onePlayerLandscape: ['player0 player0'],
|
colors: baseColors,
|
||||||
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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
keyframes: {
|
keyframes: {
|
||||||
fadeOut: {
|
fadeOut: {
|
||||||
'0%': {
|
'0%': {
|
||||||
@@ -91,19 +100,11 @@ export default {
|
|||||||
animation: {
|
animation: {
|
||||||
fadeOut: 'fadeOut 3s 1s ease-out forwards',
|
fadeOut: 'fadeOut 3s 1s ease-out forwards',
|
||||||
},
|
},
|
||||||
|
fontSize: {
|
||||||
|
xxs: ['0.625rem', '1rem'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [tailwindcssGridAreas],
|
plugins: [tailwindcssGridAreas],
|
||||||
} satisfies Config;
|
} satisfies Config;
|
||||||
|
// #98FF98
|
||||||
// const fadeOut = keyframes`
|
|
||||||
// 0% {
|
|
||||||
// opacity: 1;
|
|
||||||
// }
|
|
||||||
// 33% {
|
|
||||||
// opacity: 0.6;
|
|
||||||
// }
|
|
||||||
// 100% {
|
|
||||||
// opacity: 0;
|
|
||||||
// }
|
|
||||||
// `;
|
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import react from '@vitejs/plugin-react-swc';
|
import { VitePWA } from 'vite-plugin-pwa';
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [
|
||||||
|
VitePWA({
|
||||||
|
registerType: 'autoUpdate',
|
||||||
|
workbox: {
|
||||||
|
clientsClaim: true,
|
||||||
|
skipWaiting: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
build: {
|
build: {
|
||||||
minify: 'esbuild',
|
minify: 'esbuild',
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
@@ -11,7 +19,14 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
define: {
|
define: {
|
||||||
APP_VERSION: JSON.stringify(process.env.npm_package_version),
|
'import.meta.env.VITE_APP_VERSION': JSON.stringify(
|
||||||
REPO_READ_ACCESS_TOKEN: JSON.stringify(process.env.REPO_READ_ACCESS_TOKEN),
|
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
|
||||||
|
),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||