import { LoaderCircle } from "lucide-react"; import { DownloadCloudIcon } from "../icons/DownloadCloudIcon"; import { useState, type MouseEvent } from "react"; import { useI18n } from "../../i18n"; import type { Attachment } from "../../types/post"; import { downloadAttachment } from "./utils/downloadFile"; import { formatBytes } from "./utils/formatBytes"; import { useToast } from "../Toast"; type AttachmentDownloadPillProps = { postId: string; attachment: Attachment; leadingLabel?: string; className?: string; /** * When true, the pill scales with its container's width via container-query * units (clamped to a min/max). The host element must establish a query * container (e.g. `style={{ containerType: "inline-size" }}`). Use this on * album tiles so the pill shrinks on small thumbnails. Defaults to a fixed * size for standalone images/videos. */ adaptive?: boolean; }; export function AttachmentDownloadPill({ postId, attachment, leadingLabel, className = "absolute left-2 top-2", adaptive = false, }: AttachmentDownloadPillProps) { const { t } = useI18n(); const { showToast } = useToast(); const [isDownloading, setIsDownloading] = useState(false); const handleDownload = async (e: MouseEvent) => { e.stopPropagation(); if (isDownloading) return; setIsDownloading(true); try { await downloadAttachment(postId, attachment.id, attachment.filename); showToast(t("downloadOk")); } catch { showToast(t("downloadFail"), "error"); } finally { setIsDownloading(false); } }; // Fixed default vs. container-query-driven adaptive sizing (clamped). const fontCls = adaptive ? "text-[clamp(10px,5cqw,12px)]" : "text-[12px]"; const squareCls = adaptive ? "h-[clamp(22px,11cqw,30px)] w-[clamp(22px,11cqw,30px)]" : "h-[30px] w-[30px]"; const iconCls = adaptive ? "h-[clamp(13px,6.5cqw,18px)] w-[clamp(13px,6.5cqw,18px)]" : "h-[18px] w-[18px]"; const textBoxCls = adaptive ? "h-[clamp(22px,11cqw,30px)] px-[clamp(6px,3cqw,10px)]" : "h-[30px] px-2.5"; return ( ); }