mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
feat: stacking
This commit is contained in:
1 parent
1eca71d28c
commit
9375f134db
8 files changed
+122
-45
No files matched your search
@@ -54,7 +54,6 @@
|
||||
"crc": "^4.3.2",
|
||||
"dotenv": "^16.4.5",
|
||||
"lz4js": "^0.2.0",
|
||||
"ts-proto": "^2.2.2",
|
||||
"yaml": "^2.5.0",
|
||||
"ts-deepmerge": "^7.0.2",
|
||||
"@types/decompress": "^4.2.7",
|
||||
@@ -69,34 +68,25 @@
|
||||
"progress": "^2.0.3",
|
||||
"puppeteer": "^23.10.4",
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@astrojs/sitemap": "^3.2.1",
|
||||
"@playform/compress": "^0.1.9",
|
||||
"@playform/inline": "^0.1.2",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/three": "^0.160.0",
|
||||
"astro-compressor": "^1.0.0",
|
||||
"@astrojs/partytown": "^2.1.4",
|
||||
"@fontsource/inter": "^5.2.5",
|
||||
"@nanostores/persistent": "^0.10.2",
|
||||
"@nanostores/react": "^0.7.3",
|
||||
"@nivo/bar": "^0.87.0",
|
||||
"@nivo/line": "^0.88.0",
|
||||
"@react-three/drei": "^9.115.0",
|
||||
"@react-three/fiber": "^8.17.10",
|
||||
"compare-versions": "^6.1.1",
|
||||
"echarts": "^5.5.1",
|
||||
"immer": "^10.1.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"markdown-to-jsx": "^7.5.0",
|
||||
"nanostores": "^0.11.3",
|
||||
"react-device-detect": "^2.2.3",
|
||||
"react-promise-suspense": "^0.3.4",
|
||||
"three": "^0.169.0",
|
||||
"urlon": "^3.1.0",
|
||||
"zustand": "^4.5.5",
|
||||
"@types/bun": "latest",
|
||||
"@types/node": "^22.14.1",
|
||||
"prettier": "^3.5.3",
|
||||
"prisma": "^6.6.0",
|
||||
"typescript": "^5.8.3",
|
||||
"googleapis": "^144.0.0",
|
||||
|
||||
+4
-1
@@ -39,5 +39,8 @@
|
||||
"build:ids": "cd packages/scripts && bun build:ids",
|
||||
"prunestrings": "cd packages/scripts && bun prunestrings"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prettier": "^3.5.3"
|
||||
}
|
||||
}
|
||||
@@ -2,5 +2,8 @@
|
||||
"name": "@blitzkit/core",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "src/index.ts"
|
||||
"main": "src/index.ts",
|
||||
"dependencies": {
|
||||
"ts-proto": "^2.2.2"
|
||||
}
|
||||
}
|
||||
@@ -1254,6 +1254,7 @@
|
||||
},
|
||||
"gallery": {
|
||||
"name": "Gallery",
|
||||
"unnamed_avatar": "Unnamed avatar",
|
||||
"button": "Browse all",
|
||||
"description": "Blitz player avatars",
|
||||
"seo_description": "All World of Tanks Blitz player avatars",
|
||||
|
||||
@@ -3,7 +3,6 @@ import { defineConfig } from 'astro/config';
|
||||
|
||||
import react from '@astrojs/react';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [react()],
|
||||
devToolbar: { enabled: false },
|
||||
|
||||
@@ -8,22 +8,30 @@
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/partytown": "^2.1.4",
|
||||
"@astrojs/react": "^4.3.0",
|
||||
"@astrojs/sitemap": "^3.2.1",
|
||||
"@astrolib/seo": "^1.0.0-beta.8",
|
||||
"@blitzkit/closed": "workspace:*",
|
||||
"@blitzkit/core": "workspace:*",
|
||||
"@radix-ui/colors": "^3.0.0",
|
||||
"@radix-ui/react-icons": "^1.3.0",
|
||||
"@radix-ui/react-icons": "^1.3.2",
|
||||
"@radix-ui/themes": "^3.1.4",
|
||||
"@react-three/drei": "^9.115.0",
|
||||
"@react-three/fiber": "^8.17.10",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/react": "^19.1.5",
|
||||
"@types/react-dom": "^19.1.5",
|
||||
"@types/three": "^0.160.0",
|
||||
"astro": "^5.8.0",
|
||||
"immer": "^10.1.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"minimatch": "^10.0.1",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0"
|
||||
"react-dom": "^19.1.0",
|
||||
"three": "^0.169.0",
|
||||
"zustand": "^4.5.5"
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,17 @@
|
||||
import { ProfileAvatarComponent } from '@protos/blitz_static_profile_avatar_component';
|
||||
import { StuffUIComponent } from '@protos/blitz_static_stuff_ui_component';
|
||||
import { BlitzkitAllAvatarsComponent } from '@protos/blitzkit_static_all_avatars_component';
|
||||
import { Flex, Text } from '@radix-ui/themes';
|
||||
import { Badge, Box, Flex, Grid, Text } from '@radix-ui/themes';
|
||||
import { CatalogItemAccessor } from 'packages/core/src/blitz/catalogItemAccessor';
|
||||
import { PageWrapper } from 'packages/website-ue/src/components/PageWrapper';
|
||||
import { metadata } from 'packages/website-ue/src/core/blitz/metadata';
|
||||
import { Var } from 'packages/website-ue/src/core/radix/var';
|
||||
import type { LocaleAcceptorProps } from 'packages/website-ue/src/hooks/useLocale';
|
||||
import {
|
||||
LocaleProvider,
|
||||
useLocale,
|
||||
type LocaleAcceptorProps,
|
||||
} from 'packages/website-ue/src/hooks/useLocale';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
const allAvatars = await metadata
|
||||
.get('BlitzkitAllAvatarsEntity.blitzkit_all_avatars')
|
||||
@@ -17,40 +23,107 @@ const allAvatars = await metadata
|
||||
|
||||
export function Page({ localeData }: LocaleAcceptorProps) {
|
||||
return (
|
||||
<Flex wrap="wrap" gapX="4" gapY="6" justify="center" p="9">
|
||||
{allAvatars.map((avatar) => {
|
||||
const item = new CatalogItemAccessor(avatar);
|
||||
<LocaleProvider localeData={localeData}>
|
||||
<Content />
|
||||
</LocaleProvider>
|
||||
);
|
||||
}
|
||||
|
||||
const dx = '4px';
|
||||
const MAX_AVATARS_PREVIEW = 5;
|
||||
|
||||
function Content() {
|
||||
const { gameStrings, strings } = useLocale();
|
||||
const groups = useMemo(() => {
|
||||
const avatars = allAvatars
|
||||
.map((avatar) => {
|
||||
const item = new CatalogItemAccessor(avatar);
|
||||
const stuffComponent = item.get(StuffUIComponent, 'UIComponent');
|
||||
const avatarComponent = item.get(
|
||||
ProfileAvatarComponent,
|
||||
'profileAvatarComponent',
|
||||
);
|
||||
const name =
|
||||
gameStrings[stuffComponent.display_name] ??
|
||||
strings.website.tools.gallery.unnamed_avatar;
|
||||
|
||||
return (
|
||||
<Flex
|
||||
direction="column"
|
||||
gap="2"
|
||||
key={avatar.catalog_id}
|
||||
style={{
|
||||
width: '8rem',
|
||||
}}
|
||||
>
|
||||
<img
|
||||
alt="apple sauce"
|
||||
src={avatarComponent.avatar}
|
||||
style={{
|
||||
width: '100%',
|
||||
aspectRatio: '1 / 1',
|
||||
objectFit: 'fill',
|
||||
borderRadius: Var('radius-1'),
|
||||
boxShadow: Var('shadow-2'),
|
||||
}}
|
||||
/>
|
||||
<Text align="center">{stuffComponent.display_name}</Text>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
return { avatar, name, stuffComponent, avatarComponent };
|
||||
})
|
||||
.sort((a, b) => a.stuffComponent.grade - b.stuffComponent.grade)
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
const groups: Record<string, typeof avatars> = {};
|
||||
|
||||
for (const avatar of avatars) {
|
||||
if (avatar.name in groups) {
|
||||
groups[avatar.name].push(avatar);
|
||||
} else {
|
||||
groups[avatar.name] = [avatar];
|
||||
}
|
||||
}
|
||||
|
||||
return Object.entries(groups);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<PageWrapper>
|
||||
<Grid
|
||||
columns="repeat(auto-fill, minmax(8rem, 1fr))"
|
||||
flow="dense"
|
||||
gapX="4"
|
||||
gapY="6"
|
||||
flexGrow="1"
|
||||
>
|
||||
{groups.map(([name, avatars]) => {
|
||||
const avatarsReduced = [...avatars]
|
||||
.reverse()
|
||||
.slice(0, MAX_AVATARS_PREVIEW);
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="3" key={name}>
|
||||
<Box
|
||||
width="100%"
|
||||
style={{ aspectRatio: '1 / 1' }}
|
||||
position="relative"
|
||||
>
|
||||
{avatarsReduced.map((avatar, index) => (
|
||||
<Box
|
||||
position="absolute"
|
||||
top={`calc(${dx} * ${index})`}
|
||||
left={`calc(${dx} * ${index})`}
|
||||
width={`calc(100% - ${dx} * ${avatarsReduced.length - 1})`}
|
||||
height={`calc(100% - ${dx} * ${avatarsReduced.length - 1})`}
|
||||
style={{
|
||||
filter: `brightness(${(index + 1) / avatarsReduced.length})`,
|
||||
borderRadius: Var('radius-2'),
|
||||
boxShadow: Var('shadow-3'),
|
||||
backgroundImage: `url(${avatar.avatarComponent.avatar})`,
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center',
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{avatars.length > 1 && (
|
||||
<Box
|
||||
position="absolute"
|
||||
bottom="0"
|
||||
left="50%"
|
||||
style={{
|
||||
transform: 'translate(-50%, 25%)',
|
||||
}}
|
||||
>
|
||||
<Badge variant="solid" color="gray" highContrast size="3">
|
||||
x{avatars.length}
|
||||
</Badge>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Text size="2">{name}</Text>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user