feat: start of monorepo

This commit is contained in:
TrèsAbhi committed 2024-09-06 21:45:58 -05:00
1 parent 14f39d71ac
commit 73c7bdf0c0
260 files changed
+1236 -1235

No files matched your search

+75
View File
@@ -0,0 +1,75 @@
'use client';
import { imgur } from '@blitzkit/core';
import { Box, BoxProps, Text } from '@radix-ui/themes';
import { uniqueId } from 'lodash';
import { useEffect, useRef } from 'react';
import { Vector2Tuple } from 'three';
export enum AdType {
MediumRectangleHorizontalPurple = 738182777,
LeaderboardHorizontalPurple = 84051521,
WideSkyscraperVerticalPurple = 1755617140,
HalfPageVerticalPurple = 880185176,
}
const AD_DIMENSIONS: Record<AdType, Vector2Tuple> = {
[AdType.MediumRectangleHorizontalPurple]: [300, 250],
[AdType.LeaderboardHorizontalPurple]: [728, 90],
[AdType.WideSkyscraperVerticalPurple]: [160, 600],
[AdType.HalfPageVerticalPurple]: [300, 600],
};
type AdProps = BoxProps & {
type: AdType;
};
export function Ad({ type, style, ...props }: AdProps) {
const id = useRef(uniqueId());
const dimensions = AD_DIMENSIONS[type];
useEffect(() => {
(window as any).msAdsQueue.push(function () {
(window as any).mmnow.render({
adUnitId: type,
elementId: `${type}-${id.current}`,
});
});
}, [type]);
return (
<Box
position="relative"
width={`${dimensions[0]}px`}
height={`${dimensions[1]}px`}
style={{
outline: '1px solid var(--gray-3)',
borderRadius: 'var(--radius-1)',
background: `url(${imgur('DK21EHY')})`,
...style,
}}
{...props}
>
<Text
color="gray"
style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
}}
align="center"
>
Advertisement
</Text>
<Box
width={`${dimensions[0]}px`}
height={`${dimensions[1]}px`}
position="relative"
id={`${type}-${id.current}`}
/>
</Box>
);
}
@@ -0,0 +1,19 @@
import { Flex, FlexProps } from '@radix-ui/themes';
import { Ad, AdType } from './Ad';
export function AdMidSectionNarrowOnly(props: FlexProps) {
return (
<Flex
justify="center"
py="4"
gap="4"
display={{
initial: 'flex',
sm: 'none',
}}
{...props}
>
<Ad type={AdType.MediumRectangleHorizontalPurple} />
</Flex>
);
}
@@ -0,0 +1,23 @@
import { Flex, FlexProps } from '@radix-ui/themes';
import { Ad, AdType } from './Ad';
export function AdMidSectionResponsive(props: FlexProps) {
return (
<Flex justify="center" py="4" gap="4" {...props}>
<Ad
display={{
initial: 'none',
sm: 'block',
}}
type={AdType.LeaderboardHorizontalPurple}
/>
<Ad
display={{
initial: 'block',
sm: 'none',
}}
type={AdType.MediumRectangleHorizontalPurple}
/>
</Flex>
);
}
@@ -0,0 +1,19 @@
import { Flex, FlexProps } from '@radix-ui/themes';
import { Ad, AdType } from './Ad';
export function AdMidSectionWideOnly(props: FlexProps) {
return (
<Flex
justify="center"
py="4"
gap="4"
display={{
initial: 'none',
sm: 'flex',
}}
{...props}
>
<Ad type={AdType.LeaderboardHorizontalPurple} />
</Flex>
);
}
@@ -0,0 +1,40 @@
import { ComponentProps } from 'react';
export function BlitzkitButtonGrayIcon(props: ComponentProps<'svg'>) {
return (
<svg
width="426"
height="426"
viewBox="0 0 426 426"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g clip-path="url(#clip0_600_256)">
<path
d="M416.628 244.997L235.625 372.974C223.13 381.809 202.87 381.809 190.375 372.974L9.37173 244.997C3.1239 240.58 -3.95076e-06 234.79 0 229V196.6L213 77.5L426 196.6V229C426 234.79 422.876 240.58 416.628 244.997Z"
fill="#9E9E9E"
/>
<path
d="M200.456 257.38L221.999 242.08C228.557 237.422 231.732 232.85 231.521 228.364C231.31 223.797 228.392 219.516 222.764 215.519C217.193 211.562 211.22 209.529 204.846 209.42C198.473 209.23 192.007 211.465 185.448 216.123L163.905 231.422L200.456 257.38Z"
fill="white"
/>
<path
d="M146.77 219.252L165.937 205.64C172.44 201.022 175.726 196.69 175.796 192.643C175.809 188.557 173.256 184.696 168.135 181.059C163.07 177.462 157.717 175.708 152.076 175.798C146.435 175.887 140.363 178.241 133.861 182.859L114.693 196.472L146.77 219.252Z"
fill="white"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M235.625 52.6262L416.628 180.603C429.124 189.438 429.124 203.762 416.628 212.597L235.625 340.574C223.13 349.409 202.87 349.409 190.375 340.574L9.37173 212.597C-3.12391 203.762 -3.12391 189.438 9.37172 180.603L190.375 52.6262C202.87 43.7913 223.13 43.7913 235.625 52.6262ZM290.596 213.945L197.056 150.108L217.292 135.762L265.867 167.722L263.968 133.871L286.355 118L288.049 158.111L359.102 165.378L335.236 182.298L288.86 177.31L289.153 184.23L310.832 199.599L290.596 213.945ZM70 201.714L192.905 289L241.672 254.366C254.96 244.929 262.551 235.142 264.446 225.004C266.398 214.825 261.803 205.779 250.66 197.866C242.613 192.151 234.247 188.9 225.563 188.113C216.935 187.286 208.978 188.301 201.692 191.158L201.354 190.918C204.302 186.506 205.165 181.658 203.941 176.372C202.718 171.006 198.702 165.905 191.893 161.069C180.919 153.275 168.971 150.211 156.048 151.875C143.124 153.539 129.906 159.17 116.393 168.767L70 201.714Z"
fill="white"
/>
</g>
<defs>
<clipPath id="clip0_600_256">
<rect width="426" height="426" fill="white" />
</clipPath>
</defs>
</svg>
);
}
@@ -0,0 +1,13 @@
import { Code } from '@radix-ui/themes';
import { use } from 'react';
import { gameDefinitions } from '../../../core/blitzkit/gameDefinitions';
export function WoTBVersion() {
const awaitedGameDefinitions = use(gameDefinitions);
return (
<Code color="gray" size="2">
{awaitedGameDefinitions.version}
</Code>
);
}
@@ -0,0 +1,14 @@
import { style } from '@vanilla-extract/css';
export const containerInner = style({
justifyContent: 'space-between',
width: '100%',
maxWidth: 1024,
padding: '0 16px',
'@media': {
'screen and (max-width: 640px)': {
justifyContent: 'center',
},
},
});
@@ -0,0 +1,182 @@
'use client';
import { gameDefinitions } from '@blitzkit/core';
import { Code, Flex, Heading, Text, Theme } from '@radix-ui/themes';
import { use } from 'react';
import packageJson from '../../../../../package.json';
import { Link } from '../Link';
export function Footer() {
const awaitedGameDefinitions = use(gameDefinitions);
return (
<Theme radius="none">
<Flex
gap="6"
p="6"
direction="column"
align="center"
style={{ backgroundColor: 'var(--color-panel)' }}
>
<Flex
align="center"
justify="between"
maxWidth="40rem"
width="100%"
flexGrow="1"
gap="5"
position="relative"
direction={{ initial: 'column', sm: 'row' }}
>
<Flex
direction="column"
align={{
initial: 'center',
sm: 'start',
}}
>
<Heading>BlitzKit </Heading>
<Text color="gray">Everything World of Tanks Blitz</Text>
<Text size="1" color="gray">
Unaffiliated with Wargaming or any service
</Text>
</Flex>
<Flex
gap="6"
width={{
initial: '100%',
sm: 'auto',
}}
>
<Flex
direction="column"
gap="1"
align={{
initial: 'end',
sm: 'start',
}}
flexGrow={{
initial: '1',
sm: '0',
}}
flexBasis={{
initial: '0',
sm: 'auto',
}}
>
<Heading size="3">About</Heading>
<Flex
direction="column"
align={{
initial: 'end',
sm: 'start',
}}
>
<Link href="/docs/about/credits" color="gray">
Credits
</Link>
<Link
href="https://discord.gg/nDt7AjGJQH"
target="_blank"
color="gray"
>
Discord
</Link>
<Link
href="https://github.com/tresabhi/blitzkit"
target="_blank"
color="gray"
>
GitHub
</Link>
<Link href="/docs/patches" color="gray">
Patches
</Link>
{/* patreon supporters? */}
</Flex>
</Flex>
<Flex
direction="column"
gap="1"
flexGrow={{
initial: '1',
sm: '0',
}}
flexBasis={{
initial: '0',
sm: 'auto',
}}
>
<Heading size="3">Legal</Heading>
<Flex direction="column">
<Link href="/docs/legal/privacy-policy" color="gray">
Privacy policy
</Link>
<Link href="/docs/legal/terms-of-service" color="gray">
Terms of service
</Link>
<Link
href="https://www.google.com/settings/ads"
target="_blank"
color="gray"
>
Ad settings
</Link>
</Flex>
</Flex>
</Flex>
</Flex>
<Flex gap="5" display={{ initial: 'flex', sm: 'none' }}>
<Flex direction="column" justify="between" align="end">
<Text size="2" color="gray">
BlitzKit
</Text>
<Text size="2" color="gray">
WoT Blitz
</Text>
<Text size="2" color="gray">
CDN
</Text>
</Flex>
<Flex direction="column" justify="between" align="start">
<Code size="2" color="gray">
{packageJson.version}
</Code>
<Code size="2" color="gray">
{awaitedGameDefinitions.version}
</Code>
<Code size="2" color="gray">
{process.env.NEXT_PUBLIC_ASSET_BRANCH}
</Code>
</Flex>
</Flex>
<Flex gap="2" align="center" display={{ initial: 'none', sm: 'flex' }}>
<Text size="2" color="gray">
BlitzKit
</Text>
<Code size="2" color="gray">
{packageJson.version}
</Code>
<Text size="2" color="gray">
WoT Blitz
</Text>
<Code size="2" color="gray">
{awaitedGameDefinitions.version}
</Code>
<Text size="2" color="gray">
CDN
</Text>
<Code size="2" color="gray">
{process.env.NEXT_PUBLIC_ASSET_BRANCH}
</Code>
</Flex>
</Flex>
</Theme>
);
}
+44
View File
@@ -0,0 +1,44 @@
'use client';
import {
Link as RadixLink,
LinkProps as RadixLinkProps,
} from '@radix-ui/themes';
import { useRouter } from 'next/navigation';
import { forwardRef } from 'react';
type LinkProps = RadixLinkProps & {
disabled?: boolean;
};
export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
({ href, onClick, target, disabled, style, ...props }, ref) => {
const router = useRouter();
return (
<RadixLink
style={{
cursor: disabled ? 'not-allowed' : 'pointer',
...style,
}}
ref={ref}
href={disabled ? undefined : href}
onClick={(event) => {
if (disabled) return;
event.preventDefault();
if (href) {
if (event.ctrlKey || event.metaKey || target === '_blank') {
window.open(href);
} else {
router.push(href);
}
}
onClick?.(event);
}}
{...props}
/>
);
},
);
@@ -0,0 +1,22 @@
import { idToRegion } from '@blitzkit/core';
import { Text } from '@radix-ui/themes';
import { use, useMemo } from 'react';
import { getAccountInfo } from '../../../../../../src/core/blitz/getAccountInfo';
import * as App from '../../../stores/app';
export function WargamingAccountName() {
const wargaming = App.use((state) => state.logins.wargaming!);
const promise = useMemo(
() =>
getAccountInfo(idToRegion(wargaming.id), wargaming.id, [], {
access_token: wargaming.token,
}).then((data) => {
console.log(data);
return data?.nickname as string | undefined;
}),
[wargaming],
);
const nickname = use(promise);
return nickname ?? <Text color="gray">Unknown Account</Text>;
}
@@ -0,0 +1,54 @@
import { assertSecret } from '@blitzkit/core';
import { Button, ButtonProps, Dialog, Flex } from '@radix-ui/themes';
import { REGIONS } from '../../../../../../src/constants/regions';
import strings from '../../../../../../src/lang/en-US.json';
import { Link } from '../../Link';
import { WargamingIcon } from '../../WargamingIcon';
export function WargamingLoginButton({ children, ...props }: ButtonProps) {
return (
<Dialog.Root>
<Dialog.Trigger>
<Button
color="red"
{...props}
children={
<>
<WargamingIcon width={15} height={15} /> {children ?? 'Wargaming'}
</>
}
/>
</Dialog.Trigger>
<Dialog.Content width="fit-content">
<Dialog.Title align="center">Choose your region</Dialog.Title>
<Flex gap="2" wrap="wrap" justify="center" align="center">
{REGIONS.map((region) => (
<Dialog.Close key={region}>
<Link
href={
typeof window !== 'undefined'
? `https://api.worldoftanks.${
region
}/wot/auth/login/?application_id=${assertSecret(
process.env.WARGAMING_APPLICATION_ID,
)}&redirect_uri=${encodeURIComponent(
`${location.origin}/auth/wargaming?return=${
location.origin
}${location.pathname}`,
)}`
: undefined
}
>
<Button color="red">
{strings.common.regions.normal[region]}
</Button>
</Link>
</Dialog.Close>
))}
</Flex>
</Dialog.Content>
</Dialog.Root>
);
}
@@ -0,0 +1,69 @@
import { style, styleVariants } from '@vanilla-extract/css';
const MIN_WIDTH = 640 + 128;
export const NAVBAR_HEIGHT = 48;
export const hamburger = style({
display: 'inline-flex',
'@media': {
[`screen and (min-width: ${MIN_WIDTH}px)`]: {
display: 'none',
},
},
});
export const tools = style({
display: 'none',
'@media': {
[`screen and (min-width: ${MIN_WIDTH}px)`]: {
display: 'flex',
},
},
});
export const navbar = style({
height: NAVBAR_HEIGHT,
marginBottom: -1, // 1px overlap with content to bleed color
position: 'sticky',
top: 0,
zIndex: 1,
});
const navbarExpanderBase = style({
transitionDuration: '250ms',
height: '1000px',
width: '100%',
overflow: 'hidden',
backdropFilter: 'blur(4rem) brightness(0.75)',
WebkitBackdropFilter: 'blur(4rem) brightness(0.75)',
'@media': {
[`screen and (min-width: ${MIN_WIDTH}px)`]: {
maxHeight: NAVBAR_HEIGHT,
},
},
});
export const navbarExpander = styleVariants({
false: [
navbarExpanderBase,
{
maxHeight: NAVBAR_HEIGHT,
},
],
true: [
navbarExpanderBase,
{
maxHeight: '100vh',
overscrollBehavior: 'contain',
},
],
});
export const navbarContent = style({
width: '100%',
maxHeight: '100vh',
});
@@ -0,0 +1,325 @@
'use client';
import { assertSecret } from '@blitzkit/core/src/blitzkit/assertSecret';
import { imgur, ImgurSize } from '@blitzkit/core/src/imgur/imgur';
import { patreonLoginUrl } from '@blitzkit/core/src/patreon/patreonLoginUrl';
import {
Cross1Icon,
DiscordLogoIcon,
GearIcon,
HamburgerMenuIcon,
PersonIcon,
} from '@radix-ui/react-icons';
import {
Box,
Button,
Code,
Flex,
Grid,
IconButton,
Inset,
Popover,
ScrollArea,
Separator,
Skeleton,
Text,
} from '@radix-ui/themes';
import { usePathname } from 'next/navigation';
import { Fragment, Suspense, useState } from 'react';
import { BRANCH_NAMES } from '../../app/components/Hero/constants';
import { homeTool, TOOLS } from '../../constants/tools';
import * as App from '../../stores/app';
import { Link } from '../Link';
import { PatreonIcon } from '../PatreonIcon';
import { WargamingIcon } from '../WargamingIcon';
import { WargamingAccountName } from './components/WargamingAccountName';
import { WargamingLoginButton } from './components/WargamingLoginButton';
import * as styles from './index.css';
export function Navbar() {
const [showHamburgerMenu, setShowHamburgerMenu] = useState(false);
const pathname = usePathname();
const logins = App.use((state) => state.logins);
const mutateApp = App.useMutation();
const tools = [homeTool, ...TOOLS];
const isBranchNamed =
process.env.NEXT_PUBLIC_ASSET_BRANCH &&
BRANCH_NAMES[process.env.NEXT_PUBLIC_ASSET_BRANCH];
return (
<Flex className={styles.navbar}>
<Flex
className={styles.navbarExpander[`${showHamburgerMenu}`]}
onClick={() => setShowHamburgerMenu(false)}
direction="column"
gap="2"
>
<Flex justify="center">
<Flex flexGrow="1" maxWidth="1024px" p="3" align="center">
<Flex gap="3" align="center">
<IconButton
variant="ghost"
color="gray"
className={styles.hamburger}
onClick={(event) => {
event.stopPropagation();
setShowHamburgerMenu((state) => !state);
}}
>
{showHamburgerMenu ? <Cross1Icon /> : <HamburgerMenuIcon />}
</IconButton>
<Link
color="gray"
highContrast
href="/"
underline="hover"
weight="bold"
onClick={() => setShowHamburgerMenu(false)}
>
<Flex align="center" gap="1">
BlitzKit
{isBranchNamed && (
<Code color="gray" size="1" highContrast variant="outline">
{BRANCH_NAMES[process.env.NEXT_PUBLIC_ASSET_BRANCH!]}
</Code>
)}
</Flex>
</Link>
</Flex>
<Box flexGrow="1" />
<Flex
align="center"
gap="2"
justify="center"
className={styles.tools}
>
{TOOLS.map((tool, index) => {
const unavailableOnBranch = tool.branches?.every(
(branch) =>
branch !==
assertSecret(process.env.NEXT_PUBLIC_ASSET_BRANCH),
);
const selected = pathname.startsWith(`/tools/${tool.id}`);
if (unavailableOnBranch) return null;
return (
<Fragment key={tool.title}>
{index > 0 && <Separator orientation="vertical" size="1" />}
<Link
onClick={() => setShowHamburgerMenu(false)}
color="gray"
highContrast={selected}
size="2"
href={`/tools/${tool.id}`}
underline={selected ? 'always' : 'hover'}
>
{tool.title}
</Link>
</Fragment>
);
})}
</Flex>
<Box flexGrow="1" />
<Flex align="center" gap="3">
<Link
style={{ display: 'flex', alignContent: 'center' }}
color="gray"
href="https://discord.gg/nDt7AjGJQH"
underline="none"
target="_blank"
onClick={() => setShowHamburgerMenu(false)}
>
<DiscordLogoIcon />
</Link>
<Link
style={{ display: 'flex', alignContent: 'center' }}
color="gray"
href="https://www.patreon.com/tresabhi"
underline="none"
target="_blank"
onClick={() => setShowHamburgerMenu(false)}
>
<PatreonIcon width="0.75em" height="0.75em" />
</Link>
<Link
style={{ display: 'flex', alignContent: 'center' }}
color="gray"
href="/settings"
underline="none"
onClick={() => setShowHamburgerMenu(false)}
>
<GearIcon />
</Link>
<Popover.Root>
<Popover.Trigger>
<IconButton variant="ghost" color="gray">
<PersonIcon />
</IconButton>
</Popover.Trigger>
<Popover.Content
align="end"
width="320px"
onOpenAutoFocus={(event) => event.preventDefault()}
>
{(logins.patreon || logins.wargaming) && (
<Flex direction="column" gap="2">
<Text align="center" color="gray">
Logged in accounts
</Text>
{logins.patreon && (
<Flex align="center" gap="2" justify="center">
<PatreonIcon width={15} height={15} />
<Text>Patreon</Text>
<Button
color="red"
variant="ghost"
onClick={() =>
mutateApp((draft) => {
draft.logins.patreon = undefined;
})
}
>
Logout
</Button>
</Flex>
)}
{logins.wargaming && (
<Flex align="center" gap="2" justify="center">
<WargamingIcon width={15} height={15} />
<Text>
<Suspense
fallback={<Skeleton height="1em" width="5rem" />}
>
<WargamingAccountName />
</Suspense>
</Text>
<Button
color="red"
variant="ghost"
onClick={() =>
mutateApp((draft) => {
draft.logins.wargaming = undefined;
})
}
>
Logout
</Button>
</Flex>
)}
</Flex>
)}
{!logins.patreon !== !logins.wargaming && (
<Inset side="x">
<Separator my="4" size="4" />
</Inset>
)}
{(!logins.patreon || !logins.wargaming) && (
<Flex direction="column" gap="2">
<Text align="center" color="gray">
Log in with...
</Text>
{!logins.patreon && (
<Link
style={{ width: '100%' }}
href={patreonLoginUrl()}
>
<Button style={{ width: '100%' }} color="tomato">
<PatreonIcon width={15} height={15} /> Patreon
</Button>
</Link>
)}
{!logins.wargaming && <WargamingLoginButton />}
</Flex>
)}
</Popover.Content>
</Popover.Root>
</Flex>
</Flex>
</Flex>
<ScrollArea>
<Grid
columns="repeat(auto-fill, minmax(192px, 1fr))"
flow="dense"
gap="2"
width="100%"
p="3"
pt="0"
>
{tools.map((tool) => {
const unavailableOnBranch = tool.branches?.every(
(branch) =>
branch !== assertSecret(process.env.NEXT_PUBLIC_ASSET_BRANCH),
);
if (unavailableOnBranch) return null;
return (
<Flex
key={tool.id}
onClick={() => setShowHamburgerMenu(false)}
style={{
position: 'relative',
borderRadius: 'var(--radius-2)',
overflow: 'hidden',
backgroundImage: `url(${imgur(tool.image, { format: 'jpeg', size: ImgurSize.MediumThumbnail })})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
aspectRatio: '2 / 1',
}}
>
<Link
href={tool.id.length === 0 ? '/' : `/tools/${tool.id}`}
style={{
display: 'flex',
width: '100%',
height: '100%',
flexDirection: 'column',
textDecoration: 'none',
color: 'inherit',
}}
>
<Box
flexGrow="1"
style={{
backgroundImage: `url(${imgur(tool.image, { format: 'jpeg', size: ImgurSize.MediumThumbnail })})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
/>
<Flex
p="2"
align="center"
width="100%"
style={{
backgroundColor: 'var(--color-panel-translucent)',
backdropFilter: 'blur(4rem)',
WebkitBackdropFilter: 'blur(4rem)',
}}
>
<Text weight="medium">{tool.title}</Text>
</Flex>
</Link>
</Flex>
);
})}
</Grid>
</ScrollArea>
</Flex>
</Flex>
);
}
@@ -0,0 +1,54 @@
import { Flex, FlexProps, Theme } from '@radix-ui/themes';
import { ComponentProps } from 'react';
import { RadixSize } from '../../packages/website/src/stores/embedState';
type PageWrapperProps = FlexProps & {
color?: ComponentProps<typeof Theme>['accentColor'];
size?: number | string;
noMaxWidth?: boolean;
containerProps?: ComponentProps<typeof Theme>;
noFlex1?: boolean;
padding?: RadixSize;
};
export default function PageWrapper({
style,
color,
size = 800,
children,
noMaxWidth = false,
noFlex1 = false,
containerProps,
padding = '4',
...props
}: PageWrapperProps) {
return (
<Theme
accentColor={color}
style={{
flex: noFlex1 ? undefined : 1,
display: 'flex',
flexDirection: 'column',
...containerProps?.style,
}}
{...containerProps}
>
<Flex
direction="column"
gap="4"
p={padding}
style={{
width: '100%',
maxWidth: noMaxWidth ? undefined : size,
margin: 'auto',
boxSizing: 'border-box',
flex: 1,
...style,
}}
{...props}
>
{children}
</Flex>
</Theme>
);
}
@@ -0,0 +1,44 @@
'use client';
import { useEffect } from 'react';
export function Party3() {
useEffect(() => {
(window as any).msAdsQueue = (window as any).msAdsQueue || [];
}, []);
return (
<>
{/* analytics */}
<script
async
src="https://www.googletagmanager.com/gtag/js?id=G-GL2JVHCGPQ"
/>
<script
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-GL2JVHCGPQ');
`,
}}
/>
{/* adsense */}
{/* <script
async
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-1289406790225052"
crossOrigin="anonymous"
/> */}
{/* pub center */}
{/* <script
async
src="https://adsdk.microsoft.com/mmnow/sdk.js?siteId=364645&publisherId=253617120"
crossOrigin="anonymous"
/> */}
</>
);
}
@@ -0,0 +1,13 @@
import { ComponentProps } from 'react';
export function PatreonIcon(props: ComponentProps<'svg'>) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 436 476" {...props}>
<path
fill="currentColor"
data-fill="1"
d="M436 143c-.084-60.778-47.57-110.591-103.285-128.565C263.528-7.884 172.279-4.649 106.214 26.424 26.142 64.089.988 146.596.051 228.883c-.77 67.653 6.004 245.841 106.83 247.11 74.917.948 86.072-95.279 120.737-141.623 24.662-32.972 56.417-42.285 95.507-51.929C390.309 265.865 436.097 213.011 436 143Z"
></path>
</svg>
);
}
@@ -0,0 +1,28 @@
import { ComponentProps } from 'react';
export function WargamingIcon(props: ComponentProps<'svg'>) {
return (
<svg
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g clipPath="url(#clip0_574_231)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M7.46409 0.156338C8.91652 0.149247 10.3384 0.57301 11.55 1.37404C12.7616 2.17507 13.7085 3.31739 14.2709 4.65654C14.8332 5.9957 14.9859 7.47154 14.7095 8.89745C14.4331 10.3234 13.7401 11.6353 12.7181 12.6673C11.6961 13.6994 10.391 14.4052 8.96789 14.6955C7.54475 14.9859 6.06748 14.8477 4.72288 14.2984C3.37829 13.7492 2.22676 12.8136 1.41391 11.6099C0.601062 10.4062 0.163403 8.98846 0.156278 7.53603V7.50009C0.150882 5.5586 0.916644 3.69442 2.28523 2.31733C3.65382 0.940243 5.51323 0.162958 7.45472 0.156338H7.46409ZM7.46409 1.56259C8.76962 1.56799 10.0372 2.00218 11.0719 2.79837C12.1065 3.59456 12.8509 4.70863 13.1906 5.96922C13.5302 7.2298 13.4463 8.56706 12.9517 9.77529C12.4571 10.9835 11.5792 11.9958 10.4532 12.6563C10.8305 11.3103 10.9857 9.91172 10.9125 8.51571C11.2938 8.62353 11.5094 8.68446 11.8922 8.8079C11.47 7.70829 10.9518 6.64795 10.3438 5.63915C9.79373 6.67527 9.10279 7.63018 8.29065 8.47665L9.51565 8.40009C8.46097 10.2938 6.97347 11.2126 5.08909 11.4798C4.6594 9.33759 4.98128 5.85478 7.38597 4.21728L7.62972 5.38603C8.09847 4.63134 9.02503 3.6329 9.71409 2.93759C8.57965 2.49502 7.34402 2.37866 6.1469 2.60165C6.34534 2.77196 6.59065 2.98759 6.78909 3.15634C4.07815 4.3079 2.58909 6.20009 1.6094 8.40009C1.48639 7.55586 1.54531 6.69509 1.78221 5.87549C2.0191 5.0559 2.4285 4.29643 2.98295 3.64802C3.5374 2.99961 4.22409 2.47724 4.99695 2.11595C5.76982 1.75465 6.611 1.56279 7.46409 1.55321V1.56259Z"
fill="currentColor"
/>
</g>
<defs>
<clipPath id="clip0_574_231">
<rect width="15" height="15" fill="currentColor" />
</clipPath>
</defs>
</svg>
);
}