/** * Bundled WhatsApp icon variants, selectable via `config.iconVariant` * without hosting any image files. `solid` mirrors the library's own * default glyph (`DEFAULT_ICON_SVG` in styles.ts) so the two never drift * apart. None of these draw a border/outline/shadow — see the note above. */ declare const ICON_VARIANTS: { readonly solid: string; readonly roundedSquare: string; readonly flat: string; readonly mono: string; }; type IconVariantKey = keyof typeof ICON_VARIANTS; interface ImagesConfig { desktop?: string; mobile?: string; } interface WeightedNumber { phone: string; weight?: number; } type DistributionStrategy = "random" | "roundrobin" | "round-robin" | "round_robin" | "weighted"; interface ScheduleConfig { /** e.g. ["monday", "tuesday", "wednesday", "thursday", "friday"] */ days?: string[]; hours?: { /** "HH:MM" 24h format, local time */ start: string; end: string; }; /** IANA timezone, e.g. "America/Manaus". If omitted, uses browser local time. */ timezone?: string; } interface UtmMatch { source?: string; medium?: string; campaign?: string; term?: string; content?: string; [key: string]: string | undefined; } interface RuleConfig { country?: string; state?: string; city?: string; cities?: string[]; /** Single fixed phone number for this rule */ phone?: string; /** Multiple numbers for distribution strategies */ numbers?: WeightedNumber[]; distribution?: DistributionStrategy; /** Override the button image(s) when this rule matches */ images?: ImagesConfig; /** * Override the wa.me `?text=` message when this rule matches, e.g. to * greet visitors from a specific city/state/country differently. * Resolved independently from `phone`/`numbers` — see resolveMessage() * in rules.ts — so a rule can supply only `message` and still let * phone resolution fall through to another rule/fallback, or vice versa. * Falls back to the top-level `message` if omitted. */ message?: string; /** * Override the pill button's label (`pill.text`) when this rule * matches — only meaningful when the top-level `pill` config is set; * ignored otherwise. Resolved independently from phone/message, same * pattern as `message` — see resolvePillText() in rules.ts. */ pillText?: string; schedule?: ScheduleConfig; utm?: UtmMatch; language?: string; referrer?: string; domain?: string; page?: string; continent?: string; [key: string]: unknown; } /** * Rules matched against the current URL path (e.g. "/promocao"), evaluated * BEFORE location-based rules. The first matching rule wins and its `phone` * / `images` override whatever location-based resolution would have picked. * A rule that omits `phone` still lets location rules decide the number, * while its `images` override still applies (or vice-versa). */ interface PathRuleConfig { /** Substring or path the current pathname must contain. */ path?: string; /** Regular expression (as string, no slashes) tested against the pathname. */ pathRegex?: string; phone?: string; numbers?: WeightedNumber[]; distribution?: DistributionStrategy; images?: ImagesConfig; /** Override the wa.me `?text=` message when this path rule matches — see RuleConfig.message. */ message?: string; /** Override the pill button's label when this path rule matches — see RuleConfig.pillText. */ pillText?: string; schedule?: ScheduleConfig; utm?: UtmMatch; } interface FallbackConfig { phone?: string; numbers?: WeightedNumber[]; distribution?: DistributionStrategy; /** Override the wa.me `?text=` message when every other rule misses — see RuleConfig.message. */ message?: string; /** Override the pill button's label when every other rule misses — see RuleConfig.pillText. */ pillText?: string; } interface PulseConfig { /** Icon "breathing" scale animation. Defaults to `true` whenever `theme.pulse` is set at all. */ scale?: boolean; /** Colored expanding ring/halo around the button. Off by default. */ ring?: boolean; /** Animation cycle length, in ms. Default `1800`. */ duration?: number; /** Peak scale factor for the breathing effect. Default `1.08`. */ scaleAmount?: number; /** Ring color. Default `"#25D366"`. */ color?: string; /** Ring starting opacity. Default `0.55`. */ opacity?: number; } interface ThemeConfig { dark?: boolean; /** Adds a drop shadow behind the button image. Off by default — most images (banners, custom icons) already have their own design. */ shadow?: boolean; /** Rounds the button image's corners. Off by default, for the same reason as `shadow`. */ rounded?: boolean; /** * Makes the button pulse to draw attention. `true` enables the icon * scale/"breathing" animation with default timing (equivalent to * `{ scale: true }`). Pass a `PulseConfig` object to also enable the * ring/halo effect or tune duration, scale amount, color and opacity. */ pulse?: boolean | PulseConfig; /** * Icon/image height on desktop. Accepts px (number) or any CSS length. * Always has a sane default (`64px`) and is always responsive — see `iconSizeMobile`. */ iconSize?: CssOffset; /** Icon/image height at/below `mobileBreakpoint`. Defaults to `56px`, or to `iconSize` if you only want one fixed size everywhere. */ iconSizeMobile?: CssOffset; [key: string]: unknown; } /** * Renders a pill-shaped button — an icon plus a text label — instead of an * image or bare icon. Picking `pill` is an exclusive button style: when * present, `images`/`assetsBaseUrl`/`icon`/`iconVariant` at the top level * are ignored entirely (use `pill.icon` to choose the icon shown inside it). */ interface PillConfig { text: string; /** * How the text label expands relative to the icon: * - `"hover"` (default) — expands on mouse hover, collapses back to icon-only otherwise. * - `"always"` — always expanded. * - `"click"` — first click/tap expands it; the next click opens WhatsApp. * - `"never"` — stays icon-only; the text is still set as the accessible label. */ expand?: "hover" | "always" | "click" | "never"; /** * Override `expand` on mobile (at/below `mobileBreakpoint`). * Useful for "hover on desktop, always on mobile" patterns. * Falls back to `expand` when not set. */ expandMobile?: "hover" | "always" | "click" | "never"; /** Icon shown inside the pill. Defaults to the `"solid"` built-in variant. */ icon?: IconVariantKey | (string & {}); /** Pill background color. Defaults to `"#25D366"` (WhatsApp green). */ color?: string; /** Pill text color. Defaults to `"#ffffff"`. */ textColor?: string; /** Font size of the label in px. Defaults to `14`. */ fontSize?: number; /** Font weight. Defaults to `600`. */ fontWeight?: number | string; /** Extra horizontal padding between icon and text right edge, in px. Defaults to `18`. */ paddingRight?: number; /** Border radius of the pill in px. Defaults to `999` (fully rounded). */ borderRadius?: number; } /** Number = pixels. String accepts any valid CSS length, e.g. "5%", "2rem", "16px". */ type CssOffset = number | string; type PositionKeyword = "bottom-right" | "bottom-left" | "custom"; interface OffsetConfig { top?: CssOffset; bottom?: CssOffset; left?: CssOffset; right?: CssOffset; } interface LocationOverride { country?: string; state?: string; region?: string; city?: string; } interface ResolvedLocation { country: string | null; state: string | null; city: string | null; ip: string | null; } type MatchLevel = "Path" | "Cidade" | "Estado" | "País" | "Fallback" | "Manual"; interface PhoneMatchResult { phone: string | null; matched: MatchLevel; rule: RuleConfig | FallbackConfig | PathRuleConfig | null; /** Image override carried by a matching path rule, applied on top of the resolved images. */ images?: ImagesConfig; } interface MatchContext { language: string; referrer: string; domain: string; page: string; utm: Record; query: Record; cookies: string; localStorage: Storage | null; sessionStorage: Storage | null; continent: string | null; } interface ReadyEventPayload { phone: string | null; location: ResolvedLocation; matched: PhoneMatchResult["matched"]; } interface LocationEventPayload extends ResolvedLocation { } interface PhoneSelectedEventPayload { phone: string | null; matched: PhoneMatchResult["matched"]; } interface OpenEventPayload { phone: string | null; } interface CloseEventPayload { phone: string | null; } interface WhatsAppFloatingConfig { message?: string; /** * Explicit image URLs. When omitted, defaults to * `${assetsBaseUrl}/whatsapp-desktop.png` and `${assetsBaseUrl}/whatsapp-mobile.png`. * Can always be overridden programmatically via `WhatsAppFloating.setImages()`. */ images?: ImagesConfig; /** * Base URL used to build the default PNG asset paths * (`whatsapp-desktop.png` / `whatsapp-mobile.png`) when `images` is not set. */ assetsBaseUrl?: string; icon?: string; /** Built-in icon to use instead of `icon`/an image. See `PillConfig.icon` for the same choices used inside a pill. Ignored when `images`/`assetsBaseUrl` resolve to a URL, and when `pill` is set. */ iconVariant?: IconVariantKey | (string & {}); /** Renders a pill-shaped icon+text button instead of an image/icon. Exclusive of `images`/`icon`/`iconVariant`. */ pill?: PillConfig; ariaLabel?: string; imageAlt?: string; fallback?: FallbackConfig; rules?: RuleConfig[]; /** * Rules matched against the current URL path, evaluated before * location-based rules. First match wins and overrides phone/images. */ pathRules?: PathRuleConfig[]; /** Manually override detected location instead of calling the geo API */ location?: LocationOverride; geoApiUrl?: string; /** Extra endpoints to try, in order, before giving up. Built-in providers are used if omitted. */ geoProviders?: string[]; geoTimeout?: number; /** Cache the resolved location in localStorage. Default: false (always resolves in real time). */ cacheLocation?: boolean; geoCacheTTL?: number; remoteConfigUrl?: string; /** Viewport width (px) at or below which the mobile image/logic is used. */ mobileBreakpoint?: number; /** * Corner the button is anchored to. Defaults to "bottom-right". * Fine-tune the exact distance from that corner with `offset`. */ position?: PositionKeyword; /** Distance from the anchored corner(s). Accepts px (number) or any CSS length ("5%", "2rem"). */ offset?: OffsetConfig; zIndex?: number; theme?: ThemeConfig; css?: string; appendUtmToMessage?: boolean; analytics?: boolean; lazyLoad?: boolean; debug?: boolean; production?: boolean; onReady?: (payload: ReadyEventPayload) => void; onLocation?: (payload: LocationEventPayload) => void; onPhoneSelected?: (payload: PhoneSelectedEventPayload) => void; onOpen?: (payload: OpenEventPayload) => void; onClose?: (payload: CloseEventPayload) => void; [key: string]: unknown; } type EventName = "ready" | "location" | "phoneSelected" | "open" | "close"; declare global { interface Window { WhatsAppFloatingConfig?: WhatsAppFloatingConfig; WhatsAppFloating?: unknown; gtag?: (...args: unknown[]) => void; dataLayer?: unknown[]; fbq?: (...args: unknown[]) => void; } } type Listener = (detail: unknown) => void; declare class WhatsAppFloatingWidget { private config; private location; private phone; private matched; private el; private ready; private listeners; private geoPromise; /** Rule-driven image override (from a matching pathRule/rule). */ private ruleImages; private ruleMessage; private rulePillText; /** Explicit programmatic override set via setImages(), takes precedence over everything. */ private manualImages; /** Whether a `pill` button with `expand: "click"` is currently expanded. */ private pillExpanded; /** Incremented each time init() is called — lets a stale async start() detect it was superseded. */ private initGen; private emit; on(name: EventName, fn: Listener): this; off(name: EventName, fn: Listener): this; private buildContext; init(userConfig: WhatsAppFloatingConfig): Promise; private loadRemoteConfig; private printConsole; private resolveImages; private resolveImage; private applyMessagePlaceholders; private buildLink; private preloadImage; private render; reload(newConfig?: Partial): Promise; open(): this; close(): this; destroy(silent?: boolean): this; setPhone(phone: string): this; /** Programmatically override the desktop/mobile images, taking precedence over config and rules. */ setImages(images: ImagesConfig): this; getImages(): ImagesConfig; getPhone(): string | null; getLocation(): ResolvedLocation; getMatched(): PhoneMatchResult["matched"] | null; isReady(): boolean; getVersion(): string; } interface WhatsAppFloatingAPI { version: string; init(config: WhatsAppFloatingConfig): Promise; reload(config?: Partial): Promise; open(): WhatsAppFloatingWidget; close(): WhatsAppFloatingWidget; destroy(): WhatsAppFloatingWidget; getPhone(): string | null; getLocation(): ResolvedLocation; getMatched(): PhoneMatchResult["matched"] | null; setPhone(phone: string): WhatsAppFloatingWidget; setImages(images: ImagesConfig): WhatsAppFloatingWidget; getImages(): ImagesConfig; isReady(): boolean; on(name: EventName, fn: (detail: unknown) => void): WhatsAppFloatingWidget; off(name: EventName, fn: (detail: unknown) => void): WhatsAppFloatingWidget; } declare const api: WhatsAppFloatingAPI; declare function boot(): void; export { type CloseEventPayload, type CssOffset, type DistributionStrategy, type EventName, type FallbackConfig, type ImagesConfig, type LocationEventPayload, type LocationOverride, type MatchContext, type MatchLevel, type OffsetConfig, type OpenEventPayload, type PathRuleConfig, type PhoneMatchResult, type PhoneSelectedEventPayload, type PillConfig, type PositionKeyword, type PulseConfig, type ReadyEventPayload, type ResolvedLocation, type RuleConfig, type ScheduleConfig, type ThemeConfig, type UtmMatch, type WeightedNumber, type WhatsAppFloatingAPI, type WhatsAppFloatingConfig, boot, api as default };