101 lines
4.1 KiB
TypeScript
101 lines
4.1 KiB
TypeScript
import { Heart, Loader2, Sparkles } from "lucide-react";
|
|
import type { Ref } from "react";
|
|
import type { FeaturedImage } from "./types";
|
|
import { MASONRY_HEIGHTS } from "./utils";
|
|
|
|
type LovartFeaturedGalleryProps = {
|
|
activeCategory: string;
|
|
categories: string[];
|
|
featuredItems: FeaturedImage[];
|
|
featuredLoadMoreRef: Ref<HTMLDivElement>;
|
|
featuredSectionRef: Ref<HTMLElement>;
|
|
isLoadingFeatured: boolean;
|
|
isLoadingMoreFeatured: boolean;
|
|
setActiveCategory: (category: string) => void;
|
|
};
|
|
|
|
export function LovartFeaturedGallery({
|
|
activeCategory,
|
|
categories,
|
|
featuredItems,
|
|
featuredLoadMoreRef,
|
|
featuredSectionRef,
|
|
isLoadingFeatured,
|
|
isLoadingMoreFeatured,
|
|
setActiveCategory,
|
|
}: LovartFeaturedGalleryProps) {
|
|
return (
|
|
<section ref={featuredSectionRef} className="mt-16">
|
|
<h2 className="text-[18px] font-semibold tracking-tight">灵感发现</h2>
|
|
|
|
<div className="mt-3 flex flex-wrap gap-1.5">
|
|
{categories.map((category) => (
|
|
<button
|
|
key={category}
|
|
type="button"
|
|
onClick={() => setActiveCategory(category)}
|
|
className={`rounded-xl px-3 py-1.5 text-[12px] ${
|
|
activeCategory === category
|
|
? "bg-[#ececec] text-black dark:bg-[#24242a] dark:text-white"
|
|
: "text-black/55 hover:bg-white dark:text-white/55 dark:hover:bg-[#17171b]"
|
|
}`}
|
|
>
|
|
{category}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{featuredItems.length === 0 ? (
|
|
<div className="mt-5 rounded-xl border border-dashed border-black/15 bg-white p-10 text-center text-black/35 dark:border-white/12 dark:bg-[#141416] dark:text-white/35">
|
|
{isLoadingFeatured ? "灵感内容加载中..." : "当前没有可展示的灵感数据。"}
|
|
</div>
|
|
) : (
|
|
<div className="mt-5 columns-1 gap-4 md:columns-2 xl:columns-4">
|
|
{featuredItems.map((item, index) => (
|
|
<button
|
|
key={item.id}
|
|
type="button"
|
|
onClick={() => window.open(item.originalUrl || item.thumbnailUrl, "_blank")}
|
|
className="group mb-4 block w-full cursor-pointer break-inside-avoid rounded-2xl border border-black/8 bg-white text-left shadow-sm transition hover:-translate-y-0.5 dark:border-white/10 dark:bg-[#141416]"
|
|
>
|
|
<div
|
|
className="overflow-hidden rounded-t-2xl bg-[#e8e8e8] dark:bg-[#1b1c20]"
|
|
style={{ height: `${MASONRY_HEIGHTS[index % MASONRY_HEIGHTS.length]}px` }}
|
|
>
|
|
<img
|
|
src={item.thumbnailUrl || item.originalUrl}
|
|
alt={item.prompt || "灵感图"}
|
|
className="h-full w-full object-cover transition-transform duration-300 ease-out will-change-transform group-hover:scale-[1.04]"
|
|
/>
|
|
</div>
|
|
<div className="flex items-center justify-between px-3 py-2 text-[12px] text-black/60 dark:text-white/55">
|
|
<div className="line-clamp-1 font-medium text-black/85 dark:text-white/85">
|
|
{item.user?.name || "创作者"}
|
|
</div>
|
|
<div className="inline-flex items-center gap-2 text-[11px]">
|
|
<span className="inline-flex items-center gap-1">
|
|
<Sparkles className="h-2.5 w-2.5" />
|
|
{(1200 + index * 37).toLocaleString()}
|
|
</span>
|
|
<span className="inline-flex items-center gap-1">
|
|
<Heart className="h-2.5 w-2.5" />
|
|
{(20 + (index % 9) * 11).toLocaleString()}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
))}
|
|
</div>
|
|
)}
|
|
<div ref={featuredLoadMoreRef} className="mt-3 flex h-10 items-center justify-center">
|
|
{isLoadingMoreFeatured ? (
|
|
<div className="inline-flex items-center gap-2 text-sm text-black/45 dark:text-white/45">
|
|
<Loader2 className="h-3.5 w-3.5 animate-spin" />
|
|
正在加载更多灵感...
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|