mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +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",
|
"crc": "^4.3.2",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"lz4js": "^0.2.0",
|
"lz4js": "^0.2.0",
|
||||||
"ts-proto": "^2.2.2",
|
|
||||||
"yaml": "^2.5.0",
|
"yaml": "^2.5.0",
|
||||||
"ts-deepmerge": "^7.0.2",
|
"ts-deepmerge": "^7.0.2",
|
||||||
"@types/decompress": "^4.2.7",
|
"@types/decompress": "^4.2.7",
|
||||||
@@ -69,34 +68,25 @@
|
|||||||
"progress": "^2.0.3",
|
"progress": "^2.0.3",
|
||||||
"puppeteer": "^23.10.4",
|
"puppeteer": "^23.10.4",
|
||||||
"@astrojs/check": "^0.9.4",
|
"@astrojs/check": "^0.9.4",
|
||||||
"@astrojs/sitemap": "^3.2.1",
|
|
||||||
"@playform/compress": "^0.1.9",
|
"@playform/compress": "^0.1.9",
|
||||||
"@playform/inline": "^0.1.2",
|
"@playform/inline": "^0.1.2",
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/three": "^0.160.0",
|
|
||||||
"astro-compressor": "^1.0.0",
|
"astro-compressor": "^1.0.0",
|
||||||
"@astrojs/partytown": "^2.1.4",
|
|
||||||
"@fontsource/inter": "^5.2.5",
|
"@fontsource/inter": "^5.2.5",
|
||||||
"@nanostores/persistent": "^0.10.2",
|
"@nanostores/persistent": "^0.10.2",
|
||||||
"@nanostores/react": "^0.7.3",
|
"@nanostores/react": "^0.7.3",
|
||||||
"@nivo/bar": "^0.87.0",
|
"@nivo/bar": "^0.87.0",
|
||||||
"@nivo/line": "^0.88.0",
|
"@nivo/line": "^0.88.0",
|
||||||
"@react-three/drei": "^9.115.0",
|
|
||||||
"@react-three/fiber": "^8.17.10",
|
|
||||||
"compare-versions": "^6.1.1",
|
"compare-versions": "^6.1.1",
|
||||||
"echarts": "^5.5.1",
|
"echarts": "^5.5.1",
|
||||||
"immer": "^10.1.1",
|
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"markdown-to-jsx": "^7.5.0",
|
"markdown-to-jsx": "^7.5.0",
|
||||||
"nanostores": "^0.11.3",
|
"nanostores": "^0.11.3",
|
||||||
"react-device-detect": "^2.2.3",
|
"react-device-detect": "^2.2.3",
|
||||||
"react-promise-suspense": "^0.3.4",
|
"react-promise-suspense": "^0.3.4",
|
||||||
"three": "^0.169.0",
|
|
||||||
"urlon": "^3.1.0",
|
"urlon": "^3.1.0",
|
||||||
"zustand": "^4.5.5",
|
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"@types/node": "^22.14.1",
|
"@types/node": "^22.14.1",
|
||||||
"prettier": "^3.5.3",
|
|
||||||
"prisma": "^6.6.0",
|
"prisma": "^6.6.0",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"googleapis": "^144.0.0",
|
"googleapis": "^144.0.0",
|
||||||
|
|||||||
+4
-1
@@ -39,5 +39,8 @@
|
|||||||
"build:ids": "cd packages/scripts && bun build:ids",
|
"build:ids": "cd packages/scripts && bun build:ids",
|
||||||
"prunestrings": "cd packages/scripts && bun prunestrings"
|
"prunestrings": "cd packages/scripts && bun prunestrings"
|
||||||
},
|
},
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prettier": "^3.5.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,8 @@
|
|||||||
"name": "@blitzkit/core",
|
"name": "@blitzkit/core",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts"
|
"main": "src/index.ts",
|
||||||
|
"dependencies": {
|
||||||
|
"ts-proto": "^2.2.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1254,6 +1254,7 @@
|
|||||||
},
|
},
|
||||||
"gallery": {
|
"gallery": {
|
||||||
"name": "Gallery",
|
"name": "Gallery",
|
||||||
|
"unnamed_avatar": "Unnamed avatar",
|
||||||
"button": "Browse all",
|
"button": "Browse all",
|
||||||
"description": "Blitz player avatars",
|
"description": "Blitz player avatars",
|
||||||
"seo_description": "All World of Tanks 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';
|
import react from '@astrojs/react';
|
||||||
|
|
||||||
// https://astro.build/config
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
integrations: [react()],
|
integrations: [react()],
|
||||||
devToolbar: { enabled: false },
|
devToolbar: { enabled: false },
|
||||||
|
|||||||
@@ -8,22 +8,30 @@
|
|||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@astrojs/partytown": "^2.1.4",
|
||||||
"@astrojs/react": "^4.3.0",
|
"@astrojs/react": "^4.3.0",
|
||||||
|
"@astrojs/sitemap": "^3.2.1",
|
||||||
"@astrolib/seo": "^1.0.0-beta.8",
|
"@astrolib/seo": "^1.0.0-beta.8",
|
||||||
"@blitzkit/closed": "workspace:*",
|
"@blitzkit/closed": "workspace:*",
|
||||||
"@blitzkit/core": "workspace:*",
|
"@blitzkit/core": "workspace:*",
|
||||||
"@radix-ui/colors": "^3.0.0",
|
"@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",
|
"@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/js-yaml": "^4.0.9",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/react": "^19.1.5",
|
"@types/react": "^19.1.5",
|
||||||
"@types/react-dom": "^19.1.5",
|
"@types/react-dom": "^19.1.5",
|
||||||
|
"@types/three": "^0.160.0",
|
||||||
"astro": "^5.8.0",
|
"astro": "^5.8.0",
|
||||||
|
"immer": "^10.1.1",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"minimatch": "^10.0.1",
|
"minimatch": "^10.0.1",
|
||||||
"react": "^19.1.0",
|
"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 { ProfileAvatarComponent } from '@protos/blitz_static_profile_avatar_component';
|
||||||
import { StuffUIComponent } from '@protos/blitz_static_stuff_ui_component';
|
import { StuffUIComponent } from '@protos/blitz_static_stuff_ui_component';
|
||||||
import { BlitzkitAllAvatarsComponent } from '@protos/blitzkit_static_all_avatars_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 { 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 { metadata } from 'packages/website-ue/src/core/blitz/metadata';
|
||||||
import { Var } from 'packages/website-ue/src/core/radix/var';
|
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
|
const allAvatars = await metadata
|
||||||
.get('BlitzkitAllAvatarsEntity.blitzkit_all_avatars')
|
.get('BlitzkitAllAvatarsEntity.blitzkit_all_avatars')
|
||||||
@@ -17,40 +23,107 @@ const allAvatars = await metadata
|
|||||||
|
|
||||||
export function Page({ localeData }: LocaleAcceptorProps) {
|
export function Page({ localeData }: LocaleAcceptorProps) {
|
||||||
return (
|
return (
|
||||||
<Flex wrap="wrap" gapX="4" gapY="6" justify="center" p="9">
|
<LocaleProvider localeData={localeData}>
|
||||||
{allAvatars.map((avatar) => {
|
<Content />
|
||||||
const item = new CatalogItemAccessor(avatar);
|
</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 stuffComponent = item.get(StuffUIComponent, 'UIComponent');
|
||||||
const avatarComponent = item.get(
|
const avatarComponent = item.get(
|
||||||
ProfileAvatarComponent,
|
ProfileAvatarComponent,
|
||||||
'profileAvatarComponent',
|
'profileAvatarComponent',
|
||||||
);
|
);
|
||||||
|
const name =
|
||||||
|
gameStrings[stuffComponent.display_name] ??
|
||||||
|
strings.website.tools.gallery.unnamed_avatar;
|
||||||
|
|
||||||
return (
|
return { avatar, name, stuffComponent, avatarComponent };
|
||||||
<Flex
|
})
|
||||||
direction="column"
|
.sort((a, b) => a.stuffComponent.grade - b.stuffComponent.grade)
|
||||||
gap="2"
|
.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
key={avatar.catalog_id}
|
const groups: Record<string, typeof avatars> = {};
|
||||||
style={{
|
|
||||||
width: '8rem',
|
for (const avatar of avatars) {
|
||||||
}}
|
if (avatar.name in groups) {
|
||||||
>
|
groups[avatar.name].push(avatar);
|
||||||
<img
|
} else {
|
||||||
alt="apple sauce"
|
groups[avatar.name] = [avatar];
|
||||||
src={avatarComponent.avatar}
|
}
|
||||||
style={{
|
}
|
||||||
width: '100%',
|
|
||||||
aspectRatio: '1 / 1',
|
return Object.entries(groups);
|
||||||
objectFit: 'fill',
|
}, []);
|
||||||
borderRadius: Var('radius-1'),
|
|
||||||
boxShadow: Var('shadow-2'),
|
return (
|
||||||
}}
|
<PageWrapper>
|
||||||
/>
|
<Grid
|
||||||
<Text align="center">{stuffComponent.display_name}</Text>
|
columns="repeat(auto-fill, minmax(8rem, 1fr))"
|
||||||
</Flex>
|
flow="dense"
|
||||||
);
|
gapX="4"
|
||||||
})}
|
gapY="6"
|
||||||
</Flex>
|
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