mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +02:00
feat: code split
This commit is contained in:
1 parent
2c2c3687c7
commit
3aafe4d9f1
6 files changed
+179
-83
No files matched your search
File renamed without changes.
@@ -0,0 +1,78 @@
|
|||||||
|
import type { ProfileAvatarComponent } from '@protos/blitz_static_profile_avatar_component';
|
||||||
|
import type { SellableComponent } from '@protos/blitz_static_sellable_component';
|
||||||
|
import type { StuffUIComponent } from '@protos/blitz_static_stuff_ui_component';
|
||||||
|
import { Badge, Box, Flex, Text } from '@radix-ui/themes';
|
||||||
|
import { literals } from 'packages/i18n/src';
|
||||||
|
import { Var } from '../../core/radix/var';
|
||||||
|
import { useLocale } from '../../hooks/useLocale';
|
||||||
|
|
||||||
|
interface AvatarGroupProps {
|
||||||
|
name: string;
|
||||||
|
avatars: {
|
||||||
|
stuff: StuffUIComponent;
|
||||||
|
avatar: ProfileAvatarComponent;
|
||||||
|
sellable: SellableComponent;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const dx = '4px';
|
||||||
|
const MAX_AVATARS_PREVIEW = 5;
|
||||||
|
|
||||||
|
export function AvatarGroup({ avatars, name }: AvatarGroupProps) {
|
||||||
|
const { strings } = useLocale();
|
||||||
|
const avatarsReduced = [...avatars].reverse().slice(0, MAX_AVATARS_PREVIEW);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex direction="column" gap="3">
|
||||||
|
<Box width="100%" style={{ aspectRatio: '7 / 8' }} 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.avatar.avatar})`,
|
||||||
|
backgroundSize: 'cover',
|
||||||
|
backgroundPosition: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{avatars.length > 1 && (
|
||||||
|
<Box
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
style={{
|
||||||
|
background: `linear-gradient(-45deg, ${Var('black-a9')} 25%, ${Var('black-a1')} 50%)`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{avatars.length > 1 && (
|
||||||
|
<Box position="absolute" bottom="1" right="1">
|
||||||
|
<Badge variant="solid" color="gray" highContrast size="2">
|
||||||
|
{literals(strings.common.units.times, [`${avatars.length}`])}
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
size="2"
|
||||||
|
wrap="nowrap"
|
||||||
|
align="center"
|
||||||
|
style={{
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
import { AstroSeo } from '@astrolib/seo';
|
||||||
|
import { type Tool } from '../constants/tools';
|
||||||
|
import { getStrings } from '../core/i18n/getStrings';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
tool: Tool;
|
||||||
|
locale: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { tool, locale } = Astro.props;
|
||||||
|
const strings = await getStrings(locale);
|
||||||
|
const toolStrings =
|
||||||
|
strings.website.tools[
|
||||||
|
(tool.strings ?? tool.id) as keyof typeof strings.website.tools
|
||||||
|
];
|
||||||
|
---
|
||||||
|
|
||||||
|
<AstroSeo
|
||||||
|
title={toolStrings.name}
|
||||||
|
description={toolStrings.seo_description}
|
||||||
|
canonical={Astro.url.href}
|
||||||
|
openGraph={{
|
||||||
|
url: Astro.url.href,
|
||||||
|
images: [
|
||||||
|
{ url: `${Astro.url.origin}/assets/images/tools/${tool.id}.webp` },
|
||||||
|
],
|
||||||
|
title: toolStrings.name,
|
||||||
|
description: toolStrings.seo_description,
|
||||||
|
site_name: 'BlitzKit',
|
||||||
|
}}
|
||||||
|
twitter={{ cardType: 'summary_large_image' }}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
import { Box, Flex, Heading, Text } from '@radix-ui/themes';
|
||||||
|
import ToolOpenGraph from '../components/ToolOpenGraph.astro';
|
||||||
|
import { type Tool } from '../constants/tools';
|
||||||
|
import { getStrings } from '../core/i18n/getStrings';
|
||||||
|
import BaseLayout from './BaseLayout.astro';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
tool: Tool;
|
||||||
|
locale: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { tool, locale } = Astro.props;
|
||||||
|
const strings = await getStrings(locale);
|
||||||
|
const toolStrings =
|
||||||
|
strings.website.tools[
|
||||||
|
(tool.strings ?? tool.id) as keyof typeof strings.website.tools
|
||||||
|
];
|
||||||
|
---
|
||||||
|
|
||||||
|
<ToolOpenGraph {locale} tool={tool} />
|
||||||
|
|
||||||
|
<BaseLayout {locale}>
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url(/assets/tool-backgrounds/${tool.id}.webp)`,
|
||||||
|
backgroundSize: 'cover',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
direction="column"
|
||||||
|
align="center"
|
||||||
|
py="6"
|
||||||
|
style={{
|
||||||
|
backdropFilter: 'blur(4rem)',
|
||||||
|
WebkitBackdropFilter: 'blur(4rem)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Heading size="7">{toolStrings.name}</Heading>
|
||||||
|
<Text>{toolStrings.description}</Text>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
</BaseLayout>
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import { ProfileAvatarComponent } from '@protos/blitz_static_profile_avatar_component';
|
import { ProfileAvatarComponent } from '@protos/blitz_static_profile_avatar_component';
|
||||||
|
import { SellableComponent } from '@protos/blitz_static_sellable_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 { Badge, Box, Flex, Grid, Text } from '@radix-ui/themes';
|
import { Grid } from '@radix-ui/themes';
|
||||||
import { CatalogItemAccessor } from 'packages/core/src/blitz/catalogItemAccessor';
|
import { CatalogItemAccessor } from 'packages/core/src/blitz/catalogItemAccessor';
|
||||||
import { literals } from 'packages/i18n/src';
|
import { AvatarGroup } from 'packages/website-ue/src/components/Avatars/Group';
|
||||||
import { PageWrapper } from 'packages/website-ue/src/components/PageWrapper';
|
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 {
|
import {
|
||||||
LocaleProvider,
|
LocaleProvider,
|
||||||
useLocale,
|
useLocale,
|
||||||
@@ -30,27 +30,25 @@ export function Page({ localeData }: LocaleAcceptorProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dx = '4px';
|
|
||||||
const MAX_AVATARS_PREVIEW = 5;
|
|
||||||
|
|
||||||
function Content() {
|
function Content() {
|
||||||
const { gameStrings, strings } = useLocale();
|
const { gameStrings, strings } = useLocale();
|
||||||
const groups = useMemo(() => {
|
const groups = useMemo(() => {
|
||||||
const avatars = allAvatars
|
const avatars = allAvatars
|
||||||
.map((avatar) => {
|
.map((id) => {
|
||||||
const item = new CatalogItemAccessor(avatar);
|
const item = new CatalogItemAccessor(id);
|
||||||
const stuffComponent = item.get(StuffUIComponent, 'UIComponent');
|
const stuff = item.get(StuffUIComponent, 'UIComponent');
|
||||||
const avatarComponent = item.get(
|
const avatar = item.get(
|
||||||
ProfileAvatarComponent,
|
ProfileAvatarComponent,
|
||||||
'profileAvatarComponent',
|
'profileAvatarComponent',
|
||||||
);
|
);
|
||||||
|
const sellable = item.get(SellableComponent, 'sellableComponent');
|
||||||
const name =
|
const name =
|
||||||
gameStrings[stuffComponent.display_name] ??
|
gameStrings[stuff.display_name] ??
|
||||||
strings.website.tools.avatars.unnamed_avatar;
|
strings.website.tools.avatars.unnamed_avatar; // maybe move to dumb component?
|
||||||
|
|
||||||
return { avatar, name, stuffComponent, avatarComponent };
|
return { avatar, name, stuff, sellable };
|
||||||
})
|
})
|
||||||
.sort((a, b) => a.stuffComponent.grade - b.stuffComponent.grade)
|
.sort((a, b) => a.stuff.grade - b.stuff.grade)
|
||||||
.sort((a, b) => a.name.localeCompare(b.name));
|
.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
const groups: Record<string, typeof avatars> = {};
|
const groups: Record<string, typeof avatars> = {};
|
||||||
|
|
||||||
@@ -68,77 +66,18 @@ function Content() {
|
|||||||
return (
|
return (
|
||||||
<PageWrapper>
|
<PageWrapper>
|
||||||
<Grid
|
<Grid
|
||||||
columns="repeat(auto-fill, minmax(8rem, 1fr))"
|
columns={{
|
||||||
|
initial: 'repeat(auto-fill, minmax(6rem, 1fr))',
|
||||||
|
xs: 'repeat(auto-fill, minmax(8rem, 1fr))',
|
||||||
|
}}
|
||||||
flow="dense"
|
flow="dense"
|
||||||
gapX="4"
|
gapX="4"
|
||||||
gapY="6"
|
gapY="6"
|
||||||
flexGrow="1"
|
flexGrow="1"
|
||||||
>
|
>
|
||||||
{groups.map(([name, avatars]) => {
|
{groups.map(([name, avatars]) => (
|
||||||
const avatarsReduced = [...avatars]
|
<AvatarGroup key={name} name={name} avatars={avatars} />
|
||||||
.reverse()
|
))}
|
||||||
.slice(0, MAX_AVATARS_PREVIEW);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Flex direction="column" gap="3" key={name}>
|
|
||||||
<Box
|
|
||||||
width="100%"
|
|
||||||
style={{ aspectRatio: '7 / 8' }}
|
|
||||||
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
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
style={{
|
|
||||||
background: `linear-gradient(-45deg, ${Var('black-a9')} 25%, ${Var('black-a1')} 50%)`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{avatars.length > 1 && (
|
|
||||||
<Box position="absolute" bottom="1" right="1">
|
|
||||||
<Badge variant="solid" color="gray" highContrast size="3">
|
|
||||||
{literals(strings.common.units.times, [
|
|
||||||
`${avatars.length}`,
|
|
||||||
])}
|
|
||||||
</Badge>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Text
|
|
||||||
size="2"
|
|
||||||
wrap="nowrap"
|
|
||||||
align="center"
|
|
||||||
style={{
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{name}
|
|
||||||
</Text>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
|
import { avatarsTool } from 'packages/website-ue/src/constants/tools';
|
||||||
import { metadata } from 'packages/website-ue/src/core/blitz/metadata';
|
import { metadata } from 'packages/website-ue/src/core/blitz/metadata';
|
||||||
import BaseLayout from 'packages/website-ue/src/layouts/BaseLayout.astro';
|
import ToolLayout from 'packages/website-ue/src/layouts/ToolLayout.astro';
|
||||||
import { Page } from './_index';
|
import { Page } from './_index';
|
||||||
|
|
||||||
export { getStaticPaths } from '../index.astro';
|
export { getStaticPaths } from '../index.astro';
|
||||||
@@ -12,6 +13,6 @@ const gameStrings = await metadata.stringsPartial(locale, [
|
|||||||
]);
|
]);
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout {locale}>
|
<ToolLayout tool={avatarsTool} {locale}>
|
||||||
<Page localeData={{ locale, gameStrings }} client:load />
|
<Page localeData={{ locale, gameStrings }} client:load />
|
||||||
</BaseLayout>
|
</ToolLayout>
|
||||||
Reference in new issue
Block a user