Files
blitzkit/packages/website/src/components/Gallery/List.tsx
T

79 lines
2.1 KiB
TypeScript
Raw Normal View History

2025-04-19 00:47:28 -05:00
import locales from '@blitzkit/i18n/locales.json';
2025-01-15 20:14:05 -06:00
import { literals } from '@blitzkit/i18n/src/literals';
2024-10-24 17:50:18 -05:00
import { Flex, Text } from '@radix-ui/themes';
2024-10-24 17:32:46 -05:00
import fuzzysort from 'fuzzysort';
2024-10-24 17:46:02 -05:00
import { times } from 'lodash-es';
import { useMemo, useState } from 'react';
2025-04-19 00:47:28 -05:00
import { awaitableGallery } from '../../core/awaitables/gallery';
2025-01-07 12:47:55 -06:00
import { useLocale } from '../../hooks/useLocale';
2024-10-24 17:32:46 -05:00
import { GalleryEphemeral } from '../../stores/galleryEphemeral';
2024-10-24 17:46:02 -05:00
import { GalleryCard } from './Card';
2024-10-24 17:32:46 -05:00
interface GalleryListProps {
avatars: Avatar[];
}
export interface Avatar {
name: string;
id: string;
}
2025-04-19 00:47:28 -05:00
const gallery = await awaitableGallery;
2024-10-24 17:50:18 -05:00
const DEFAULT_LOADED = 42;
2024-11-24 20:39:21 -06:00
const PREVIEW_COUNT = 28;
2024-10-24 17:46:02 -05:00
2025-04-19 00:47:28 -05:00
export function GalleryList() {
2024-10-24 17:32:46 -05:00
const search = GalleryEphemeral.use((state) => state.search);
2024-10-24 17:46:02 -05:00
const [loadedCards, setLoadedCards] = useState(DEFAULT_LOADED);
2025-04-19 00:47:28 -05:00
const { locale, strings, unwrap } = useLocale();
2024-10-24 17:32:46 -05:00
const filtered = useMemo(() => {
2024-10-24 17:46:02 -05:00
setLoadedCards(DEFAULT_LOADED);
2024-10-24 17:32:46 -05:00
if (search === undefined) {
2025-04-19 00:47:28 -05:00
return gallery.avatars;
2024-10-24 17:32:46 -05:00
} else {
return fuzzysort
2025-04-19 00:47:28 -05:00
.go(search, gallery.avatars, {
keys: [
...locales.supported.map(
(supported) => `name.locales.${supported.locale}`,
),
'id',
],
})
2024-10-24 17:32:46 -05:00
.map((result) => result.obj);
}
}, [search]);
return (
2024-10-24 17:50:18 -05:00
<>
<Text align="center" color="gray">
2025-01-07 13:00:43 -06:00
{literals(strings.website.tools.gallery.search.results, [
filtered.length.toLocaleString(locale),
])}
2024-10-24 17:50:18 -05:00
</Text>
2024-10-24 17:46:02 -05:00
2024-10-24 17:52:23 -05:00
<Flex wrap="wrap" gap="4" justify="center">
2024-10-24 17:50:18 -05:00
{filtered.slice(0, loadedCards).map((avatar) => (
2025-04-19 00:47:28 -05:00
<GalleryCard
key={avatar.id}
id={avatar.id}
name={unwrap(avatar.name)}
/>
2024-10-24 17:50:18 -05:00
))}
{times(
Math.min(PREVIEW_COUNT, filtered.length - loadedCards),
(index) => (
<GalleryCard
key={index}
skeleton
onIntersection={() => setLoadedCards((state) => state + 2)}
/>
),
)}
</Flex>
</>
2024-10-24 17:32:46 -05:00
);
}