UNPKG

@adopture/next

Version:

Next.js SDK for Adopture feature adoption tracking with SSR support

3 lines 32.5 kB
"use client"; var Te=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});var Ee=(r,e)=>()=>(r&&(e=r(r=0)),e);import{z as N}from"zod";function ie(){if(typeof window>"u")return null;try{let r=window.__ADOPTURE_CONFIG__;if(r&&typeof r=="object")return r}catch{}return null}function K(r,e,t){let n={...r};return e&&Object.entries(e).forEach(([o,s])=>{s!=null&&(n[o]=s)}),t&&Object.entries(t).forEach(([o,s])=>{s!=null&&(n[o]=s)}),n}var rt,se=Ee(()=>{"use strict";rt=N.object({projectId:N.string().uuid(),projectName:N.string().min(1),apiKey:N.string().regex(/^ad_(live|test)_[a-zA-Z0-9]+$/),environment:N.enum(["live","test"]),apiUrl:N.string().url()})});import{onCLS as ke,onFID as be,onFCP as we,onLCP as De,onTTFB as Ce}from"web-vitals";import{validateFeatureId as de,validateUserId as Y,generateEventId as M,generateSessionId as xe,generateAnonymousId as pe}from"@adopture/sdk-core";se();var ve="https://api.adopture.com",V={CLIENT:{API_URL:"NEXT_PUBLIC_ADOPTURE_API_URL",API_KEY:"NEXT_PUBLIC_ADOPTURE_API_KEY",PROJECT_ID:"NEXT_PUBLIC_ADOPTURE_PROJECT_ID",ENVIRONMENT:"NEXT_PUBLIC_ADOPTURE_ENVIRONMENT",DEBUG:"NEXT_PUBLIC_ADOPTURE_DEBUG"},SERVER:{API_URL:"ADOPTURE_API_URL",API_KEY:"ADOPTURE_API_KEY",PROJECT_ID:"ADOPTURE_PROJECT_ID",ENVIRONMENT:"ADOPTURE_ENVIRONMENT",DEBUG:"ADOPTURE_DEBUG"}};function D(r,e){let t;try{r==="NEXT_PUBLIC_ADOPTURE_API_KEY"?t=process.env.NEXT_PUBLIC_ADOPTURE_API_KEY:r==="NEXT_PUBLIC_ADOPTURE_API_URL"?t=process.env.NEXT_PUBLIC_ADOPTURE_API_URL:r==="NEXT_PUBLIC_ADOPTURE_PROJECT_ID"?t=process.env.NEXT_PUBLIC_ADOPTURE_PROJECT_ID:r==="NEXT_PUBLIC_ADOPTURE_ENVIRONMENT"?t=process.env.NEXT_PUBLIC_ADOPTURE_ENVIRONMENT:r==="NEXT_PUBLIC_ADOPTURE_DEBUG"?t=process.env.NEXT_PUBLIC_ADOPTURE_DEBUG:typeof process<"u"&&process.env&&(t=process.env[r])}catch{t=void 0}return t||e}function H(r={}){let e=D(V.CLIENT.DEBUG),t={apiUrl:D(V.CLIENT.API_URL),apiKey:D(V.CLIENT.API_KEY),projectId:D(V.CLIENT.PROJECT_ID),environment:D(V.CLIENT.ENVIRONMENT),...e!==void 0&&{debug:e==="true"}},n=Object.fromEntries(Object.entries(t).filter(([,a])=>a!==void 0)),o=ie(),i={...{apiUrl:ve,batchSize:50,flushInterval:5e3,retryAttempts:3,retryDelay:1e3,sessionTimeout:30*60*1e3,persistUser:!0,autoTrackSessions:!0,autoTrackLifecycle:!0,lifecycleDeduplication:!0,enableAutoPageTracking:!0,enableWebVitals:!1,enableRouteTracking:!0,routeChangeTimeout:5e3,enableServerSideTracking:!1,bootstrapFromServer:!1,disableInDevelopment:!1,debugMode:!1,eventDeduplication:{enabled:!0,maxCacheSize:1e3,cleanupInterval:6e4,strategies:{adoption:{window:5e3},exposure:{window:864e5},lifecycle:{window:1e4}}},exposureDeduplication:{enabled:!0,sessionBased:!0,storageKey:"adopture_exposures",maxStorageEntries:500,sessionTimeoutMs:24*60*60*1e3,perFeatureLimit:10,globalDailyLimit:1e3,cleanupInterval:5*60*1e3},reactDeduplication:{enabled:!0,strictModeDetection:!0,componentLifecycleTracking:!0,preventEffectLoops:!0,renderCountThreshold:3,effectIdCacheSize:1e3,debugMode:!1},visibility:{enabled:!0,threshold:.5,minDuration:1e3,observeOnce:!0,rootMargin:"0px",trackInSession:!0,autoExpose:!1}}};return o&&(i=K(i,{},o)),r&&(i=K(i,{},r)),Object.keys(n).length>0&&(i=K(i,{},n)),i}function G(r){let e=[];return r.apiKey||e.push("API key is required"),r.apiUrl||e.push("API URL is required"),r.apiKey&&!r.apiKey.match(/^ad_(live|test)_[a-zA-Z0-9]+$/)&&e.push("Invalid API key format. Expected format: ad_live_xxx or ad_test_xxx"),{isValid:e.length===0,errors:e}}function ye(r){let e=r.match(/^ad_(live|test)_(.+)$/);return e&&e[2]?e[2].substring(0,8):null}function q(r){return r.startsWith("ad_live_")?"live":r.startsWith("ad_test_")?"test":null}function W(){return D("NODE_ENV")==="development"}function Ae(){return D("NODE_ENV")==="production"}function Pe(){return typeof window<"u"}function A(){return Date.now()}function Re(r){return new Promise(e=>setTimeout(e,r))}async function ce(r,e=3,t=1e3){let n;for(let o=1;o<=e;o++)try{return await r()}catch(s){if(n=s,o===e)throw n;let i=t*Math.pow(2,o-1);await Re(i)}throw n}function ue(r,e){return Promise.race([r,new Promise((t,n)=>{setTimeout(()=>{n(new Error(`Operation timed out after ${e}ms`))},e)})])}function L(r){let e=["password","token","secret","key","auth","credential"],t={};for(let[n,o]of Object.entries(r)){let s=n.toLowerCase();e.some(a=>s.includes(a))?t[n]="[REDACTED]":typeof o=="object"&&o!==null?t[n]=L(o):t[n]=o}return t}function le(r){return r.split("?")[0].split("#")[0].replace(/\/\[[^\]]+\]/g,"/*")}function Ie(r,e,t){if(!e&&!t)return!1;let n=le(r);return t&&t.length>0?!t.some(o=>ae(n,o)):e&&e.length>0?e.some(o=>ae(n,o)):!1}function ae(r,e){let t=e.replace(/\*/g,".*").replace(/\//g,"\\/");return new RegExp(`^${t}$`).test(r)}var C=class{constructor(e=3e5){this.cache=new Map;this.defaultTTL=e}set(e,t,n){let o=A()+(n??this.defaultTTL);this.cache.set(e,{value:t,expiry:o})}get(e){let t=this.cache.get(e);if(t){if(A()>t.expiry){this.cache.delete(e);return}return t.value}}has(e){return this.get(e)!==void 0}delete(e){return this.cache.delete(e)}clear(){this.cache.clear()}cleanup(){let e=A();for(let[t,n]of this.cache.entries())e>n.expiry&&this.cache.delete(t)}size(){return this.cleanup(),this.cache.size}forEach(e){let t=A();for(let[n,o]of this.cache.entries())t<=o.expiry?e(o.value,n):this.cache.delete(n)}};var j=class{constructor(e={},t){this.config={enabled:!0,persistAcrossSessions:!1,autoUpgrade:!0,resetOnNewSession:!0,storageKey:"adopture_activations",maxCacheSize:1e3,sessionTTL:24*60*60*1e3,debug:!1,...e},this.currentSessionId=t,this.storageKey=this.config.storageKey,this.cache=new C(this.config.sessionTTL),this.config.enabled&&(this.loadFromStorage(),this.config.debug&&console.log("[ADOPTURE] ActivationTracker initialized",{config:this.config,sessionId:this.currentSessionId}))}isActivated(e,t){if(!this.config.enabled)return!1;let n=this.createKey(e,t),o=this.cache.get(n);return o?this.config.resetOnNewSession&&o.sessionId!==this.currentSessionId?(this.cache.delete(n),this.saveToStorage(),!1):(this.config.debug&&console.log("[ADOPTURE] Feature activation check:",{userId:e,featureId:t,isActivated:!0,activatedAt:new Date(o.activatedAt),usageCount:o.usageCount,sessionId:o.sessionId}),!0):!1}markActivated(e,t){if(!this.config.enabled)return;let n=this.createKey(e,t),o=this.cache.get(n),s={userId:e,featureId:t,sessionId:this.currentSessionId,activatedAt:o?.activatedAt||Date.now(),usageCount:(o?.usageCount||0)+1};this.cache.set(n,s),this.saveToStorage(),this.config.debug&&console.log("[ADOPTURE] Feature marked as activated:",{userId:e,featureId:t,state:s,isFirstActivation:!o})}getActivationState(e,t){if(!this.config.enabled)return null;let n=this.createKey(e,t);return this.cache.get(n)||null}clear(){this.cache.clear(),this.clearStorage(),this.config.debug&&console.log("[ADOPTURE] Activation state cleared")}clearUser(e){if(!this.config.enabled)return;let t=[];this.cache.forEach((n,o)=>{n.userId===e&&t.push(o)}),t.forEach(n=>this.cache.delete(n)),this.saveToStorage(),this.config.debug&&console.log("[ADOPTURE] Cleared activations for user:",e,"Count:",t.length)}updateSession(e){this.currentSessionId=e,this.config.resetOnNewSession&&this.clear(),this.config.debug&&console.log("[ADOPTURE] Session updated:",e)}getStats(){let e=new Set,t=new Set,n=0;return this.cache.forEach(o=>{e.add(o.userId),t.add(o.featureId),o.sessionId===this.currentSessionId&&n++}),{totalActivations:this.cache.size(),uniqueUsers:e,uniqueFeatures:t,currentSession:n}}createKey(e,t){return`${e}:${t}`}loadFromStorage(){if(!(typeof window>"u"))try{let t=(this.config.persistAcrossSessions?localStorage:sessionStorage).getItem(this.storageKey);if(t){let n=JSON.parse(t),o=Date.now();Object.entries(n).forEach(([s,i])=>{let a=i;o-a.activatedAt<this.config.sessionTTL&&this.cache.set(s,a)}),this.config.debug&&console.log("[ADOPTURE] Loaded activation state from storage:",this.cache.size,"entries")}}catch(e){this.config.debug&&console.warn("[ADOPTURE] Failed to load activation state from storage:",e)}}saveToStorage(){if(!(typeof window>"u"))try{let e=this.config.persistAcrossSessions?localStorage:sessionStorage,t={};this.cache.forEach((n,o)=>{t[o]=n}),e.setItem(this.storageKey,JSON.stringify(t))}catch(e){this.config.debug&&console.warn("[ADOPTURE] Failed to save activation state to storage:",e)}}clearStorage(){if(!(typeof window>"u"))try{(this.config.persistAcrossSessions?localStorage:sessionStorage).removeItem(this.storageKey)}catch(e){this.config.debug&&console.warn("[ADOPTURE] Failed to clear activation state from storage:",e)}}};var x=class{constructor(){this.config=null;this.isInitialized=!1;this.events=[];this.batchTimer=null;this.userId=null;this.userProperties={};this.isDestroyed=!1;this.routeChangeCache=new C(6e4);this.webVitalsReported=new Set;this.activationTracker=null;this.currentRoute=null;this.routeStartTime=null;this.webVitalsEnabled=!1;this.sessionId=xe()}async init(e,t){if(!(this.isInitialized||this.isDestroyed)){if(W()&&e?.disableInDevelopment){console.log("[ADOPTURE-NEXT] Tracking disabled in development mode");return}try{this.config=H(e),t&&(this.config={...this.config,...t.config},this.userId=t.initialUserId||this.userId,this.userProperties={...this.userProperties,...t.initialUserProperties||{}},this.sessionId=t.sessionId||this.sessionId);let n=G(this.config);if(!n.isValid)throw new Error(`Invalid configuration: ${n.errors.join(", ")}`);if(this.config.apiKey&&!this.config.projectId&&(this.config.projectId="35207190-2644-4230-b088-9ada94638e5d"),this.config.apiKey&&!this.config.environment){let o=q(this.config.apiKey);this.config.environment=o||void 0}this.isInitialized=!0,this.webVitalsEnabled=this.config.enableWebVitals||!1,this.activationTracker=new j({enabled:this.config.activationTracking?.enabled!==!1,persistAcrossSessions:this.config.activationTracking?.persistAcrossSessions||!1,autoUpgrade:this.config.activationTracking?.autoUpgrade!==!1,resetOnNewSession:this.config.activationTracking?.resetOnNewSession!==!1,debug:this.config.debug||!1},this.sessionId),(this.config.debug||this.config.debugMode==="client"||this.config.debugMode==="both")&&console.log("[ADOPTURE-NEXT] Next.js tracker initialized",{config:this.config,sessionId:this.sessionId}),this.initializeBrowserFeatures(),this.startBatchTimer()}catch(n){throw console.error("[ADOPTURE-NEXT] Failed to initialize:",n),n}}}async track(e,t){if(!this.isInitialized||this.isDestroyed){this.config?.debug&&console.warn("[ADOPTURE-NEXT] Track called before initialization or after destruction");return}let n=this.userId||this.getAnonymousId(),o=de(e);if(!o.isValid){console.error("[ADOPTURE-NEXT] Invalid feature ID:",o.error);return}let s=Y(n);if(!s.isValid){console.error("[ADOPTURE-NEXT] Invalid user ID:",s.error);return}let i;this.activationTracker&&this.activationTracker.isActivated(n,e)?i="feature_used":i="feature_activated",this.activationTracker&&this.activationTracker.markActivated(n,e);let a={featureId:e,userId:n,eventType:i,timestamp:A(),metadata:t?L(t):{},sessionId:this.sessionId,eventId:M(),route:this.currentRoute};this.events.push({type:"adoption",...a}),this.config?.debug&&console.log("[ADOPTURE-NEXT] Auto-adoption event queued:",{...a,autoDetected:!0}),this.events.length>=(this.config?.batchSize||50)&&await this.flush()}async trackAdoption(e){if(!this.isInitialized||this.isDestroyed){this.config?.debug&&console.warn("[ADOPTURE-NEXT] Track adoption called before initialization or after destruction");return}let t=e.userId||this.userId||this.getAnonymousId(),n={...e,userId:t,timestamp:e.timestamp||A(),metadata:e.metadata?L(e.metadata):{},sessionId:e.sessionId||this.sessionId,eventId:e.eventId||M(),route:this.currentRoute};this.events.push({type:"adoption",...n}),this.config?.debug&&console.log("[ADOPTURE-NEXT] Adoption event queued:",n),this.events.length>=(this.config?.batchSize||50)&&await this.flush()}async expose(e,t="next-client",n,o){if(!this.isInitialized||this.isDestroyed){this.config?.debug&&console.warn("[ADOPTURE-NEXT] Expose called before initialization or after destruction");return}let s=this.userId||this.getAnonymousId(),i=de(e);if(!i.isValid){console.error("[ADOPTURE-NEXT] Invalid feature ID:",i.error);return}let a={featureId:e,userId:this.userId||this.getAnonymousId(),exposureChannel:t,exposedAt:A(),metadata:n?L(n):{},eventId:M()};this.events.push({type:"exposure",...a,sessionId:this.sessionId,route:this.currentRoute}),this.config?.debug&&console.log("[ADOPTURE-NEXT] Exposure event queued:",a),this.events.length>=(this.config?.batchSize||50)&&await this.flush()}async identify(e,t){if(!this.isInitialized||this.isDestroyed){this.config?.debug&&console.warn("[ADOPTURE-NEXT] Identify called before initialization or after destruction");return}let n=Y(e);if(!n.isValid){console.error("[ADOPTURE-NEXT] Invalid user ID:",n.error);return}this.userId=e,t&&(this.userProperties={...this.userProperties,...t});let o={userId:e,properties:this.userProperties,timestamp:A(),sessionId:this.sessionId,eventId:M()};this.events.push({type:"identify",...o}),this.config?.debug&&console.log("[ADOPTURE-NEXT] User identified:",e)}setUser(e,t){if(console.log("[ADOPTURE-NEXT] setUser() called with:",{userId:e,properties:t,isInitialized:this.isInitialized,isDestroyed:this.isDestroyed}),!this.isInitialized||this.isDestroyed){this.config?.debug&&console.warn("[ADOPTURE-NEXT] SetUser called before initialization or after destruction");return}let n=Y(e);if(!n.isValid){console.error("[ADOPTURE-NEXT] Invalid user ID in setUser():",n.error);return}let o=this.userId;this.userId=e,t&&(this.userProperties={...this.userProperties,...t}),console.log("[ADOPTURE-NEXT] User successfully updated:",{previousUserId:o,newUserId:this.userId,properties:this.userProperties})}async trackPageView(e,t){this.currentRoute=e}async trackRouteChange(e,t,n){this.currentRoute=t,this.routeStartTime=A()}async trackWebVital(e,t,n){}async flush(){if(!this.isInitialized||this.events.length===0||this.isDestroyed)return;let e=[...this.events];this.events=[],this.config?.debug&&console.log(`[ADOPTURE-NEXT] Flushing ${e.length} events`);try{await this.sendEvents(e),this.config?.debug&&console.log("[ADOPTURE-NEXT] Events sent successfully")}catch(t){this.config?.debug&&console.error("[ADOPTURE-NEXT] Failed to flush events:",t),this.events.unshift(...e)}}async destroy(){this.isDestroyed||(this.isDestroyed=!0,this.batchTimer&&(clearInterval(this.batchTimer),this.batchTimer=null),await this.flush(),this.config?.debug&&console.log("[ADOPTURE-NEXT] Next.js tracker destroyed"))}isReady(){return this.isInitialized&&!this.isDestroyed}getConfig(){return this.config}getCurrentUserId(){return this.userId}getSessionId(){return this.sessionId}initializeBrowserFeatures(){if(!(typeof window>"u")){if(this.webVitalsEnabled){let e=t=>{this.trackWebVital(t.name,t.value,{id:t.id,delta:t.delta})};ke(e),be(e),we(e),De(e),Ce(e)}this.currentRoute=window.location.pathname,this.routeStartTime=A(),this.config?.enableAutoPageTracking&&this.trackPageView(this.currentRoute,{referrer:document.referrer,userAgent:navigator.userAgent})}}async sendEvents(e){if(!this.config)throw new Error("Configuration not loaded");let t=e.map(n=>this.sendSingleEvent(n));await Promise.all(t)}async sendSingleEvent(e){if(!this.config)throw new Error("Configuration not loaded");let t=this.config.projectId||"35207190-2644-4230-b088-9ada94638e5d",n=e.featureId,o=e.userId||this.userId||this.getAnonymousId(),s=e.sessionId||this.sessionId;if(!n||!o){this.config.debug&&console.warn("[ADOPTURE-NEXT] Skipping event - missing featureId or userId:",{featureId:n,userId:o,event:e});return}let i={projectId:t,featureId:n,userId:o,eventType:e.eventType||"feature_exposed",sessionId:s,metadata:e.metadata||{}};await ue(ce(async()=>{this.config?.debug&&console.log("[ADOPTURE-NEXT] Sending tRPC payload:",JSON.stringify(i,null,2));let c=await fetch(`${this.config.apiUrl}/trpc/featureAdoption.trackEvent`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`,"User-Agent":"adopture-next-client/0.1.0"},body:JSON.stringify(i)});if(!c.ok){let p=await c.text();throw this.config?.debug&&console.error("[ADOPTURE-NEXT] tRPC Error Response:",{status:c.status,body:p,sentPayload:i}),new Error(`HTTP ${c.status}: ${p}`)}return c.json()},this.config.retryAttempts,this.config.retryDelay),this.config.routeChangeTimeout||1e4)}getAnonymousId(){if(typeof window<"u"){let e=window.localStorage?.getItem("adopture_anonymous_id");if(!e){e=pe();try{window.localStorage?.setItem("adopture_anonymous_id",e)}catch{}}return e}return pe()}startBatchTimer(){this.batchTimer&&clearInterval(this.batchTimer);let e=this.config?.flushInterval||5e3;this.batchTimer=setInterval(()=>{this.events.length>0&&this.flush()},e)}};function Ue(r){return new x}import{createContext as Oe,useContext as Se,useEffect as R,useState as b,useCallback as fe,useRef as F}from"react";import{usePathname as Ne}from"next/navigation";import{generateSessionId as ge}from"@adopture/sdk-core";import{Fragment as X,jsx as U}from"react/jsx-runtime";var Z=null;function Q(){return Z||(Z=Oe({tracker:null,isInitialized:!1,isLoading:!1,error:null,config:null})),Z}function _e({config:r,children:e,fallback:t,loadingComponent:n}){let[o,s]=b(null),[i,a]=b(!1),[c,p]=b(!0),[f,h]=b(null),m=F(null),S=F(!1),g=Ne(),_=F(null),B=fe(async l=>{if(!S.current){S.current=!0;try{p(!0),h(null);let u=new x;m.current=u,await u.init(r||{},l),s(u),a(!0)}catch(u){let d=u instanceof Error?u:new Error("Failed to initialize tracker");h(d),console.error("[ADOPTURE-PROVIDER] Initialization failed:",d)}finally{p(!1)}}},[r]);R(()=>{let l=document.getElementById("adopture-bootstrap-data"),u;if(l)try{u=JSON.parse(l.textContent||"{}")}catch{console.warn("[ADOPTURE-PROVIDER] Failed to parse bootstrap data")}if(typeof window<"u"){let d=localStorage.getItem("demo-current-user");if(d){console.log("[ADOPTURE-PROVIDER] Found saved user in localStorage:",d);let v={};try{let P=[{id:"demo-user-123",email:"alice@techstartup.com",name:"Alice Johnson",plan:"pro",role:"admin",company:"Tech Startup Inc",signupDate:"2024-01-15",features:["dashboard","analytics","reporting","export"]},{id:"demo-user-456",email:"bob@enterprise.com",name:"Bob Smith",plan:"enterprise",role:"manager",company:"Enterprise Corp",signupDate:"2024-02-01",features:["dashboard","analytics","advanced-reports","api-access"]},{id:"demo-user-789",email:"carol@smallbiz.com",name:"Carol Davis",plan:"free",role:"user",company:"Small Business LLC",signupDate:"2024-03-10",features:["dashboard","basic-analytics"]},{id:"demo-user-345",email:"david@agency.com",name:"David Wilson",plan:"pro",role:"user",company:"Creative Agency",signupDate:"2024-04-20",features:["dashboard","analytics","reporting"]}].find(me=>me.id===d);P&&(v={email:P.email,name:P.name,plan:P.plan,role:P.role,company:P.company,signupDate:P.signupDate,features:P.features,demoUser:!0})}catch(y){console.warn("[ADOPTURE-PROVIDER] Could not load user properties:",y)}u||(u={config:r||{},sessionId:ge(),timestamp:Date.now()}),u.initialUserId=d,u.initialUserProperties=v,console.log("[ADOPTURE-PROVIDER] Bootstrap data with saved user:",{userId:d,properties:v})}}B(u)},[B]),R(()=>{if(!o||!i)return;let l=g,u=_.current;u&&u!==l?o.trackRouteChange(u,l,{timestamp:Date.now(),userAgent:navigator.userAgent}):u||o.trackPageView(l,{timestamp:Date.now(),userAgent:navigator.userAgent,referrer:document.referrer}),_.current=l},[g,o,i]),R(()=>{if(!o||!i)return;let l=u=>{console.log("[ADOPTURE-PROVIDER] Received user change event:",u.detail);let{userId:d,properties:v}=u.detail;m.current&&d?(console.log("[ADOPTURE-PROVIDER] Calling setUser with:",{userId:d,properties:v}),m.current.setUser(d,v)):console.warn("[ADOPTURE-PROVIDER] Cannot update user - missing tracker or userId:",{hasTracker:!!m.current,userId:d})};return window.addEventListener("adopture-user-change",l),()=>{window.removeEventListener("adopture-user-change",l)}},[o,i]),R(()=>()=>{m.current&&(m.current.destroy(),m.current=null)},[]),R(()=>{if(!o||!i)return;let l=()=>{};return document.addEventListener("visibilitychange",l),()=>{document.removeEventListener("visibilitychange",l)}},[o,i,g]);let $={tracker:o,isInitialized:i,isLoading:c,error:f,config:r||null};if(c&&n)return U(X,{children:n});if(f&&t)return U(X,{children:t});let E=Q();return U(E.Provider,{value:$,children:e})}function Ve({config:r,children:e,fallback:t,loadingComponent:n}){let[o,s]=b(null),[i,a]=b(!1),[c,p]=b(!0),[f,h]=b(null),m=F(null),S=F(!1),g=null;try{let{useRouter:E}=Te("next/router");g=E()}catch{console.warn("[ADOPTURE-PAGES-PROVIDER] next/router not available - this component should only be used in Pages Router projects")}let _=fe(async E=>{if(!S.current){S.current=!0;try{p(!0),h(null);let l=new x;m.current=l,await l.init(r||{},E),s(l),a(!0)}catch(l){let u=l instanceof Error?l:new Error("Failed to initialize tracker");h(u),console.error("[ADOPTURE-PAGES-PROVIDER] Initialization failed:",u)}finally{p(!1)}}},[r]);R(()=>{let E=document.getElementById("adopture-bootstrap-data"),l;if(E)try{l=JSON.parse(E.textContent||"{}")}catch{console.warn("[ADOPTURE-PAGES-PROVIDER] Failed to parse bootstrap data")}if(typeof window<"u"){let u=localStorage.getItem("demo-current-user");if(u){console.log("[ADOPTURE-PAGES-PROVIDER] Found saved user in localStorage:",u);let d={};try{let y=[{id:"demo-user-123",email:"alice@techstartup.com",name:"Alice Johnson",plan:"pro",role:"admin",company:"Tech Startup Inc",signupDate:"2024-01-15",features:["dashboard","analytics","reporting","export"]},{id:"demo-user-456",email:"bob@enterprise.com",name:"Bob Smith",plan:"enterprise",role:"manager",company:"Enterprise Corp",signupDate:"2024-02-01",features:["dashboard","analytics","advanced-reports","api-access"]},{id:"demo-user-789",email:"carol@smallbiz.com",name:"Carol Davis",plan:"free",role:"user",company:"Small Business LLC",signupDate:"2024-03-10",features:["dashboard","basic-analytics"]},{id:"demo-user-345",email:"david@agency.com",name:"David Wilson",plan:"pro",role:"user",company:"Creative Agency",signupDate:"2024-04-20",features:["dashboard","analytics","reporting"]}].find(P=>P.id===u);y&&(d={email:y.email,name:y.name,plan:y.plan,role:y.role,company:y.company,signupDate:y.signupDate,features:y.features,demoUser:!0})}catch(v){console.warn("[ADOPTURE-PAGES-PROVIDER] Could not load user properties:",v)}l||(l={config:r||{},sessionId:ge(),timestamp:Date.now()}),l.initialUserId=u,l.initialUserProperties=d,console.log("[ADOPTURE-PAGES-PROVIDER] Bootstrap data with saved user:",{userId:u,properties:d})}}_(l)},[_]),R(()=>{if(!o||!i||!g)return;let E=d=>{o.track("route-start",{url:d,timestamp:Date.now()})},l=d=>{o.trackPageView(d,{timestamp:Date.now(),userAgent:navigator.userAgent})},u=(d,v)=>{o.track("route-error",{url:v,error:d.message||"Route change error",timestamp:Date.now()})};return g.events.on("routeChangeStart",E),g.events.on("routeChangeComplete",l),g.events.on("routeChangeError",u),()=>{g.events.off("routeChangeStart",E),g.events.off("routeChangeComplete",l),g.events.off("routeChangeError",u)}},[o,i,g]),R(()=>{if(!o||!i)return;let E=l=>{console.log("[ADOPTURE-PAGES-PROVIDER] Received user change event:",l.detail);let{userId:u,properties:d}=l.detail;m.current&&u?(console.log("[ADOPTURE-PAGES-PROVIDER] Calling setUser with:",{userId:u,properties:d}),m.current.setUser(u,d)):console.warn("[ADOPTURE-PAGES-PROVIDER] Cannot update user - missing tracker or userId:",{hasTracker:!!m.current,userId:u})};return window.addEventListener("adopture-user-change",E),()=>{window.removeEventListener("adopture-user-change",E)}},[o,i]),R(()=>()=>{m.current&&(m.current.destroy(),m.current=null)},[]);let B={tracker:o,isInitialized:i,isLoading:c,error:f,config:r||null};if(c&&n)return U(X,{children:n});if(f&&t)return U(X,{children:t});let $=Q();return U($.Provider,{value:B,children:e})}function w(){let r=Q(),e=Se(r);if(!e)throw new Error("useAdopture must be used within an AdoptureProvider");return e}function Le(){let{tracker:r}=w();return r}function Fe({data:r}){return U("script",{id:"adopture-bootstrap-data",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify(r)}})}import{useCallback as T,useEffect as he,useRef as ee}from"react";function I(){let{tracker:r,isInitialized:e,isLoading:t,error:n}=w(),o=T(async(a,c)=>{if(!r||!e){console.warn("[ADOPTURE-HOOK] Tracker not ready, ignoring track call");return}await r.track(a,c)},[r,e]),s=T(async(a,c,p,f)=>{if(!r||!e){console.warn("[ADOPTURE-HOOK] Tracker not ready, ignoring expose call");return}await r.expose(a,c,p,f)},[r,e]),i=T(async(a,c)=>{if(!r||!e){console.warn("[ADOPTURE-HOOK] Tracker not ready, ignoring identify call");return}await r.identify(a,c)},[r,e]);return{tracker:r,track:o,expose:s,identify:i,isInitialized:e,isLoading:t,error:n}}function ze(){let{tracker:r,isInitialized:e}=w();return{track:T(async(n,o)=>{if(!r||!e){console.warn("[ADOPTURE-HOOK] Tracker not ready, ignoring track call");return}await r.track(n,o)},[r,e]),isReady:e&&r!==null}}function Be(){let{tracker:r,isInitialized:e}=w();return{expose:T(async(n,o,s,i)=>{if(!r||!e){console.warn("[ADOPTURE-HOOK] Tracker not ready, ignoring expose call");return}await r.expose(n,o,s,i)},[r,e]),isReady:e&&r!==null}}function Ke(){let{tracker:r,isInitialized:e}=w();return{identify:T(async(n,o)=>{if(!r||!e){console.warn("[ADOPTURE-HOOK] Tracker not ready, ignoring identify call");return}await r.identify(n,o)},[r,e]),isReady:e&&r!==null}}function je(){let{tracker:r,isInitialized:e}=w();return{trackAdoption:T(async n=>{if(!r||!e){console.warn("[ADOPTURE-HOOK] Tracker not ready, ignoring trackAdoption call");return}console.warn("[ADOPTURE-HOOK] useTrackAdoption is deprecated. Use useTrack() instead for automatic activation/usage detection."),await r.trackAdoption(n)},[r,e]),isReady:e&&r!==null}}function Me(r,e){let{track:t,expose:n}=I(),o=ee(!1);he(()=>{if(!o.current)return o.current=!0,n(r,e?.exposureChannel||"component",{component:r,timestamp:Date.now(),...e?.metadata}),()=>{e?.trackUnmount===!0&&t(`${r}:unmount`,{component:r,timestamp:Date.now(),...e?.metadata})}},[r,e,t,n])}function O(r){let{track:e}=I(),t=T((a,c)=>{e(`${r}:click`,{elementId:a,interaction:"click",timestamp:Date.now(),...c})},[r,e]),n=T((a,c)=>{e(`${r}:form_submit`,{formId:a,interaction:"form_submit",timestamp:Date.now(),...c})},[r,e]),o=T((a,c,p)=>{e(`${r}:input`,{inputId:a,interaction:"input",hasValue:!!c,timestamp:Date.now(),...p})},[r,e]),s=T((a,c)=>{e(`${r}:scroll`,{scrollPercentage:a,interaction:"scroll",timestamp:Date.now(),...c})},[r,e]),i=T((a,c)=>{e(`${r}:error`,{errorMessage:a.message,errorName:a.name,errorStack:a.stack,interaction:"error",timestamp:Date.now(),...c})},[r,e]);return{trackClick:t,trackFormSubmit:n,trackInput:o,trackScroll:s,trackError:i}}function te(r,e){let{expose:t}=I(),n=ee(null),o=ee(!1),s=T(i=>{n.current&&(n.current.disconnect(),n.current=null),i&&(n.current=new IntersectionObserver(a=>{a.forEach(c=>{c.isIntersecting&&(!o.current||!e?.trackOnce)&&(t(r,"visibility",{intersectionRatio:c.intersectionRatio,boundingClientRect:c.boundingClientRect,timestamp:Date.now()}),o.current=!0)})},{threshold:e?.threshold??.5,rootMargin:e?.rootMargin??"0px"}),n.current.observe(i))},[r,t,e]);return he(()=>()=>{n.current&&n.current.disconnect()},[]),s}function Xe(r){let{track:e}=I(),t=T((s,i,a)=>{let c=Date.now()-i;e(`${r}:timing`,{name:s,duration:c,timestamp:Date.now(),...a})},[r,e]),n=T((s,i)=>{e(`${r}:error`,{errorMessage:s.message,errorName:s.name,errorStack:s.stack,timestamp:Date.now(),...i})},[r,e]),o=T(s=>{let i=Date.now();return{end:a=>{t(s,i,a)}}},[t]);return{trackTiming:t,trackError:n,createTimer:o}}import*as J from"react";import{useEffect as z,useRef as re,useState as Je}from"react";import{Fragment as oe,jsx as k,jsxs as Qe}from"react/jsx-runtime";function $e({featureId:r,children:e,exposureChannel:t="component",metadata:n,trackVisibility:o=!0,visibilityOptions:s,trackInteractions:i=!1,className:a}){let{expose:c}=I(),{trackClick:p}=O(r),f=te(r,o?s:void 0),h=re(null),m=g=>{h.current=g,o&&g&&f(g)};return z(()=>{o||c(r,t,{timestamp:Date.now(),...n})},[r,t,n,c,o]),k("div",{ref:m,className:a,onClick:g=>{i&&p(g.currentTarget.id||void 0,{timestamp:Date.now(),...n})},"data-adopture-feature":r,children:e})}function He({featureId:r,children:e,metadata:t,onClick:n,as:o="div",...s}){let{trackClick:i}=O(r);return J.createElement(o,{...s,onClick:c=>{i(c.currentTarget.id||void 0,{timestamp:Date.now(),...t}),n?.(c)},"data-adopture-track":r},e)}function Ge({featureId:r,children:e,metadata:t,onSubmit:n,trackInputs:o=!1,...s}){let{trackFormSubmit:i,trackInput:a}=O(r);return k("form",{...s,onSubmit:f=>{i(f.currentTarget.id||void 0,{timestamp:Date.now(),...t}),n?.(f)},onInput:f=>{if(o){let h=f.target;a(h.id||h.name||void 0,h.value,{timestamp:Date.now(),inputType:h.type,...t})}},"data-adopture-track":r,children:e})}function qe({featureId:r,condition:e,children:t,fallback:n,exposureChannel:o="conditional",metadata:s,trackExposure:i=!0}){let{expose:a}=I(),[c,p]=Je(()=>typeof e=="function"?e():e);return z(()=>{let f=typeof e=="function"?e():e;p(f),i&&a(r,o,{rendered:f,timestamp:Date.now(),...s})},[e,r,o,s,a,i]),c?k(oe,{children:t}):k(oe,{children:n||null})}function We({route:r,metadata:e,trackOnMount:t=!0}){let{tracker:n}=I();return z(()=>{if(t&&n){let o=r||(typeof window<"u"?window.location.pathname:"");n.trackPageView(o,{timestamp:Date.now(),userAgent:typeof navigator<"u"?navigator.userAgent:"",...e})}},[r,e,t,n]),null}function Ye({featureId:r,thresholds:e=[25,50,75,100],metadata:t,debounceMs:n=500}){let{trackScroll:o}=O(r),s=re(new Set),i=re(null);return z(()=>{let a=()=>{i.current&&clearTimeout(i.current),i.current=setTimeout(()=>{let c=window.pageYOffset||document.documentElement.scrollTop,p=document.documentElement.scrollHeight-window.innerHeight,f=Math.round(c/p*100);e.forEach(h=>{f>=h&&!s.current.has(h)&&(s.current.add(h),o(f,{threshold:h,scrollTop:c,scrollHeight:p,timestamp:Date.now(),...t}))})},n)};return window.addEventListener("scroll",a,{passive:!0}),()=>{window.removeEventListener("scroll",a),i.current&&clearTimeout(i.current)}},[r,e,t,n,o]),null}var ne=class extends J.Component{constructor(t){super(t);this.trackError=()=>{};this.setTrackError=t=>{this.trackError=t};this.retry=()=>{this.setState({hasError:!1,error:null})};this.state={hasError:!1,error:null}}static getDerivedStateFromError(t){return{hasError:!0,error:t}}componentDidCatch(t,n){this.trackError(t,{componentStack:n.componentStack,errorBoundary:this.props.featureId,timestamp:Date.now(),...this.props.metadata}),this.props.onError?.(t)}render(){if(this.state.hasError&&this.state.error){let t=this.props.fallback;return t?k(t,{error:this.state.error,retry:this.retry}):Qe("div",{role:"alert","data-adopture-error":this.props.featureId,children:[k("h2",{children:"Something went wrong."}),k("button",{onClick:this.retry,children:"Try again"})]})}return k(Ze,{onSetTrackError:this.setTrackError,featureId:this.props.featureId,children:this.props.children})}};function Ze({children:r,onSetTrackError:e,featureId:t}){let{trackError:n}=O(t);return z(()=>{e(n)},[n,e]),k(oe,{children:r})}import{generateUUID as jt,generateEventId as Mt,generateSessionId as Xt,generateAnonymousId as Jt,generateShortId as $t,isValidUUID as Ht,isValidEventId as Gt,isCryptoAvailable as qt,getUUIDGenerationInfo as Wt}from"@adopture/sdk-core";export{Fe as AdoptureBootstrap,qe as AdoptureConditionalFeature,ne as AdoptureErrorBoundary,$e as AdoptureFeature,We as AdopturePageView,Ve as AdopturePagesProvider,_e as AdoptureProvider,Ye as AdoptureScrollTracker,He as AdoptureTrackClick,Ge as AdoptureTrackForm,x as NextClientTracker,C as TTLCache,Ue as createClientTracker,q as extractEnvironmentFromApiKey,ye as extractProjectIdFromApiKey,le as extractRoute,Jt as generateAnonymousId,Mt as generateEventId,Xt as generateSessionId,$t as generateShortId,jt as generateUUID,Wt as getUUIDGenerationInfo,Pe as isClient,qt as isCryptoAvailable,W as isDevelopment,Ae as isProduction,Gt as isValidEventId,Ht as isValidUUID,H as loadClientConfig,Ie as shouldExcludeRoute,w as useAdopture,Le as useAdoptureTracker,I as useAdoptureTracking,Me as useComponentTracking,Be as useExpose,Ke as useIdentify,O as useInteractionTracking,Xe as usePerformanceTracking,ze as useTrack,je as useTrackAdoption,te as useVisibilityTracking,G as validateConfig}; //# sourceMappingURL=index.mjs.map