feat: cached styling

This commit is contained in:
TrèsAbhi committed 2024-06-23 20:45:56 -05:00
1 parent 1d65dc755f
commit ff4be57faf
5 files changed
+97 -89

No files matched your search

BIN
View File
Binary file not shown.
+1
View File
@@ -40,6 +40,7 @@
"@resvg/resvg-js": "^2.4.1", "@resvg/resvg-js": "^2.4.1",
"@types/three": "^0.160.0", "@types/three": "^0.160.0",
"@vanilla-extract/css": "^1.13.0", "@vanilla-extract/css": "^1.13.0",
"@vanilla-extract/dynamic": "^2.1.1",
"adm-zip": "^0.5.12", "adm-zip": "^0.5.12",
"bepaint": "^0.1.0-beta.3", "bepaint": "^0.1.0-beta.3",
"csv-parse": "^5.5.6", "csv-parse": "^5.5.6",
@@ -0,0 +1,31 @@
import { createVar, style } from '@vanilla-extract/css';
export const cardBackgroundVar = createVar();
export const card = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 'var(--space-2)',
background: cardBackgroundVar,
});
export const image = style({
height: 64,
width: '100%',
objectPosition: 'center right',
objectFit: 'contain',
});
export const classIcon = style({
width: '1em',
height: '1em',
minWidth: '1em',
minHeight: '1em',
});
export const name = style({
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
});
@@ -1,49 +1,50 @@
import { Flex, Link, Text } from '@radix-ui/themes'; import { Flex, Text } from '@radix-ui/themes';
import { use, useEffect, useMemo, useRef } from 'react'; import { Icon } from '@radix-ui/themes/dist/cjs/components/callout';
import { classIcons } from '../../../../components/ClassIcon'; import { assignInlineVars } from '@vanilla-extract/dynamic';
import { useEffect, useRef } from 'react';
import { Link } from '../../../../components/Link';
import { asset } from '../../../../core/blitzkit/asset'; import { asset } from '../../../../core/blitzkit/asset';
import { modelDefinitions } from '../../../../core/blitzkit/modelDefinitions';
import { resolveDpm } from '../../../../core/blitzkit/resolveDpm';
import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions'; import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions';
import { tankIcon } from '../../../../core/blitzkit/tankIcon'; import { tankIcon } from '../../../../core/blitzkit/tankIcon';
import { tankopediaFilterTank } from '../../../../core/blitzkit/tankopediaFilterTank'; import { tankopediaFilterTank } from '../../../../core/blitzkit/tankopediaFilterTank';
import { useTankopediaFilters } from '../../../../stores/tankopediaFilters'; import { useTankopediaFilters } from '../../../../stores/tankopediaFilters';
import * as styles from './TankCard.css';
interface TankCardProps { interface TankCardProps {
tank: TankDefinition; tank: TankDefinition;
} }
export function TankCard({ tank }: TankCardProps) { export function TankCard({ tank }: TankCardProps) {
const awaitedModelDefinitions = use(modelDefinitions); // const awaitedModelDefinitions = use(modelDefinitions);
const Icon = classIcons[tank.class]; // const Icon = classIcons[tank.class];
const link = useRef<HTMLAnchorElement>(null); const link = useRef<HTMLAnchorElement>(null);
const sortBy = useTankopediaFilters((state) => state.sort.by); // const sortBy = useTankopediaFilters((state) => state.sort.by);
const discriminator = useMemo(() => { // const discriminator = useMemo(() => {
if (sortBy.startsWith('meta')) return undefined; // if (sortBy.startsWith('meta')) return undefined;
const turret = tank.turrets.at(-1)!; // const turret = tank.turrets.at(-1)!;
const gun = turret.guns.at(-1)!; // const gun = turret.guns.at(-1)!;
const shell = gun.shells[0]; // const shell = gun.shells[0];
const tracks = tank.tracks.at(-1)!; // const tracks = tank.tracks.at(-1)!;
const tankModelDefinition = awaitedModelDefinitions[tank.id]; // const tankModelDefinition = awaitedModelDefinitions[tank.id];
switch (sortBy) { // switch (sortBy) {
case 'fire.aimTime': // case 'fire.aimTime':
return `${gun.aimTime.toFixed(2)}s`; // return `${gun.aimTime.toFixed(2)}s`;
case 'fire.caliber': // case 'fire.caliber':
return `${shell.caliber.toFixed(0)}mm`; // return `${shell.caliber.toFixed(0)}mm`;
case 'fire.damage': // case 'fire.damage':
return `${shell.damage.armor.toFixed(0)}hp`; // return `${shell.damage.armor.toFixed(0)}hp`;
case 'fire.dispersionMoving': // case 'fire.dispersionMoving':
return `+ ${tracks.dispersion.move.toFixed(3)}`; // return `+ ${tracks.dispersion.move.toFixed(3)}`;
case 'fire.dispersionStill': // case 'fire.dispersionStill':
return gun.dispersion.base.toFixed(3); // return gun.dispersion.base.toFixed(3);
case 'fire.dpm': // case 'fire.dpm':
return resolveDpm(gun, shell).toFixed(0); // return resolveDpm(gun, shell).toFixed(0);
case 'fire.gunDepression': // case 'fire.gunDepression':
return awaitedModelDefinitions; // return awaitedModelDefinitions;
} // }
}, [sortBy]); // }, [sortBy]);
useEffect(() => { useEffect(() => {
const unsubscribe = useTankopediaFilters.subscribe((filters) => { const unsubscribe = useTankopediaFilters.subscribe((filters) => {
@@ -70,27 +71,12 @@ export function TankCard({ tank }: TankCardProps) {
highContrast={tank.treeType === 'researchable'} highContrast={tank.treeType === 'researchable'}
underline="hover" underline="hover"
href={`/tools/tankopedia/${tank.id}`} href={`/tools/tankopedia/${tank.id}`}
style={{ className={styles.card}
display: 'flex', style={assignInlineVars({
flexDirection: 'column', [styles.cardBackgroundVar]: `top left / contain no-repeat url(${asset(`flags/scratched/${tank.nation}.webp`)})`,
alignItems: 'center', })}
gap: 'var(--space-2)',
background: `url(${asset(`flags/scratched/${tank.nation}.webp`)})`,
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'top left',
}}
> >
<img <img alt={tank.name} src={tankIcon(tank.id)} className={styles.image} />
alt={tank.name}
src={tankIcon(tank.id)}
height={64}
style={{
width: '100%',
objectPosition: 'center right',
objectFit: 'contain',
}}
/>
<Flex <Flex
justify="center" justify="center"
@@ -100,27 +86,13 @@ export function TankCard({ tank }: TankCardProps) {
width="100%" width="100%"
maxWidth="100%" maxWidth="100%"
> >
<Icon <Icon className={styles.classIcon} />
style={{ <Text align="center" className={styles.name}>
width: '1em',
height: '1em',
minWidth: '1em',
minHeight: '1em',
}}
/>
<Text
align="center"
style={{
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
}}
>
{tank.name} {tank.name}
</Text> </Text>
</Flex> </Flex>
{discriminator && ( {/* {discriminator && (
<Text <Text
mt="-2" mt="-2"
color="gray" color="gray"
@@ -133,7 +105,7 @@ export function TankCard({ tank }: TankCardProps) {
> >
{discriminator} {discriminator}
</Text> </Text>
)} )} */}
</Link> </Link>
); );
} }
+23 -19
View File
@@ -2,25 +2,29 @@
import { LinkProps, Link as RadixLink } from '@radix-ui/themes'; import { LinkProps, Link as RadixLink } from '@radix-ui/themes';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { forwardRef } from 'react';
export function Link({ href, onClick, ...props }: LinkProps) { export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
const router = useRouter(); ({ href, onClick, ...props }, ref) => {
const router = useRouter();
return ( return (
<RadixLink <RadixLink
href={href} ref={ref}
onClick={(event) => { href={href}
event.preventDefault(); onClick={(event) => {
if (href) { event.preventDefault();
if (event.ctrlKey || event.metaKey) { if (href) {
window.open(href); if (event.ctrlKey || event.metaKey) {
} else { window.open(href);
router.push(href); } else {
router.push(href);
}
} }
} onClick?.(event);
onClick?.(event); }}
}} {...props}
{...props} />
/> );
); },
} );