ultisuite-client/components/gmail/email-list/attachments/email-list-attachment-row.tsx
2026-05-20 16:01:08 +02:00

89 lines
2.6 KiB
TypeScript

"use client"
import {
useCallback,
useEffect,
useLayoutEffect,
useRef,
useState,
} from "react"
import type { EmailAttachment } from "@/lib/email-data"
import { ListAttachmentChip } from "./list-attachment-chip"
export function EmailListAttachmentRow({
emailId,
attachments,
}: {
emailId: string
attachments: EmailAttachment[]
}) {
const containerRef = useRef<HTMLDivElement>(null)
const measureRef = useRef<HTMLDivElement>(null)
const [collapsed, setCollapsed] = useState(false)
const attachSig = attachments.map((a) => `${a.name}\u0001${a.kind ?? ""}`).join("\u0002")
const updateCollapsed = useCallback(() => {
const container = containerRef.current
const measure = measureRef.current
if (!container || !measure || attachments.length <= 1) {
setCollapsed(false)
return
}
const available = container.clientWidth
const needed = measure.scrollWidth
setCollapsed(needed > available + 1)
}, [attachSig, attachments.length])
useLayoutEffect(() => {
updateCollapsed()
}, [updateCollapsed])
useEffect(() => {
const el = containerRef.current
if (!el || typeof ResizeObserver === "undefined") return
const ro = new ResizeObserver(() => updateCollapsed())
ro.observe(el)
return () => ro.disconnect()
}, [updateCollapsed])
const othersLabel =
attachments.length - 1 === 1 ? "1 autre" : `${attachments.length - 1} autres`
const othersTitle = attachments
.slice(1)
.map((a) => a.name)
.join(", ")
return (
<div ref={containerRef} className="relative min-w-0 w-full">
{attachments.length > 1 && (
<div
ref={measureRef}
className="pointer-events-none invisible absolute left-0 top-0 z-[-1] flex w-max flex-nowrap gap-1.5"
aria-hidden
>
{attachments.map((att, idx) => (
<ListAttachmentChip key={`${emailId}-m-${idx}`} att={att} />
))}
</div>
)}
<div className="flex min-w-0 flex-nowrap items-center gap-1.5 overflow-hidden">
{collapsed && attachments.length > 1 ? (
<>
<ListAttachmentChip att={attachments[0]!} />
<span
className="shrink-0 rounded-full border border-mail-list-chip-border bg-mail-list-chip-muted px-2.5 py-1 text-[13px] leading-snug text-muted-foreground"
title={othersTitle}
>
{othersLabel}
</span>
</>
) : (
attachments.map((att, idx) => (
<ListAttachmentChip key={`${emailId}-v-${idx}`} att={att} />
))
)}
</div>
</div>
)
}