import { z } from 'zod'; import * as react from 'react'; import { ReactNode } from 'react'; interface StorageAdapter { getItem(key: string): Promise; setItem(key: string, value: string): Promise; removeItem(key: string): Promise; } interface DeviceAdapter { /** Auto-captured context attached to feedback (os, version, locale, screen…). */ getMetadata(): Record; } interface ShakeAdapter { /** * Subscribe to shake gestures; returns an unsubscribe fn. No-op if unsupported. * `options.threshold` is the total acceleration (g) that counts as a shake — * higher values require a stronger shake. Falls back to the adapter default. */ subscribe(onShake: () => void, options?: { threshold?: number; }): () => void; } interface EventSourceAdapter { /** * Open a Server-Sent Events connection to `url`. `onSignal` is called with * each event's `type` string (the SSE payload is a lightweight signal — the * client refetches the named resource). Returns an unsubscribe that closes * the connection. No-op / unsupported adapters may return a no-op cleanup. */ connect(url: string, onSignal: (type: string) => void): () => void; } interface PlatformAdapters { storage: StorageAdapter; device: DeviceAdapter; shake?: ShakeAdapter; /** Live updates over SSE. Optional — without it the SDK stays pull-only. */ eventSource?: EventSourceAdapter; } interface QueuedAction { id: string; type: "messages"; payload: Record; createdAt: number; } declare class OfflineQueue { private readonly storage; private items; private loaded; constructor(storage: StorageAdapter); load(): Promise; private persist; enqueue(type: QueuedAction["type"], payload: Record): Promise; remove(id: string): Promise; list(): Promise; } declare const themeTokensSchema: z.ZodNullable>; colors: z.ZodOptional>>; radius: z.ZodOptional; typography: z.ZodOptional>>>; }, z.core.$strip>>; type ThemeTokens = z.infer; declare const activationConfigSchema: z.ZodObject<{ fab: z.ZodBoolean; shake: z.ZodBoolean; programmatic: z.ZodBoolean; }, z.core.$strip>; type ActivationConfig = z.infer; declare const widgetConfigSchema: z.ZodObject<{ theme: z.ZodNullable>; colors: z.ZodOptional>>; radius: z.ZodOptional; typography: z.ZodOptional>>>; }, z.core.$strip>>; enabledModules: z.ZodObject<{ messages: z.ZodBoolean; featureRequests: z.ZodBoolean; changelog: z.ZodBoolean; }, z.core.$strip>; copy: z.ZodNullable>>; activation: z.ZodObject<{ fab: z.ZodBoolean; shake: z.ZodBoolean; programmatic: z.ZodBoolean; }, z.core.$strip>; autoShow: z.ZodOptional; }, z.core.$strip>>; }, z.core.$strip>; type WidgetConfig = z.infer; interface AutoShowConfig { announcements: boolean; changelog: boolean; /** Auto-open the panel to a thread when there's a new unread admin reply. */ messages: boolean; } interface WherdUser { /** Your stable user id (becomes externalId server-side). */ id: string; email?: string; name?: string; /** HMAC-SHA256(id, secretKey) computed on your server — marks identity verified. */ userHash?: string; traits?: Record; } type WherdView = "messages" | "changelog" | "featureRequests"; /** Message category shown as chips when starting a new thread. */ type MessageType = "idea" | "issue" | "other"; interface IdentifyResponse { endUserId: string; verified: boolean; } interface StartMessageResponse { id: string; createdAt: string; } type MessageAuthor = "user" | "admin"; interface MessageReply { author: MessageAuthor; body: string; createdAt: string; } interface MessageThread { id: string; /** Who opened the thread. Defaults to "user"; "admin" means an operator * reached out first, so the opening body renders as their message. */ origin?: MessageAuthor; body: string; createdAt: string; /** Admin replies the end-user hasn't read yet. */ unread: number; replies: MessageReply[]; } interface MessagesResponse { threads: MessageThread[]; unreadTotal: number; } type AnnouncementSeverity = "info" | "warning" | "critical"; interface Announcement { id: string; title: string; body: string; severity: AnnouncementSeverity; publishedAt: string | null; } interface AnnouncementsResponse { announcements: Announcement[]; } interface ChangelogEntry { id: string; title: string; body: string; publishedAt: string | null; read: boolean; } interface ChangelogResponse { entries: ChangelogEntry[]; unreadCount: number; } type FeatureRequestStatus = "open" | "planned" | "in_progress" | "done"; interface FeatureRequest { id: string; title: string; body: string | null; status: FeatureRequestStatus; voteCount: number; createdAt: string; hasVoted: boolean; } interface WherdState { /** True once init() (config load + identity) has completed. */ ready: boolean; isOpen: boolean; view: WherdView; config: WidgetConfig | null; /** Theme passed by the developer via the Provider — overrides server config. */ localTheme: ThemeTokens | null; /** Activation overrides from the Provider — override server config (fab/shake). */ localActivation: Partial | null; user: WherdUser | null; verified: boolean; /** Unread changelog count — drives the "What's New" badge app-wide. */ changelogUnread: number; /** The user's message threads (shared so live updates reach every view). */ messages: MessageThread[]; /** Unread admin replies across the user's message threads. */ messagesUnread: number; /** Active, non-dismissed announcements (banners). */ announcements: Announcement[]; /** Bumped on each live feature-request event so list hooks refetch. */ featureRequestsRevision: number; } declare class Store { private state; private listeners; constructor(initial: WherdState); getSnapshot: () => WherdState; subscribe: (listener: () => void) => (() => void); set(patch: Partial): void; } interface WherdClientOptions { /** The project's publishable public key (pk_...). */ publicKey: string; /** Wherd API base URL. Defaults to the hosted API; override only for local dev. */ apiUrl?: string; user?: WherdUser; /** Developer theme override, merged over server config. */ theme?: ThemeTokens; /** Activation overrides (fab/shake), merged over server config. */ activation?: Partial; /** Auto-show overrides (announcements/changelog), merged over server config. */ autoShow?: Partial; adapters: PlatformAdapters; } interface SubmitResult { ok: boolean; queued: boolean; id?: string; error?: string; } declare class WherdClient { readonly store: Store; readonly queue: OfflineQueue; private readonly adapters; private readonly publicKey; private readonly apiUrl; private anonymousId; private user; private readonly localAutoShow; private dismissedAnnouncements; private liveDispose; constructor(opts: WherdClientOptions); init(): Promise; private autoShow; private maybeAutoShowAnnouncement; private maybeAutoShowChangelog; private maybeAutoShowMessages; subscribeLive(): () => void; disconnectLive(): void; private handleLiveEvent; foregroundRefresh(): Promise; shouldShowShakeHint(): Promise; dismissShakeHint(): Promise; private headers; getAnonymousId(): string; refreshConfig(): Promise; identify(user: WherdUser): Promise; startMessage(input: { body: string; metadata?: Record; }): Promise; refreshMessages(): Promise; replyToMessage(messageId: string, body: string): Promise; markMessageRead(messageId: string): Promise; refreshAnnouncements(): Promise; dismissAnnouncement(announcementId: string): Promise; private identityQuery; listFeatureRequests(): Promise; createFeatureRequest(input: { title: string; body?: string; }): Promise; voteFeatureRequest(requestId: string, voted: boolean): Promise<{ voted: boolean; voteCount: number; } | null>; refreshChangelog(): Promise; markChangelogRead(entryId: string): Promise; flush(): Promise; open(view?: WherdView): void; close(): void; setView(view: WherdView): void; setTheme(theme: ThemeTokens | null): void; } interface ResolvedTheme { colorScheme: "light" | "dark"; colors: { primary: string; primaryForeground: string; background: string; foreground: string; muted: string; mutedForeground: string; border: string; }; radius: number; fontFamily?: string; } declare function resolveTheme(server: ThemeTokens | null | undefined, local: ThemeTokens | null | undefined, systemColorScheme?: "light" | "dark"): ResolvedTheme; declare function uid(prefix?: string): string; declare function timeAgo(iso: string): string; declare function formatMessageTime(iso: string): string; declare function WherdCoreProvider({ client, children, }: { client: WherdClient; children: ReactNode; }): react.JSX.Element; declare function useWherdClient(): WherdClient; declare function useWherdState(): WherdState; declare function useWherd(): { open: (view?: WherdView) => void; close: () => void; setView: (view: WherdView) => void; identify: (user: WherdUser) => Promise; start: (input: { body: string; metadata?: Record; }) => Promise; ready: boolean; isOpen: boolean; view: WherdView; config: WidgetConfig | null; localTheme: ThemeTokens | null; localActivation: Partial | null; user: WherdUser | null; verified: boolean; changelogUnread: number; messages: MessageThread[]; messagesUnread: number; announcements: Announcement[]; featureRequestsRevision: number; }; declare function useComposer(): { body: string; setBody: react.Dispatch>; type: MessageType; setType: react.Dispatch>; email: string; setEmail: react.Dispatch>; submit: () => Promise; submitting: boolean; submitted: boolean; queued: boolean; error: string | null; reset: () => void; }; declare function useMessages(): { threads: MessageThread[]; unreadTotal: number; loading: boolean; refresh: () => Promise; reply: (id: string, body: string) => Promise; markRead: (id: string) => Promise; }; declare function useUnreadMessages(): number; declare function useAnnouncements(): { announcements: Announcement[]; dismiss: (id: string) => Promise; }; declare function useFeatureRequests(): { requests: FeatureRequest[]; loading: boolean; refresh: () => Promise; vote: (id: string, next: boolean) => Promise; create: (input: { title: string; body?: string; }) => Promise; }; declare function useUnreadChangelog(): number; declare function useActivation(): ActivationConfig; declare function useShakeHint(): { visible: boolean; dismiss: () => void; }; declare function useChangelog(): { entries: ChangelogEntry[]; loading: boolean; refresh: () => Promise; markRead: (id: string) => Promise; markAllRead: () => Promise; }; declare function useResolvedTheme(systemColorScheme?: "light" | "dark"): ResolvedTheme; export { type ActivationConfig, type Announcement, type AnnouncementSeverity, type AnnouncementsResponse, type AutoShowConfig, type ChangelogEntry, type ChangelogResponse, type DeviceAdapter, type EventSourceAdapter, type FeatureRequest, type FeatureRequestStatus, type IdentifyResponse, type MessageAuthor, type MessageReply, type MessageThread, type MessageType, type MessagesResponse, OfflineQueue, type PlatformAdapters, type QueuedAction, type ResolvedTheme, type ShakeAdapter, type StartMessageResponse, type StorageAdapter, Store, type SubmitResult, type ThemeTokens, WherdClient, type WherdClientOptions, WherdCoreProvider, type WherdState, type WherdUser, type WherdView, type WidgetConfig, activationConfigSchema, formatMessageTime, resolveTheme, themeTokensSchema, timeAgo, uid, useActivation, useAnnouncements, useChangelog, useComposer, useFeatureRequests, useMessages, useResolvedTheme, useShakeHint, useUnreadChangelog, useUnreadMessages, useWherd, useWherdClient, useWherdState, widgetConfigSchema };