import { type ComponentPropsWithoutRef, type ReactNode } from 'react'; import { type VariantProps } from 'class-variance-authority'; import { ExternalLink, type LucideIcon } from 'lucide-react'; declare const rootVariants: (props?: ({ surface?: "elevated" | "flat" | null | undefined; } & import("class-variance-authority/types").ClassProp) | undefined) => string; export interface ContactProfileCardAddress { /** Display text — already formatted by the consumer (street, postcode, city). */ line: string; /** Optional lat/lng — drives the static-map link + the embedded thumbnail. */ lat?: number; lng?: number; } export interface ContactProfileCardHandle { /** Resolved consumer-supplied data — useful for agent introspection. */ getProfession: () => string | undefined; } export interface ContactProfileCardProps extends Omit, 'aria-label' | 'children' | 'children'> { /** * Override the localised "Profilo" / "Profile" heading. Most * consumers leave this unset. */ heading?: string; /** * Free-text intro paragraph rendered above the data rows (e.g. * the practice's `bookingDescription` field). When omitted, the * card jumps straight into the data rows. */ description?: string; /** Street + postcode + city, with optional lat/lng for the map link. */ address?: ContactProfileCardAddress; /** Phone number, displayed as-is. Compiled into a `tel:` link. */ phone?: string; /** * WhatsApp number — digits only (no `+`, no spaces). Compiled into * a `https://wa.me/` link with an optional pre-filled message. */ whatsappNumber?: string; /** Optional pre-filled WhatsApp message. Consumer-localised. */ whatsappMessage?: string; /** Public-facing email. Compiled into a `mailto:` link. */ email?: string; /** * Practice website. An address without a scheme (`www.example.it`) is * linked over `https://`; anything but a web address shows as text. */ website?: string; /** * Google Maps Static API key. When provided alongside `address.lat` * and `address.lng`, renders a static-map thumbnail at the top of * the card — a single one-shot `` fetch, no JS SDK boot, no * consent gate needed (the same pattern PracticeResults uses). * * Without it (or without coords), the card renders info rows only — * the address row's "Open in Google Maps" link is still emitted as * a real `` so the spatial cue isn't lost. * * Additive — existing consumers that don't pass this prop see the * same render as before. */ googleMapsApiKey?: string; /** * Zoom level for the embedded map thumbnail. Default `14` — * neighbourhood-level, shows the pin in context. Ignored when the * thumbnail isn't rendered. */ mapZoom?: number; /** * ISO 639-1 language codes the practice speaks. Rendered as * `` chips. Each code is auto-resolved * into the active locale's native language name via the kit's * built-in `languages.` i18n bundle (18 ISO codes × 18 * locales). For example `languages={['it', 'en']}` with * `i18n.language === 'it'` renders "Italiano" + "Inglese". * * Unknown / unbundled codes fall back to the uppercase ISO code * (`'xyz'` → `'XYZ'`). To override a specific label — regional * dialect, brand-voice variant, codes the kit doesn't ship — pass * `languageLabels`. */ languages?: string[]; /** * Override map from ISO code → display label, applied on top of * the kit's i18n auto-resolution. Only set when you need a * consumer-specific label for a code — the typical case is * regional dialect / brand-voice variants / non-ISO codes. * * Resolution order: `languageLabels[code]` > `t('languages.')` * > `code.toUpperCase()`. */ languageLabels?: Record; /** * Insurance / convention strings (consumer-supplied, free text). * Rendered as `` chips. */ insurances?: string[]; /** * First-visit price in the smallest currency unit (cents / centesimi). * Formatted via `Intl.NumberFormat`; `0` renders the translated word * "Free". Omit when the consumer doesn't want to show the price. */ firstVisitPriceCents?: number; /** ISO-4217 currency code for the price formatter. Defaults to `EUR`. */ currencyCode?: string; /** Profession line — single value or already-joined comma list. */ profession?: string; /** Show the "expert for anxious patients" row when true. */ specializedInFearPatients?: boolean; /** * Fires when the patient clicks the phone link. The kit emits a * `track('practice_profile_card_phone_click')` event before * invoking this — gate consumer-side analytics on the same event * to avoid duplicate fires. */ onPhoneClick?: () => void; /** Fires when the patient clicks the WhatsApp link. */ onWhatsAppClick?: () => void; /** Fires when the patient clicks the static-map link. */ onMapClick?: () => void; /** Fires when the patient clicks the email mailto link. */ onEmailClick?: () => void; /** * Rendered above the heading — e.g. a `` for the operator * variant, or a coloured chip strip. Optional. */ headerSlot?: ReactNode; /** * Render an arbitrary map widget at the top of the card chrome — * replaces the built-in static `` thumbnail that * `googleMapsApiKey` would otherwise produce. Use this when you * want an interactive map inside the card boundary instead of a * fixed image: * * * } * … * /> * * When both `mapSlot` and `googleMapsApiKey` are provided, the slot * wins (explicit > implicit). When neither is provided, no map area * renders. The slot is unstyled — pass through any container chrome * the consumer wants (e.g. a fixed height wrapper). The kit * positions it where the static thumbnail would have lived. */ mapSlot?: ReactNode; /** * Rendered at the end of the card body, below the rows. Use for * a "Book now" `