"use client" import { useLayoutEffect, useRef, type ComponentType, type ReactNode } from "react" import { Check, Minus, Plus } from "lucide-react" import { Icon } from "@iconify/react" import { Input } from "@/components/ui/input" import { cn } from "@/lib/utils" import type { LabelRowItem } from "@/lib/sidebar-nav-data" import type { LabelPickerVisual } from "@/lib/label-picker-visual" import { LabelPickerLeadingVisual } from "@/components/gmail/email-label-picker-block" export type ContactLabelPresence = "none" | "some" | "all" export type ContactLabelPickerItemComponent = ComponentType<{ children: ReactNode onSelect?: (event: Event) => void className?: string }> function LabelPickerCheckboxVisual({ checked, }: { checked: boolean | "indeterminate" }) { return ( {checked === true ? ( ) : checked === "indeterminate" ? ( ) : null} ) } export function ContactLabelPickerBlock({ query, onQueryChange, labelRows, resolveLabelVisual, Item, getLabelPresence, onToggleLabel, onCreateLabel, listClassName, searchAutoFocus = true, }: { query: string onQueryChange: (v: string) => void labelRows: LabelRowItem[] resolveLabelVisual: (labelId: string) => LabelPickerVisual Item: ContactLabelPickerItemComponent getLabelPresence: (labelId: string) => ContactLabelPresence onToggleLabel: (labelId: string) => void onCreateLabel: (labelText: string) => void listClassName?: string searchAutoFocus?: boolean }) { const searchInputRef = useRef(null) useLayoutEffect(() => { if (!searchAutoFocus) return let inner = 0 const outer = requestAnimationFrame(() => { inner = requestAnimationFrame(() => { searchInputRef.current?.focus({ preventScroll: true }) }) }) return () => { cancelAnimationFrame(outer) if (inner) cancelAnimationFrame(inner) } }, [searchAutoFocus]) const q = query.trim().toLowerCase() const available = labelRows.filter((r) => r.enabled !== false) const filtered = available.filter( (row) => q.length === 0 || row.label.toLowerCase().includes(q), ) const trimmed = query.trim() const hasExact = available.some( (row) => row.label.toLowerCase() === trimmed.toLowerCase(), ) const canCreate = trimmed.length > 0 && !hasExact return ( <>
e.stopPropagation()} > onQueryChange(e.target.value)} placeholder="Rechercher ou créer un libellé…" aria-label="Rechercher ou créer un libellé" className="h-8 border-[#dadce0] text-sm shadow-none" autoComplete="off" onPointerDown={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()} onKeyDown={(e) => e.stopPropagation()} />
{canCreate ? ( { e.preventDefault() onCreateLabel(trimmed) }} > Créer le libellé « {trimmed} » ) : null} {filtered.map((row) => { const presence = getLabelPresence(row.id) const boxChecked: boolean | "indeterminate" = presence === "all" ? true : presence === "some" ? "indeterminate" : false return ( { e.preventDefault() onToggleLabel(row.id) }} > {row.icon ? ( ) : ( )} {row.label} ) })} {filtered.length === 0 && !canCreate ? (
Aucun libellé correspondant
) : null}
) }