{"version":3,"sources":["../src/index.ts","../src/react.tsx"],"names":["Heartbeep","config","apiUrl","item","data","payload","error","event","name","metadata","HeartbeepContext","createContext","HeartbeepProvider","children","siteId","debug","heartbeepRef","useRef","useEffect","contextValue","React","useHeartbeep","context","useContext","AutoPageview","pageview","handleRouteChange"],"mappings":"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","file":"react.mjs","sourcesContent":["import type {\n  HeartbeepConfig,\n  EventType,\n  TrackEventData,\n  TrackEventPayload,\n} from \"./types\";\n\nexport * from \"./types\";\n\nexport class Heartbeep {\n  private config: HeartbeepConfig;\n  private queue: Array<{ event: EventType; payload?: TrackEventPayload }> = [];\n  private isReady = false;\n\n  constructor(config: HeartbeepConfig) {\n    if (!config.siteId) {\n      throw new Error(\"[Heartbeep] siteId is required\");\n    }\n\n    // Build the API URL\n    let apiUrl = config.apiUrl || 'https://heartbeep.live/api/beep/website';\n    // Remove trailing slash\n    apiUrl = apiUrl.replace(/\\/$/, '');\n    // Append siteId if not already included\n    if (!apiUrl.includes(config.siteId)) {\n      apiUrl = `${apiUrl}/${config.siteId}`;\n    }\n\n    this.config = {\n      ...config,\n      apiUrl,\n      debug: config.debug || false,\n    };\n\n    // Initialize when DOM is ready\n    if (typeof window !== \"undefined\") {\n      if (document.readyState === \"loading\") {\n        document.addEventListener(\"DOMContentLoaded\", () => this.init());\n      } else {\n        this.init();\n      }\n    }\n  }\n\n  private init(): void {\n    this.isReady = true;\n    this.processQueue();\n\n    if (this.config.debug) {\n      console.log(\"[Heartbeep] Initialized with siteId:\", this.config.siteId);\n    }\n  }\n\n  private processQueue(): void {\n    while (this.queue.length > 0) {\n      const item = this.queue.shift();\n      if (item) {\n        this.track(item.event, item.payload);\n      }\n    }\n  }\n\n  private async send(data: TrackEventData): Promise<void> {\n    if (this.config.debug) {\n      console.log(\"[Heartbeep] Tracking event:\", data);\n    }\n\n    try {\n      const payload = JSON.stringify(data);\n\n      // Try sendBeacon first for reliability\n      if (typeof navigator !== \"undefined\" && navigator.sendBeacon) {\n        const sent = navigator.sendBeacon(this.config.apiUrl!, payload);\n        if (sent) return;\n      }\n\n      // Fallback to fetch\n      if (typeof fetch !== \"undefined\") {\n        await fetch(this.config.apiUrl!, {\n          method: \"POST\",\n          headers: { \"Content-Type\": \"application/json\" },\n          body: payload,\n          keepalive: true,\n        });\n      }\n    } catch (error) {\n      if (this.config.debug) {\n        console.error(\"[Heartbeep] Error tracking event:\", error);\n      }\n    }\n  }\n\n  track(event: EventType, payload?: TrackEventPayload): void {\n    // Queue events if not ready\n    if (!this.isReady) {\n      this.queue.push({ event, payload });\n      return;\n    }\n\n    // Skip tracking if running on server\n    if (typeof window === \"undefined\") {\n      return;\n    }\n\n    const data: TrackEventData = {\n      event,\n      name: payload?.name || document.title,\n      url: window.location.href,\n      timestamp: Date.now(),\n      metadata: payload?.metadata,\n    };\n\n    this.send(data);\n  }\n\n  // Convenience method for pageview tracking\n  pageview(name?: string): void {\n    this.track(\"pageview\", { name });\n  }\n\n  // Convenience method for click tracking\n  click(name: string, metadata?: Record<string, any>): void {\n    this.track(\"click\", { name, metadata });\n  }\n\n  // Convenience method for purchase tracking\n  purchase(name: string, metadata?: Record<string, any>): void {\n    this.track(\"purchase\", { name, metadata });\n  }\n}\n\n// Convenience beep function for quick tracking\nexport function beep(event: EventType, name?: string): void {\n  console.log(`[Beeper] 🔔 ${event}: ${name || \"unnamed event\"}`);\n}\n","import React, { createContext, useContext, useEffect, useRef } from \"react\";\nimport { Heartbeep } from \"./index\";\nimport type { HeartbeepConfig, EventType, TrackEventPayload } from \"./types\";\n\ninterface HeartbeepContextValue {\n  heartbeep: Heartbeep | null;\n  track: (event: EventType, payload?: TrackEventPayload) => void;\n  pageview: (name?: string) => void;\n  click: (name: string, metadata?: Record<string, any>) => void;\n  purchase: (name: string, metadata?: Record<string, any>) => void;\n}\n\nconst HeartbeepContext = createContext<HeartbeepContextValue | null>(null);\n\nexport interface HeartbeepProviderProps {\n  children: React.ReactNode;\n  siteId: string;\n  apiUrl?: string;\n  debug?: boolean;\n}\n\nexport function HeartbeepProvider({\n  children,\n  siteId,\n  apiUrl,\n  debug,\n}: HeartbeepProviderProps) {\n  const heartbeepRef = useRef<Heartbeep | null>(null);\n\n  useEffect(() => {\n    if (typeof window !== \"undefined\" && !heartbeepRef.current) {\n      const config: HeartbeepConfig = {\n        siteId,\n        apiUrl,\n        debug,\n      };\n      heartbeepRef.current = new Heartbeep(config);\n    }\n  }, [siteId, apiUrl, debug]);\n\n  const contextValue: HeartbeepContextValue = {\n    heartbeep: heartbeepRef.current,\n    track: (event, payload) => {\n      heartbeepRef.current?.track(event, payload);\n    },\n    pageview: name => {\n      heartbeepRef.current?.pageview(name);\n    },\n    click: (name, metadata) => {\n      heartbeepRef.current?.click(name, metadata);\n    },\n    purchase: (name, metadata) => {\n      heartbeepRef.current?.purchase(name, metadata);\n    },\n  };\n\n  return (\n    <HeartbeepContext.Provider value={contextValue}>\n      {children}\n    </HeartbeepContext.Provider>\n  );\n}\n\nexport function useHeartbeep() {\n  const context = useContext(HeartbeepContext);\n  if (!context) {\n    throw new Error(\"useHeartbeep must be used within a HeartbeepProvider\");\n  }\n  return context;\n}\n\n// Auto-track page views on route change\nexport function AutoPageview({ children }: { children?: React.ReactNode }) {\n  const { pageview } = useHeartbeep();\n\n  useEffect(() => {\n    pageview();\n\n    // Listen for route changes (works with Next.js and React Router)\n    const handleRouteChange = () => pageview();\n\n    window.addEventListener(\"popstate\", handleRouteChange);\n    return () => window.removeEventListener(\"popstate\", handleRouteChange);\n  }, [pageview]);\n\n  return <>{children}</>;\n}\n"]}