@trillboards/connect 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- var TrillboardsConnect=(()=>{var Lt=Object.defineProperty,Mt=Object.defineProperties;var zt=Object.getOwnPropertyDescriptors;var W=Object.getOwnPropertySymbols;var $t=Object.prototype.hasOwnProperty,Ut=Object.prototype.propertyIsEnumerable;var Z=(t,e,r)=>e in t?Lt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,y=(t,e)=>{for(var r in e||(e={}))$t.call(e,r)&&Z(t,r,e[r]);if(W)for(var r of W(e))Ut.call(e,r)&&Z(t,r,e[r]);return t},k=(t,e)=>Mt(t,zt(e));var P=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var it=P((me,nt)=>{var U="https://api.trillboards.com/v1/partner",A={UNREGISTERED:"unregistered",REGISTERING:"registering",REGISTERED:"registered",ONLINE:"online",OFFLINE:"offline",ERROR:"error"};function Vt(t){if(!t||typeof t!="string")throw new Error("deviceId must be a non-empty string");let e=2166136261;for(let a=0;a<t.length;a++)e^=t.charCodeAt(a),e=Math.imul(e,16777619);let r=(e>>>0).toString(16).padStart(8,"0"),n=16777619;for(let a=0;a<t.length;a++)n^=t.charCodeAt(a)*(a+1),n=Math.imul(n,2166136261);let i=(n>>>0).toString(16).padStart(8,"0");return`SDK_${r}${i}`}function tt(){let t={sdk_version:"1.0.0",timestamp:new Date().toISOString()};return typeof navigator!="undefined"&&(t.user_agent=navigator.userAgent,t.platform=navigator.platform,t.language=navigator.language,t.online=navigator.onLine,t.hardware_concurrency=navigator.hardwareConcurrency),typeof screen!="undefined"&&(t.screen_width=screen.width,t.screen_height=screen.height,t.pixel_ratio=typeof devicePixelRatio!="undefined"?devicePixelRatio:1,t.color_depth=screen.colorDepth),t}async function et(t,e,r={}){if(!t)throw new Error("apiKey is required for device registration");if(!e)throw new Error("deviceId is required for device registration");let n=tt(),i={};n.screen_width&&(i.width=n.screen_width,i.height=n.screen_height);let a={device_id:e,device_type:r.device_type||"digital_signage",name:r.name||`SDK Device: ${e}`,display:y(y({},i),r.display),location:r.location||{},custom_metadata:y(y({},n),r.custom)},u;try{u=await fetch(`${U}/device`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`,"X-SDK-Version":"1.0.0"},body:JSON.stringify(a)})}catch(o){let c=new Error(`Network error during device registration: ${o.message}. If running from a browser, ensure your domain can reach api.trillboards.com. Test with: fetch("https://api.trillboards.com/v1/partner/ping").then(r => r.json()).then(console.log)`);throw c.statusCode=0,c.phase="device_registration",c.diagnosticUrl=`${U}/ping`,c}if(!u.ok){let o=await u.json().catch(()=>({})),c=new Error(o.message||`Device registration failed: ${u.status}`);throw c.statusCode=u.status,c.response=o,c}return u.json()}function rt(t,e=6e4,r={}){if(!t)throw new Error("fingerprint is required for heartbeat");let n=r.maxRetries||10,i=r.retryBackoff||1.5,a=r.onSuccess||(()=>{}),u=r.onError||(()=>{}),o=null,c=0,d=0,s=null,l=!1,h=e;async function f(){try{let b=await fetch(`${U}/device/${encodeURIComponent(t)}/heartbeat`,{method:"POST",headers:{"Content-Type":"application/json","X-SDK-Version":"1.0.0"},body:JSON.stringify({timestamp:new Date().toISOString(),total_beats:d})});if(!b.ok)throw new Error(`Heartbeat failed: HTTP ${b.status}`);let v=await b.json();return c=0,h=e,d++,s=new Date,a({beat:d,status:v.status||"online",last_seen_at:v.last_seen_at,timestamp:s.toISOString()}),v}catch(b){return c++,u({error:b.message,consecutiveFailures:c,willRetry:c<n}),c>=n?(console.error(`[Trillboards SDK] Heartbeat stopped after ${n} consecutive failures`),T(),null):(h=Math.min(e*Math.pow(i,c),e*5),null)}}function S(){l&&(o=setTimeout(async()=>{await f(),S()},h))}function I(){l||(l=!0,c=0,h=e,f().then(()=>{S()}))}function T(){l=!1,o&&(clearTimeout(o),o=null)}function D(){return{running:l,totalBeats:d,lastBeatAt:s?s.toISOString():null,consecutiveFailures:c,currentIntervalMs:h}}return{start:I,stop:T,getStatus:D,sendBeat:f}}var V=class{constructor(e){this.deviceId=e,this.status=A.UNREGISTERED,this.fingerprint=null,this.screenId=null,this.embedUrl=null,this.registrationData=null,this.heartbeatController=null,this.listeners={},this.lastError=null}on(e,r){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(r)}off(e,r){this.listeners[e]&&(this.listeners[e]=this.listeners[e].filter(n=>n!==r))}emit(e,r){this.listeners[e]&&this.listeners[e].forEach(n=>{try{n(r)}catch(i){console.error(`[Trillboards SDK] Event listener error for '${e}':`,i)}})}setStatus(e){let r=this.status;this.status=e,r!==e&&this.emit("status_change",{from:r,to:e,deviceId:this.deviceId,timestamp:new Date().toISOString()})}async register(e,r={},n={}){this.setStatus(A.REGISTERING);try{let i=await et(e,this.deviceId,r);this.fingerprint=i.fingerprint,this.screenId=i.screen_id,this.embedUrl=i.embed_url,this.registrationData=i,this.lastError=null,this.setStatus(A.REGISTERED),this.emit("registered",i);let a=n.interval||6e4;return this.heartbeatController=rt(this.fingerprint,a,{onSuccess:u=>{this.setStatus(A.ONLINE),this.emit("heartbeat",u)},onError:u=>{u.willRetry||this.setStatus(A.OFFLINE),this.emit("heartbeat_error",u)},maxRetries:n.maxRetries||10,retryBackoff:n.retryBackoff||1.5}),this.heartbeatController.start(),i}catch(i){throw this.lastError=i,this.setStatus(A.ERROR),this.emit("error",{phase:"registration",error:i.message,statusCode:i.statusCode}),i}}destroy(){this.heartbeatController&&(this.heartbeatController.stop(),this.heartbeatController=null),this.setStatus(A.OFFLINE),this.listeners={}}getState(){return{deviceId:this.deviceId,status:this.status,fingerprint:this.fingerprint,screenId:this.screenId,embedUrl:this.embedUrl,heartbeat:this.heartbeatController?this.heartbeatController.getStatus():null,lastError:this.lastError?this.lastError.message:null}}};nt.exports={registerDevice:et,generateFingerprint:Vt,startHeartbeat:rt,DeviceTracker:V,DeviceStatus:A,collectDeviceMetadata:tt}});var lt=P((ye,ct)=>{var Gt="https://api.trillboards.com/v1/partner";function Ht(t){if(!t||typeof t!="string")return null;let e;if(typeof DOMParser!="undefined")e=new DOMParser().parseFromString(t,"text/xml");else return{mediaFiles:[],tracking:{},impressionUrls:[],errorUrls:[],raw:t};let r={mediaFiles:[],tracking:{},impressionUrls:[],errorUrls:[],clickThrough:null,clickTracking:[],duration:0};e.querySelectorAll("Impression").forEach(s=>{let l=(s.textContent||"").trim();l&&r.impressionUrls.push(l)}),e.querySelectorAll("Error").forEach(s=>{let l=(s.textContent||"").trim();l&&r.errorUrls.push(l)}),e.querySelectorAll("MediaFile").forEach(s=>{r.mediaFiles.push({url:(s.textContent||"").trim(),type:s.getAttribute("type")||"video/mp4",width:parseInt(s.getAttribute("width"))||0,height:parseInt(s.getAttribute("height"))||0,bitrate:parseInt(s.getAttribute("bitrate"))||0,delivery:s.getAttribute("delivery")||"progressive"})}),e.querySelectorAll("Tracking").forEach(s=>{let l=s.getAttribute("event"),h=(s.textContent||"").trim();l&&h&&(r.tracking[l]||(r.tracking[l]=[]),r.tracking[l].push(h))});let o=e.querySelector("ClickThrough");o&&(r.clickThrough=(o.textContent||"").trim()),e.querySelectorAll("ClickTracking").forEach(s=>{let l=(s.textContent||"").trim();l&&r.clickTracking.push(l)});let d=e.querySelector("Duration");if(d){let l=(d.textContent||"").trim().split(":");l.length===3&&(r.duration=parseInt(l[0])*3600+parseInt(l[1])*60+parseFloat(l[2]))}return r}function G(t){return new Promise(e=>{if(!t){e(!1);return}let r=t.includes("?")?"&":"?",n=`${t}${r}cb=${Date.now()}`;if(typeof Image!="undefined"){let i=new Image;i.onload=()=>e(!0),i.onerror=()=>e(!1),i.src=n,setTimeout(()=>e(!1),5e3)}else fetch(n,{method:"GET",mode:"no-cors"}).then(()=>e(!0)).catch(()=>e(!1))})}async function st(t,e={}){if(!t)throw new Error("fingerprint is required to fetch ads");let r={Accept:"application/json","X-SDK-Version":"1.0.0"};e.etag&&(r["If-None-Match"]=e.etag);let n=await fetch(`${Gt}/device/${encodeURIComponent(t)}/ads`,{method:"GET",headers:r});if(n.status===304)return{ads:[],unchanged:!0,etag:e.etag};if(!n.ok){let a=await n.json().catch(()=>({})),u=new Error(a.message||`Failed to fetch ads: ${n.status}`);throw u.statusCode=n.status,u}let i=await n.json();return{ads:i.ads||[],settings:i.settings||{},cache_until:i.cache_until,etag:i.etag||null,device:i.device||{},unchanged:!1}}function ot(t,e,r={}){if(!t||!t.url)throw new Error("Valid ad object with url is required");let n=typeof e=="string"?document.querySelector(e):e;if(!n)throw new Error("Container element not found");let i=r.muted!==!1,a=r.autoplay!==!1,u=r.objectFit||"cover",o=r.onStart||(()=>{}),c=r.onComplete||(()=>{}),d=r.onError||(()=>{}),s=null,l=null,h=null,f=!1;return n.innerHTML="",n.style.position=n.style.position||"relative",n.style.overflow="hidden",t.type==="video"?(s=document.createElement("video"),s.src=t.url,s.muted=i,s.autoplay=a,s.playsInline=!0,s.setAttribute("playsinline",""),s.setAttribute("webkit-playsinline",""),s.style.width="100%",s.style.height="100%",s.style.objectFit=u,s.style.display="block",s.addEventListener("play",()=>{f||(h=Date.now(),o({ad:t,type:"video",timestamp:new Date().toISOString()}))}),s.addEventListener("ended",()=>{f||c({ad:t,type:"video",duration:h?(Date.now()-h)/1e3:0,completed:!0,timestamp:new Date().toISOString()})}),s.addEventListener("error",S=>{f||d({ad:t,type:"video",error:S.message||"Video playback error",timestamp:new Date().toISOString()})}),n.appendChild(s)):(s=document.createElement("img"),s.src=t.url,s.alt=t.title||"Advertisement",s.style.width="100%",s.style.height="100%",s.style.objectFit=u,s.style.display="block",s.addEventListener("load",()=>{if(!f){h=Date.now(),o({ad:t,type:"image",timestamp:new Date().toISOString()});let S=(t.duration||r.imageDuration||8)*1e3;l=setTimeout(()=>{f||c({ad:t,type:"image",duration:t.duration||r.imageDuration||8,completed:!0,timestamp:new Date().toISOString()})},S)}}),s.addEventListener("error",()=>{f||d({ad:t,type:"image",error:"Image failed to load",timestamp:new Date().toISOString()})}),n.appendChild(s)),{pause(){s&&s.pause&&s.pause()},resume(){s&&s.play&&s.play().catch(()=>{})},destroy(){f=!0,l&&(clearTimeout(l),l=null),s&&(s.pause&&s.pause(),s.parentNode&&s.parentNode.removeChild(s),s=null)},getPlaybackState(){return s?t.type==="video"?{state:s.paused?"paused":"playing",currentTime:s.currentTime,duration:s.duration,muted:s.muted}:{state:h?"showing":"loading",elapsed:h?(Date.now()-h)/1e3:0}:{state:"destroyed"}}}}async function at(t,e,r={}){if(!t||!t.id)throw new Error("Valid ad object with id is required");let n={impression_url:!1,pixel_url:!1,vast_impressions:[]};if(t.impression_url)try{let i=new URL(t.impression_url);r.duration&&i.searchParams.set("duration",String(r.duration)),r.completed!==void 0&&i.searchParams.set("completed",String(r.completed));let a=await fetch(i.toString(),{method:"GET",mode:"no-cors"});n.impression_url=!0}catch(i){n.impression_url=!1}if(t.pixel_url&&(n.pixel_url=await G(t.pixel_url)),t.vast_data&&t.vast_data.impressionUrls)for(let i of t.vast_data.impressionUrls){let a=await G(i);n.vast_impressions.push({url:i,fired:a})}return n}function Jt(t){if(!t.fingerprint)throw new Error("fingerprint is required for ad rotation");let e=t.intervalSeconds||60,r=t.refreshMinutes||5,n=t.onAdStart||(()=>{}),i=t.onAdComplete||(()=>{}),a=t.onError||(()=>{}),u=t.onImpression||(()=>{}),o=[],c={},d=0,s=null,l=null,h=null,f=!1,S=null,I=0,T=0;async function D(){try{let p=await st(t.fingerprint,{etag:S});return p.unchanged||(o=p.ads,c=p.settings||{},S=p.etag,d=0),o}catch(p){return a({phase:"fetch",error:p.message}),o}}function b(){if(o.length===0)return null;let p=o[d%o.length];return d=(d+1)%o.length,p}async function v(){if(!f)return;s&&(s.destroy(),s=null);let p=b();if(!p){l=setTimeout(v,e*1e3);return}try{if(s=ot(p,t.container,{muted:t.muted!==!1,autoplay:!0,objectFit:t.objectFit||"cover",imageDuration:c.image_duration||p.duration||8,onStart:m=>{I++,n(k(y({},m),{totalAdsShown:I})),at(p,t.fingerprint,{duration:p.duration,completed:!1}).then(g=>{T++,u({ad:p,result:g,totalImpressions:T})}).catch(g=>{a({phase:"impression",error:g.message})}),t.analytics&&t.analytics.track("ad_start",{ad_id:p.id,ad_type:p.type,fingerprint:t.fingerprint})},onComplete:m=>{i(k(y({},m),{totalAdsShown:I})),t.analytics&&t.analytics.track("ad_complete",{ad_id:p.id,ad_type:p.type,duration:m.duration,fingerprint:t.fingerprint});let g=(p.type==="video",0);l=setTimeout(v,g)},onError:m=>{a(k(y({},m),{phase:"render"})),t.analytics&&t.analytics.track("error",{ad_id:p.id,error:m.error,fingerprint:t.fingerprint}),l=setTimeout(v,2e3)}}),p.type!=="video"){let m=(p.duration||c.image_duration||8)*1e3;l=setTimeout(v,m)}}catch(m){a({phase:"render",error:m.message,ad:p}),l=setTimeout(v,5e3)}}function j(){f||(f=!0,D().then(()=>{v()}),h=setInterval(async()=>{await D()},r*60*1e3))}function F(){f=!1,l&&(clearTimeout(l),l=null),h&&(clearInterval(h),h=null),s&&(s.destroy(),s=null)}function K(){f&&(l&&(clearTimeout(l),l=null),v())}function $(){return{running:f,totalAds:o.length,currentIndex:d,totalAdsShown:I,totalImpressions:T,intervalSeconds:e,settings:c,etag:S}}return{start:j,stop:F,next:K,getStatus:$,loadAds:D}}ct.exports={fetchAds:st,renderAd:ot,trackImpression:at,parseVast:Ht,firePixel:G,createAdRotation:Jt}});var gt=P((_e,mt)=>{var Yt="trillboards_connect",R="cached_ads",C="queued_impressions",dt="metadata",Xt="https://api.trillboards.com/v1/partner";function O(){return new Promise((t,e)=>{if(typeof indexedDB=="undefined"){e(new Error("IndexedDB is not available in this environment"));return}let r=indexedDB.open(Yt,1);r.onupgradeneeded=n=>{let i=n.target.result;if(!i.objectStoreNames.contains(R)){let a=i.createObjectStore(R,{keyPath:"id"});a.createIndex("fingerprint","fingerprint",{unique:!1}),a.createIndex("cached_at","cached_at",{unique:!1}),a.createIndex("expires_at","expires_at",{unique:!1})}if(!i.objectStoreNames.contains(C)){let a=i.createObjectStore(C,{keyPath:"queue_id",autoIncrement:!0});a.createIndex("timestamp","timestamp",{unique:!1}),a.createIndex("synced","synced",{unique:!1})}i.objectStoreNames.contains(dt)||i.createObjectStore(dt,{keyPath:"key"})},r.onsuccess=()=>t(r.result),r.onerror=()=>e(r.error)})}async function Qt(t,e,r=10){if(!e||!Array.isArray(e)||e.length===0)return 0;let n=new Date,i=new Date(n.getTime()+1440*60*1e3),a=e.slice(0,r).map(o=>k(y({},o),{fingerprint:t,cached_at:n.toISOString(),expires_at:i.toISOString()})),u=await O();return new Promise((o,c)=>{let d=u.transaction(R,"readwrite"),s=d.objectStore(R),l=0;for(let h of a){let f=s.put(h);f.onsuccess=()=>l++}d.oncomplete=()=>{u.close(),o(l)},d.onerror=()=>{u.close(),c(d.error)}})}async function Wt(t){let e=await O();return new Promise((r,n)=>{let o=e.transaction(R,"readonly").objectStore(R).index("fingerprint").getAll(t);o.onsuccess=()=>{let c=new Date().toISOString(),d=(o.result||[]).filter(s=>s.expires_at>c);e.close(),r(d)},o.onerror=()=>{e.close(),n(o.error)}})}async function Zt(){let t=await O();return new Promise((e,r)=>{let n=t.transaction(R,"readwrite"),a=n.objectStore(R).index("expires_at"),u=new Date().toISOString(),o=IDBKeyRange.upperBound(u),c=a.openCursor(o),d=0;c.onsuccess=s=>{let l=s.target.result;l&&(l.delete(),d++,l.continue())},n.oncomplete=()=>{t.close(),e(d)},n.onerror=()=>{t.close(),r(n.error)}})}async function te(t){if(!t||!t.adid)throw new Error("impressionData with adid is required");let e=k(y({},t),{timestamp:new Date().toISOString(),synced:!1,retry_count:0}),r=await O();return new Promise((n,i)=>{let a=r.transaction(C,"readwrite"),o=a.objectStore(C).add(e),c;o.onsuccess=()=>{c=o.result},a.oncomplete=()=>{r.close(),n(c)},a.onerror=()=>{r.close(),i(a.error)}})}async function ut(t=100){let e=await O();return new Promise((r,n)=>{let o=e.transaction(C,"readonly").objectStore(C).index("synced").getAll(!1,t);o.onsuccess=()=>{e.close(),r(o.result||[])},o.onerror=()=>{e.close(),n(o.error)}})}async function ht(t){if(!t||t.length===0)return 0;let e=await O();return new Promise((r,n)=>{let i=e.transaction(C,"readwrite"),a=i.objectStore(C),u=0;for(let o of t){let c=a.get(o);c.onsuccess=()=>{let d=c.result;d&&(d.synced=!0,d.synced_at=new Date().toISOString(),a.put(d),u++)}}i.oncomplete=()=>{e.close(),r(u)},i.onerror=()=>{e.close(),n(i.error)}})}async function ft(t=72){let e=new Date(Date.now()-t*60*60*1e3).toISOString(),r=await O();return new Promise((n,i)=>{let a=r.transaction(C,"readwrite"),o=a.objectStore(C).openCursor(),c=0;o.onsuccess=d=>{let s=d.target.result;if(s){let l=s.value;l.synced&&l.timestamp<e&&(s.delete(),c++),s.continue()}},a.oncomplete=()=>{r.close(),n(c)},a.onerror=()=>{r.close(),i(a.error)}})}async function pt(t={}){let e=t.batchSize||50,r=t.onProgress||(()=>{}),n=t.onError||(()=>{}),i={total:0,synced:0,failed:0,batches:0},a=await ut(100);if(i.total=a.length,a.length===0)return i;for(let u=0;u<a.length;u+=e){let o=a.slice(u,u+e),c=o.map(d=>({adid:d.adid,impid:d.impid,did:d.did,device_fingerprint:d.device_fingerprint,aid:d.aid,sid:d.sid,duration:d.duration,completed:d.completed,timestamp:d.timestamp}));try{let d=await fetch(`${Xt}/impressions/batch`,{method:"POST",headers:{"Content-Type":"application/json","X-SDK-Version":"1.0.0"},body:JSON.stringify({impressions:c})});if(d.ok){let s=await d.json(),l=o.map(h=>h.queue_id);await ht(l),i.synced+=s.recorded||o.length,i.failed+=s.failed||0}else i.failed+=o.length,n({batch:i.batches,status:d.status,count:o.length})}catch(d){i.failed+=o.length,n({batch:i.batches,error:d.message,count:o.length})}i.batches++,r({processed:Math.min(u+e,a.length),total:a.length,synced:i.synced,failed:i.failed})}return await ft(72).catch(()=>{}),i}function ee(t={}){let e=t.syncIntervalMs||3e5,r=t.onSyncComplete||(()=>{}),n=t.onStatusChange||(()=>{}),i=null,a=!1,u=!1;async function o(){if(!u){u=!0;try{if(!(typeof navigator!="undefined"?navigator.onLine:!0)){u=!1;return}let S=await pt({batchSize:50,onError:I=>{console.warn("[Trillboards SDK] Sync batch error:",I)}});r(S)}catch(f){console.error("[Trillboards SDK] Auto-sync error:",f)}finally{u=!1}}}function c(){n({online:!0,timestamp:new Date().toISOString()}),o()}function d(){n({online:!1,timestamp:new Date().toISOString()})}function s(){a||(a=!0,typeof window!="undefined"&&(window.addEventListener("online",c),window.addEventListener("offline",d)),i=setInterval(o,e),o())}function l(){a=!1,typeof window!="undefined"&&(window.removeEventListener("online",c),window.removeEventListener("offline",d)),i&&(clearInterval(i),i=null)}function h(){return{running:a,syncing:u,online:typeof navigator!="undefined"?navigator.onLine:!0}}return{start:s,stop:l,sync:o,getStatus:h}}mt.exports={openDatabase:O,cacheAds:Qt,getCachedAds:Wt,clearExpiredAds:Zt,queueImpression:te,getUnsyncedImpressions:ut,markSynced:ht,purgeSyncedImpressions:ft,syncImpressions:pt,createAutoSync:ee}});var bt=P((be,wt)=>{var L="trillboards-connect-branding",H="trillboards-connect-custom-css",yt=`
1
+ var TrillboardsConnect=(()=>{var Lt=Object.defineProperty,Mt=Object.defineProperties;var zt=Object.getOwnPropertyDescriptors;var W=Object.getOwnPropertySymbols;var $t=Object.prototype.hasOwnProperty,Ut=Object.prototype.propertyIsEnumerable;var Z=(t,e,r)=>e in t?Lt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,y=(t,e)=>{for(var r in e||(e={}))$t.call(e,r)&&Z(t,r,e[r]);if(W)for(var r of W(e))Ut.call(e,r)&&Z(t,r,e[r]);return t},k=(t,e)=>Mt(t,zt(e));var P=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var it=P((me,nt)=>{var U="https://api.trillboards.com/v1/partner",A={UNREGISTERED:"unregistered",REGISTERING:"registering",REGISTERED:"registered",ONLINE:"online",OFFLINE:"offline",ERROR:"error"};function Vt(t){if(!t||typeof t!="string")throw new Error("deviceId must be a non-empty string");let e=2166136261;for(let o=0;o<t.length;o++)e^=t.charCodeAt(o),e=Math.imul(e,16777619);let r=(e>>>0).toString(16).padStart(8,"0"),n=16777619;for(let o=0;o<t.length;o++)n^=t.charCodeAt(o)*(o+1),n=Math.imul(n,2166136261);let i=(n>>>0).toString(16).padStart(8,"0");return`SDK_${r}${i}`}function tt(){let t={sdk_version:"1.0.0",timestamp:new Date().toISOString()};return typeof navigator!="undefined"&&(t.user_agent=navigator.userAgent,t.platform=navigator.platform,t.language=navigator.language,t.online=navigator.onLine,t.hardware_concurrency=navigator.hardwareConcurrency),typeof screen!="undefined"&&(t.screen_width=screen.width,t.screen_height=screen.height,t.pixel_ratio=typeof devicePixelRatio!="undefined"?devicePixelRatio:1,t.color_depth=screen.colorDepth),t}async function et(t,e,r={}){if(!t)throw new Error("apiKey is required for device registration");if(!e)throw new Error("deviceId is required for device registration");let n=tt(),i={};n.screen_width&&(i.width=n.screen_width,i.height=n.screen_height);let o={device_id:e,device_type:r.device_type||"digital_signage",name:r.name||`SDK Device: ${e}`,display:y(y({},i),r.display),location:r.location||{},custom_metadata:y(y({},n),r.custom)},u;try{u=await fetch(`${U}/device`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`,"X-SDK-Version":"1.0.0"},body:JSON.stringify(o)})}catch(l){let c=new Error(`Network error during device registration: ${l.message}. If running from a browser, ensure your domain can reach api.trillboards.com. Test with: fetch("https://api.trillboards.com/v1/partner/ping").then(r => r.json()).then(console.log)`);throw c.statusCode=0,c.phase="device_registration",c.diagnosticUrl=`${U}/ping`,c}if(!u.ok){let l=await u.json().catch(()=>({})),c=new Error(l.message||`Device registration failed: ${u.status}`);throw c.statusCode=u.status,c.response=l,c}let a=await u.json();return a.data||a}function rt(t,e=6e4,r={}){if(!t)throw new Error("fingerprint is required for heartbeat");let n=r.maxRetries||10,i=r.retryBackoff||1.5,o=r.onSuccess||(()=>{}),u=r.onError||(()=>{}),a=null,l=0,c=0,s=null,d=!1,h=e;async function f(){try{let b=await fetch(`${U}/device/${encodeURIComponent(t)}/heartbeat`,{method:"POST",headers:{"Content-Type":"application/json","X-SDK-Version":"1.0.0"},body:JSON.stringify({timestamp:new Date().toISOString(),total_beats:c})});if(!b.ok)throw new Error(`Heartbeat failed: HTTP ${b.status}`);let v=await b.json();return l=0,h=e,c++,s=new Date,o({beat:c,status:v.status||"online",last_seen_at:v.last_seen_at,timestamp:s.toISOString()}),v}catch(b){return l++,u({error:b.message,consecutiveFailures:l,willRetry:l<n}),l>=n?(console.error(`[Trillboards SDK] Heartbeat stopped after ${n} consecutive failures`),T(),null):(h=Math.min(e*Math.pow(i,l),e*5),null)}}function S(){d&&(a=setTimeout(async()=>{await f(),S()},h))}function I(){d||(d=!0,l=0,h=e,f().then(()=>{S()}))}function T(){d=!1,a&&(clearTimeout(a),a=null)}function D(){return{running:d,totalBeats:c,lastBeatAt:s?s.toISOString():null,consecutiveFailures:l,currentIntervalMs:h}}return{start:I,stop:T,getStatus:D,sendBeat:f}}var V=class{constructor(e){this.deviceId=e,this.status=A.UNREGISTERED,this.fingerprint=null,this.screenId=null,this.embedUrl=null,this.registrationData=null,this.heartbeatController=null,this.listeners={},this.lastError=null}on(e,r){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(r)}off(e,r){this.listeners[e]&&(this.listeners[e]=this.listeners[e].filter(n=>n!==r))}emit(e,r){this.listeners[e]&&this.listeners[e].forEach(n=>{try{n(r)}catch(i){console.error(`[Trillboards SDK] Event listener error for '${e}':`,i)}})}setStatus(e){let r=this.status;this.status=e,r!==e&&this.emit("status_change",{from:r,to:e,deviceId:this.deviceId,timestamp:new Date().toISOString()})}async register(e,r={},n={}){this.setStatus(A.REGISTERING);try{let i=await et(e,this.deviceId,r);this.fingerprint=i.fingerprint,this.screenId=i.screen_id,this.embedUrl=i.embed_url,this.registrationData=i,this.lastError=null,this.setStatus(A.REGISTERED),this.emit("registered",i);let o=n.interval||6e4;return this.heartbeatController=rt(this.fingerprint,o,{onSuccess:u=>{this.setStatus(A.ONLINE),this.emit("heartbeat",u)},onError:u=>{u.willRetry||this.setStatus(A.OFFLINE),this.emit("heartbeat_error",u)},maxRetries:n.maxRetries||10,retryBackoff:n.retryBackoff||1.5}),this.heartbeatController.start(),i}catch(i){throw this.lastError=i,this.setStatus(A.ERROR),this.emit("error",{phase:"registration",error:i.message,statusCode:i.statusCode}),i}}destroy(){this.heartbeatController&&(this.heartbeatController.stop(),this.heartbeatController=null),this.setStatus(A.OFFLINE),this.listeners={}}getState(){return{deviceId:this.deviceId,status:this.status,fingerprint:this.fingerprint,screenId:this.screenId,embedUrl:this.embedUrl,heartbeat:this.heartbeatController?this.heartbeatController.getStatus():null,lastError:this.lastError?this.lastError.message:null}}};nt.exports={registerDevice:et,generateFingerprint:Vt,startHeartbeat:rt,DeviceTracker:V,DeviceStatus:A,collectDeviceMetadata:tt}});var lt=P((ye,ct)=>{var Gt="https://api.trillboards.com/v1/partner";function Ht(t){if(!t||typeof t!="string")return null;let e;if(typeof DOMParser!="undefined")e=new DOMParser().parseFromString(t,"text/xml");else return{mediaFiles:[],tracking:{},impressionUrls:[],errorUrls:[],raw:t};let r={mediaFiles:[],tracking:{},impressionUrls:[],errorUrls:[],clickThrough:null,clickTracking:[],duration:0};e.querySelectorAll("Impression").forEach(s=>{let d=(s.textContent||"").trim();d&&r.impressionUrls.push(d)}),e.querySelectorAll("Error").forEach(s=>{let d=(s.textContent||"").trim();d&&r.errorUrls.push(d)}),e.querySelectorAll("MediaFile").forEach(s=>{r.mediaFiles.push({url:(s.textContent||"").trim(),type:s.getAttribute("type")||"video/mp4",width:parseInt(s.getAttribute("width"))||0,height:parseInt(s.getAttribute("height"))||0,bitrate:parseInt(s.getAttribute("bitrate"))||0,delivery:s.getAttribute("delivery")||"progressive"})}),e.querySelectorAll("Tracking").forEach(s=>{let d=s.getAttribute("event"),h=(s.textContent||"").trim();d&&h&&(r.tracking[d]||(r.tracking[d]=[]),r.tracking[d].push(h))});let a=e.querySelector("ClickThrough");a&&(r.clickThrough=(a.textContent||"").trim()),e.querySelectorAll("ClickTracking").forEach(s=>{let d=(s.textContent||"").trim();d&&r.clickTracking.push(d)});let c=e.querySelector("Duration");if(c){let d=(c.textContent||"").trim().split(":");d.length===3&&(r.duration=parseInt(d[0])*3600+parseInt(d[1])*60+parseFloat(d[2]))}return r}function G(t){return new Promise(e=>{if(!t){e(!1);return}let r=t.includes("?")?"&":"?",n=`${t}${r}cb=${Date.now()}`;if(typeof Image!="undefined"){let i=new Image;i.onload=()=>e(!0),i.onerror=()=>e(!1),i.src=n,setTimeout(()=>e(!1),5e3)}else fetch(n,{method:"GET",mode:"no-cors"}).then(()=>e(!0)).catch(()=>e(!1))})}async function st(t,e={}){if(!t)throw new Error("fingerprint is required to fetch ads");let r={Accept:"application/json","X-SDK-Version":"1.0.0"};e.etag&&(r["If-None-Match"]=e.etag);let n=await fetch(`${Gt}/device/${encodeURIComponent(t)}/ads`,{method:"GET",headers:r});if(n.status===304)return{ads:[],unchanged:!0,etag:e.etag};if(!n.ok){let o=await n.json().catch(()=>({})),u=new Error(o.message||`Failed to fetch ads: ${n.status}`);throw u.statusCode=n.status,u}let i=await n.json();return{ads:i.ads||[],settings:i.settings||{},cache_until:i.cache_until,etag:i.etag||null,device:i.device||{},unchanged:!1}}function ot(t,e,r={}){if(!t||!t.url)throw new Error("Valid ad object with url is required");let n=typeof e=="string"?document.querySelector(e):e;if(!n)throw new Error("Container element not found");let i=r.muted!==!1,o=r.autoplay!==!1,u=r.objectFit||"cover",a=r.onStart||(()=>{}),l=r.onComplete||(()=>{}),c=r.onError||(()=>{}),s=null,d=null,h=null,f=!1;return n.innerHTML="",n.style.position=n.style.position||"relative",n.style.overflow="hidden",t.type==="video"?(s=document.createElement("video"),s.src=t.url,s.muted=i,s.autoplay=o,s.playsInline=!0,s.setAttribute("playsinline",""),s.setAttribute("webkit-playsinline",""),s.style.width="100%",s.style.height="100%",s.style.objectFit=u,s.style.display="block",s.addEventListener("play",()=>{f||(h=Date.now(),a({ad:t,type:"video",timestamp:new Date().toISOString()}))}),s.addEventListener("ended",()=>{f||l({ad:t,type:"video",duration:h?(Date.now()-h)/1e3:0,completed:!0,timestamp:new Date().toISOString()})}),s.addEventListener("error",S=>{f||c({ad:t,type:"video",error:S.message||"Video playback error",timestamp:new Date().toISOString()})}),n.appendChild(s)):(s=document.createElement("img"),s.src=t.url,s.alt=t.title||"Advertisement",s.style.width="100%",s.style.height="100%",s.style.objectFit=u,s.style.display="block",s.addEventListener("load",()=>{if(!f){h=Date.now(),a({ad:t,type:"image",timestamp:new Date().toISOString()});let S=(t.duration||r.imageDuration||8)*1e3;d=setTimeout(()=>{f||l({ad:t,type:"image",duration:t.duration||r.imageDuration||8,completed:!0,timestamp:new Date().toISOString()})},S)}}),s.addEventListener("error",()=>{f||c({ad:t,type:"image",error:"Image failed to load",timestamp:new Date().toISOString()})}),n.appendChild(s)),{pause(){s&&s.pause&&s.pause()},resume(){s&&s.play&&s.play().catch(()=>{})},destroy(){f=!0,d&&(clearTimeout(d),d=null),s&&(s.pause&&s.pause(),s.parentNode&&s.parentNode.removeChild(s),s=null)},getPlaybackState(){return s?t.type==="video"?{state:s.paused?"paused":"playing",currentTime:s.currentTime,duration:s.duration,muted:s.muted}:{state:h?"showing":"loading",elapsed:h?(Date.now()-h)/1e3:0}:{state:"destroyed"}}}}async function at(t,e,r={}){if(!t||!t.id)throw new Error("Valid ad object with id is required");let n={impression_url:!1,pixel_url:!1,vast_impressions:[]};if(t.impression_url)try{let i=new URL(t.impression_url);r.duration&&i.searchParams.set("duration",String(r.duration)),r.completed!==void 0&&i.searchParams.set("completed",String(r.completed));let o=await fetch(i.toString(),{method:"GET",mode:"no-cors"});n.impression_url=!0}catch(i){n.impression_url=!1}if(t.pixel_url&&(n.pixel_url=await G(t.pixel_url)),t.vast_data&&t.vast_data.impressionUrls)for(let i of t.vast_data.impressionUrls){let o=await G(i);n.vast_impressions.push({url:i,fired:o})}return n}function Jt(t){if(!t.fingerprint)throw new Error("fingerprint is required for ad rotation");let e=t.intervalSeconds||60,r=t.refreshMinutes||5,n=t.onAdStart||(()=>{}),i=t.onAdComplete||(()=>{}),o=t.onError||(()=>{}),u=t.onImpression||(()=>{}),a=[],l={},c=0,s=null,d=null,h=null,f=!1,S=null,I=0,T=0;async function D(){try{let p=await st(t.fingerprint,{etag:S});return p.unchanged||(a=p.ads,l=p.settings||{},S=p.etag,c=0),a}catch(p){return o({phase:"fetch",error:p.message}),a}}function b(){if(a.length===0)return null;let p=a[c%a.length];return c=(c+1)%a.length,p}async function v(){if(!f)return;s&&(s.destroy(),s=null);let p=b();if(!p){d=setTimeout(v,e*1e3);return}try{if(s=ot(p,t.container,{muted:t.muted!==!1,autoplay:!0,objectFit:t.objectFit||"cover",imageDuration:l.image_duration||p.duration||8,onStart:m=>{I++,n(k(y({},m),{totalAdsShown:I})),at(p,t.fingerprint,{duration:p.duration,completed:!1}).then(g=>{T++,u({ad:p,result:g,totalImpressions:T})}).catch(g=>{o({phase:"impression",error:g.message})}),t.analytics&&t.analytics.track("ad_start",{ad_id:p.id,ad_type:p.type,fingerprint:t.fingerprint})},onComplete:m=>{i(k(y({},m),{totalAdsShown:I})),t.analytics&&t.analytics.track("ad_complete",{ad_id:p.id,ad_type:p.type,duration:m.duration,fingerprint:t.fingerprint});let g=(p.type==="video",0);d=setTimeout(v,g)},onError:m=>{o(k(y({},m),{phase:"render"})),t.analytics&&t.analytics.track("error",{ad_id:p.id,error:m.error,fingerprint:t.fingerprint}),d=setTimeout(v,2e3)}}),p.type!=="video"){let m=(p.duration||l.image_duration||8)*1e3;d=setTimeout(v,m)}}catch(m){o({phase:"render",error:m.message,ad:p}),d=setTimeout(v,5e3)}}function j(){f||(f=!0,D().then(()=>{v()}),h=setInterval(async()=>{await D()},r*60*1e3))}function F(){f=!1,d&&(clearTimeout(d),d=null),h&&(clearInterval(h),h=null),s&&(s.destroy(),s=null)}function K(){f&&(d&&(clearTimeout(d),d=null),v())}function $(){return{running:f,totalAds:a.length,currentIndex:c,totalAdsShown:I,totalImpressions:T,intervalSeconds:e,settings:l,etag:S}}return{start:j,stop:F,next:K,getStatus:$,loadAds:D}}ct.exports={fetchAds:st,renderAd:ot,trackImpression:at,parseVast:Ht,firePixel:G,createAdRotation:Jt}});var gt=P((_e,mt)=>{var Yt="trillboards_connect",R="cached_ads",C="queued_impressions",dt="metadata",Xt="https://api.trillboards.com/v1/partner";function O(){return new Promise((t,e)=>{if(typeof indexedDB=="undefined"){e(new Error("IndexedDB is not available in this environment"));return}let r=indexedDB.open(Yt,1);r.onupgradeneeded=n=>{let i=n.target.result;if(!i.objectStoreNames.contains(R)){let o=i.createObjectStore(R,{keyPath:"id"});o.createIndex("fingerprint","fingerprint",{unique:!1}),o.createIndex("cached_at","cached_at",{unique:!1}),o.createIndex("expires_at","expires_at",{unique:!1})}if(!i.objectStoreNames.contains(C)){let o=i.createObjectStore(C,{keyPath:"queue_id",autoIncrement:!0});o.createIndex("timestamp","timestamp",{unique:!1}),o.createIndex("synced","synced",{unique:!1})}i.objectStoreNames.contains(dt)||i.createObjectStore(dt,{keyPath:"key"})},r.onsuccess=()=>t(r.result),r.onerror=()=>e(r.error)})}async function Qt(t,e,r=10){if(!e||!Array.isArray(e)||e.length===0)return 0;let n=new Date,i=new Date(n.getTime()+1440*60*1e3),o=e.slice(0,r).map(a=>k(y({},a),{fingerprint:t,cached_at:n.toISOString(),expires_at:i.toISOString()})),u=await O();return new Promise((a,l)=>{let c=u.transaction(R,"readwrite"),s=c.objectStore(R),d=0;for(let h of o){let f=s.put(h);f.onsuccess=()=>d++}c.oncomplete=()=>{u.close(),a(d)},c.onerror=()=>{u.close(),l(c.error)}})}async function Wt(t){let e=await O();return new Promise((r,n)=>{let a=e.transaction(R,"readonly").objectStore(R).index("fingerprint").getAll(t);a.onsuccess=()=>{let l=new Date().toISOString(),c=(a.result||[]).filter(s=>s.expires_at>l);e.close(),r(c)},a.onerror=()=>{e.close(),n(a.error)}})}async function Zt(){let t=await O();return new Promise((e,r)=>{let n=t.transaction(R,"readwrite"),o=n.objectStore(R).index("expires_at"),u=new Date().toISOString(),a=IDBKeyRange.upperBound(u),l=o.openCursor(a),c=0;l.onsuccess=s=>{let d=s.target.result;d&&(d.delete(),c++,d.continue())},n.oncomplete=()=>{t.close(),e(c)},n.onerror=()=>{t.close(),r(n.error)}})}async function te(t){if(!t||!t.adid)throw new Error("impressionData with adid is required");let e=k(y({},t),{timestamp:new Date().toISOString(),synced:!1,retry_count:0}),r=await O();return new Promise((n,i)=>{let o=r.transaction(C,"readwrite"),a=o.objectStore(C).add(e),l;a.onsuccess=()=>{l=a.result},o.oncomplete=()=>{r.close(),n(l)},o.onerror=()=>{r.close(),i(o.error)}})}async function ut(t=100){let e=await O();return new Promise((r,n)=>{let a=e.transaction(C,"readonly").objectStore(C).index("synced").getAll(!1,t);a.onsuccess=()=>{e.close(),r(a.result||[])},a.onerror=()=>{e.close(),n(a.error)}})}async function ht(t){if(!t||t.length===0)return 0;let e=await O();return new Promise((r,n)=>{let i=e.transaction(C,"readwrite"),o=i.objectStore(C),u=0;for(let a of t){let l=o.get(a);l.onsuccess=()=>{let c=l.result;c&&(c.synced=!0,c.synced_at=new Date().toISOString(),o.put(c),u++)}}i.oncomplete=()=>{e.close(),r(u)},i.onerror=()=>{e.close(),n(i.error)}})}async function ft(t=72){let e=new Date(Date.now()-t*60*60*1e3).toISOString(),r=await O();return new Promise((n,i)=>{let o=r.transaction(C,"readwrite"),a=o.objectStore(C).openCursor(),l=0;a.onsuccess=c=>{let s=c.target.result;if(s){let d=s.value;d.synced&&d.timestamp<e&&(s.delete(),l++),s.continue()}},o.oncomplete=()=>{r.close(),n(l)},o.onerror=()=>{r.close(),i(o.error)}})}async function pt(t={}){let e=t.batchSize||50,r=t.onProgress||(()=>{}),n=t.onError||(()=>{}),i={total:0,synced:0,failed:0,batches:0},o=await ut(100);if(i.total=o.length,o.length===0)return i;for(let u=0;u<o.length;u+=e){let a=o.slice(u,u+e),l=a.map(c=>({adid:c.adid,impid:c.impid,did:c.did,device_fingerprint:c.device_fingerprint,aid:c.aid,sid:c.sid,duration:c.duration,completed:c.completed,timestamp:c.timestamp}));try{let c=await fetch(`${Xt}/impressions/batch`,{method:"POST",headers:{"Content-Type":"application/json","X-SDK-Version":"1.0.0"},body:JSON.stringify({impressions:l})});if(c.ok){let s=await c.json(),d=a.map(h=>h.queue_id);await ht(d),i.synced+=s.recorded||a.length,i.failed+=s.failed||0}else i.failed+=a.length,n({batch:i.batches,status:c.status,count:a.length})}catch(c){i.failed+=a.length,n({batch:i.batches,error:c.message,count:a.length})}i.batches++,r({processed:Math.min(u+e,o.length),total:o.length,synced:i.synced,failed:i.failed})}return await ft(72).catch(()=>{}),i}function ee(t={}){let e=t.syncIntervalMs||3e5,r=t.onSyncComplete||(()=>{}),n=t.onStatusChange||(()=>{}),i=null,o=!1,u=!1;async function a(){if(!u){u=!0;try{if(!(typeof navigator!="undefined"?navigator.onLine:!0)){u=!1;return}let S=await pt({batchSize:50,onError:I=>{console.warn("[Trillboards SDK] Sync batch error:",I)}});r(S)}catch(f){console.error("[Trillboards SDK] Auto-sync error:",f)}finally{u=!1}}}function l(){n({online:!0,timestamp:new Date().toISOString()}),a()}function c(){n({online:!1,timestamp:new Date().toISOString()})}function s(){o||(o=!0,typeof window!="undefined"&&(window.addEventListener("online",l),window.addEventListener("offline",c)),i=setInterval(a,e),a())}function d(){o=!1,typeof window!="undefined"&&(window.removeEventListener("online",l),window.removeEventListener("offline",c)),i&&(clearInterval(i),i=null)}function h(){return{running:o,syncing:u,online:typeof navigator!="undefined"?navigator.onLine:!0}}return{start:s,stop:d,sync:a,getStatus:h}}mt.exports={openDatabase:O,cacheAds:Qt,getCachedAds:Wt,clearExpiredAds:Zt,queueImpression:te,getUnsyncedImpressions:ut,markSynced:ht,purgeSyncedImpressions:ft,syncImpressions:pt,createAutoSync:ee}});var bt=P((be,wt)=>{var L="trillboards-connect-branding",H="trillboards-connect-custom-css",yt=`
2
2
  /* Trillboards Connect SDK - Default Branding */
3
3
  .trillboards-container {
4
4
  position: relative;
@@ -100,5 +100,5 @@ var TrillboardsConnect=(()=>{var Lt=Object.defineProperty,Mt=Object.defineProper
100
100
  .trillboards-skip-btn:hover {
101
101
  background: rgba(255, 255, 255, 0.25);
102
102
  }
103
- `;function St(){if(typeof document=="undefined")return null;if(document.getElementById(L))return document.getElementById(L);let t=document.createElement("style");return t.id=L,t.type="text/css",t.textContent=yt,document.head.appendChild(t),t}async function _t(t,e={}){if(typeof document=="undefined"||!t||typeof t!="string")return null;let r=e.timeout||5e3,n=e.onLoad||(()=>{}),i=e.onError||(()=>{}),a=document.getElementById(H);return a&&a.parentNode.removeChild(a),new Promise(u=>{let o=document.createElement("link");o.id=H,o.rel="stylesheet",o.type="text/css",o.href=t;let c=setTimeout(()=>{i({error:"CSS load timeout",url:t}),u(null)},r);o.onload=()=>{clearTimeout(c),n({url:t}),u(o)},o.onerror=()=>{clearTimeout(c),i({error:"CSS load failed",url:t}),u(null)},document.head.appendChild(o)})}function re(){if(typeof document=="undefined")return;let t=document.getElementById(L);t&&t.parentNode.removeChild(t);let e=document.getElementById(H);e&&e.parentNode.removeChild(e)}async function ne(t={}){let e={defaultApplied:!1,customApplied:!1,customUrl:null},r=St();if(e.defaultApplied=!!r,t.custom_css_url){e.customUrl=t.custom_css_url;let n=await _t(t.custom_css_url);e.customApplied=!!n}return e}wt.exports={injectDefaultBranding:St,loadCustomCss:_t,removeBranding:re,applyBranding:ne,DEFAULT_CSS:yt}});var Et=P((ve,It)=>{var vt="https://api.trillboards.com/v1/partner",w={AD_START:"ad_start",AD_COMPLETE:"ad_complete",AD_SKIP:"ad_skip",AD_ERROR:"ad_error",ERROR:"error",HEARTBEAT:"heartbeat",SDK_INIT:"sdk_init",SDK_ERROR:"sdk_error",DEVICE_REGISTERED:"device_registered",OFFLINE_SYNC:"offline_sync",AD_IMPRESSION:"ad_impression",VISIBILITY_CHANGE:"visibility_change"};function ie(t={}){let e=t.fingerprint||"unknown",r=t.apiKey||null,n=t.flushIntervalMs||3e4,i=t.maxBufferSize||50,a=t.onFlush||(()=>{}),u=t.onError||(()=>{}),o=t.enabled!==!1,c=[],d=null,s=!1,l=!1,h=0,f=0,S=0,I=T();function T(){let m=Date.now().toString(36),g=Math.random().toString(36).substring(2,8);return`sess_${m}_${g}`}function D(m,g={}){if(!o||!l)return null;let x={event:m,fingerprint:e,session_id:I,timestamp:new Date().toISOString(),data:k(y({},g),{sdk_version:"1.0.0"})};return c.push(x),h++,c.length>=i&&b(),x}async function b(){if(s||c.length===0)return{flushed:0,errors:0};s=!0;let m=c.splice(0);try{let g=m.filter(B=>[w.AD_START,w.AD_COMPLETE,w.AD_SKIP,w.AD_IMPRESSION].includes(B.event)),x=m.filter(B=>![w.AD_START,w.AD_COMPLETE,w.AD_SKIP,w.AD_IMPRESSION].includes(B.event)),E=0;if(g.length>0){let B=g.filter(_=>_.data&&_.data.ad_id).map(_=>({adid:_.data.ad_id,impid:_.data.impression_id||`sdk_${Date.now()}_${Math.random().toString(36).substr(2,6)}`,did:_.fingerprint,device_fingerprint:_.fingerprint,duration:_.data.duration||0,completed:_.event===w.AD_COMPLETE,timestamp:_.timestamp}));if(B.length>0){let _={"Content-Type":"application/json","X-SDK-Version":"1.0.0"};r&&(_.Authorization=`Bearer ${r}`);let Q=await fetch(`${vt}/impressions/batch`,{method:"POST",headers:_,body:JSON.stringify({impressions:B})});if(Q.ok)E+=B.length;else throw new Error(`Batch send failed: ${Q.status}`)}E+=g.length-g.filter(_=>_.data&&_.data.ad_id).length}E+=x.length,f+=E;let X={flushed:E,errors:0,timestamp:new Date().toISOString()};return a(X),X}catch(g){S++,c.unshift(...m),c.length>i*3&&(c=c.slice(-i*2));let x={flushed:0,errors:m.length,error:g.message};return u(x),x}finally{s=!1}}function v(){l||(l=!0,I=T(),d=setInterval(()=>{b()},n),typeof window!="undefined"&&(window.addEventListener("beforeunload",F),document.addEventListener("visibilitychange",K)),D(w.SDK_INIT,{fingerprint:e,flush_interval_ms:n,max_buffer_size:i}))}async function j(){l=!1,d&&(clearInterval(d),d=null),typeof window!="undefined"&&(window.removeEventListener("beforeunload",F),document.removeEventListener("visibilitychange",K)),await b()}function F(){if(c.length>0&&typeof navigator!="undefined"&&navigator.sendBeacon){let m=c.filter(g=>g.data&&g.data.ad_id);if(m.length>0){let g=m.map(E=>({adid:E.data.ad_id,impid:E.data.impression_id||`sdk_${Date.now()}_${Math.random().toString(36).substr(2,6)}`,did:E.fingerprint,duration:E.data.duration||0,completed:E.event===w.AD_COMPLETE,timestamp:E.timestamp})),x=new Blob([JSON.stringify({impressions:g})],{type:"application/json"});navigator.sendBeacon(`${vt}/impressions/batch`,x)}c=[]}}function K(){document.visibilityState==="hidden"?(D(w.VISIBILITY_CHANGE,{visible:!1}),b()):D(w.VISIBILITY_CHANGE,{visible:!0})}function $(){return{running:l,enabled:o,sessionId:I,bufferSize:c.length,totalTracked:h,totalFlushed:f,totalErrors:S,fingerprint:e}}async function p(){await j(),c=[],h=0,f=0,S=0}return{track:D,flush:b,start:v,stop:j,destroy:p,getStats:$,EventTypes:w}}It.exports={createAnalytics:ie,EventTypes:w}});var fe=P((Ee,z)=>{var{DeviceTracker:Tt,DeviceStatus:se,generateFingerprint:xt,registerDevice:oe,startHeartbeat:ae}=it(),{fetchAds:At,renderAd:Rt,trackImpression:Ot,parseVast:ce,createAdRotation:Bt}=lt(),{cacheAds:Pt,getCachedAds:le,queueImpression:Nt,syncImpressions:qt,createAutoSync:jt,clearExpiredAds:de}=gt(),{applyBranding:Ft,injectDefaultBranding:ue,loadCustomCss:he,removeBranding:Kt}=bt(),{createAnalytics:J,EventTypes:M}=Et(),N="1.0.0",kt="https://api.trillboards.com/v1/partner";function Dt(t){if(!t)throw new Error("TrillboardsConnect.init() requires a configuration object");if(!t.apiKey)throw new Error("apiKey is required. Get your API key from https://trillboards.com/earner");if(!t.deviceId)throw new Error("deviceId is required. Provide a unique identifier for this device.")}function Ct(t){return t?typeof t=="string"?typeof document!="undefined"?document.getElementById(t):null:t:null}var q=class{constructor(e){this.config=e,this.apiKey=e.apiKey,this.deviceId=e.deviceId,this.containerId=e.containerId,this.options=e.options||{},this.deviceTracker=null,this.adRotation=null,this.autoSync=null,this.analytics=null,this.socketConnection=null,this.initialized=!1,this.destroyed=!1,this.fingerprint=null,this.screenId=null,this.embedUrl=null,this.sdkConfig=null,this._listeners={}}on(e,r){return this._listeners[e]||(this._listeners[e]=[]),this._listeners[e].push(r),this}off(e,r){return this._listeners[e]&&(this._listeners[e]=this._listeners[e].filter(n=>n!==r)),this}_emit(e,r){this._listeners[e]&&this._listeners[e].forEach(n=>{try{n(r)}catch(i){console.error(`[Trillboards SDK] Listener error for '${e}':`,i)}})}async initialize(){if(this.initialized)return console.warn("[Trillboards SDK] Already initialized"),this;if(this._emit("initializing",{deviceId:this.deviceId,timestamp:new Date().toISOString()}),this.options.analytics!==!1){let r=xt(this.deviceId);this.analytics=J({fingerprint:r,apiKey:this.apiKey,flushIntervalMs:this.options.analyticsFlushInterval||3e4,maxBufferSize:this.options.analyticsBufferSize||50,onFlush:n=>{this._emit("analytics_flush",n)},onError:n=>{this._emit("analytics_error",n)}}),this.analytics.start()}this.deviceTracker=new Tt(this.deviceId),this.deviceTracker.on("status_change",r=>this._emit("device_status",r)),this.deviceTracker.on("registered",r=>this._emit("device_registered",r)),this.deviceTracker.on("error",r=>this._emit("device_error",r)),this.deviceTracker.on("heartbeat",r=>this._emit("heartbeat",r)),this.deviceTracker.on("heartbeat_error",r=>this._emit("heartbeat_error",r));try{let r=await this.deviceTracker.register(this.apiKey,{device_type:this.options.deviceType||"digital_signage",name:this.options.deviceName||`SDK Device: ${this.deviceId}`,display:this.options.display,location:this.options.location,custom:y({sdk_version:N},this.options.metadata||{})},{interval:this.options.heartbeatInterval||6e4,maxRetries:this.options.heartbeatMaxRetries||10,retryBackoff:1.5});this.fingerprint=r.fingerprint,this.screenId=r.screen_id,this.embedUrl=r.embed_url,this.analytics&&(this.analytics.destroy(),this.analytics=J({fingerprint:this.fingerprint,apiKey:this.apiKey,flushIntervalMs:this.options.analyticsFlushInterval||3e4,maxBufferSize:this.options.analyticsBufferSize||50,onFlush:n=>this._emit("analytics_flush",n),onError:n=>this._emit("analytics_error",n)}),this.analytics.start(),this.analytics.track(M.DEVICE_REGISTERED,{fingerprint:this.fingerprint,screen_id:this.screenId}))}catch(r){throw this._emit("error",{phase:"device_registration",error:r.message,statusCode:r.statusCode}),this.analytics&&this.analytics.track(M.SDK_ERROR,{phase:"device_registration",error:r.message}),r}try{let r=await fetch(`${kt}/info`,{headers:{Authorization:`Bearer ${this.apiKey}`,"X-SDK-Version":N}});if(r.ok){let n=await r.json();this.sdkConfig=n.sdk_config||{}}}catch(r){this.sdkConfig={}}try{await Ft(this.sdkConfig)}catch(r){console.warn("[Trillboards SDK] Branding error:",r.message)}let e=Ct(this.containerId);return e&&this.fingerprint&&(this.adRotation=Bt({fingerprint:this.fingerprint,container:e,intervalSeconds:this.sdkConfig.ad_interval||this.options.adInterval||60,refreshMinutes:this.options.adRefreshMinutes||5,muted:this.options.muted!==!1,objectFit:this.options.objectFit||"cover",analytics:this.analytics,onAdStart:r=>{this._emit("ad_start",r)},onAdComplete:r=>{this._emit("ad_complete",r)},onError:r=>{this._emit("ad_error",r)},onImpression:r=>{this._emit("impression",r)}}),this.adRotation.start()),this.options.offlineCache!==!1&&typeof indexedDB!="undefined"&&(this.autoSync=jt({syncIntervalMs:this.options.syncInterval||300*1e3,onSyncComplete:r=>{this._emit("sync_complete",r),this.analytics&&this.analytics.track(M.OFFLINE_SYNC,{synced:r.synced,failed:r.failed})},onStatusChange:r=>{this._emit("connectivity_change",r)}}),this.autoSync.start()),this._setupSocket(),this.initialized=!0,this._emit("ready",{deviceId:this.deviceId,fingerprint:this.fingerprint,screenId:this.screenId,embedUrl:this.embedUrl,timestamp:new Date().toISOString()}),this}_setupSocket(){let e=typeof window!="undefined"&&window.io?window.io:null;if(!(!e||!this.fingerprint))try{this.socketConnection=e(kt.replace("/v1/partner",""),{transports:["websocket","polling"],query:{fingerprint:this.fingerprint,sdk_version:N,type:"partner_sdk"},reconnection:!0,reconnectionAttempts:10,reconnectionDelay:1e3,reconnectionDelayMax:3e4}),this.socketConnection.on("connect",()=>{this._emit("socket_connected",{socketId:this.socketConnection.id}),this.socketConnection.emit("join_screen",{fingerprint:this.fingerprint,screen_id:this.screenId})}),this.socketConnection.on("disconnect",r=>{this._emit("socket_disconnected",{reason:r})}),this.socketConnection.on("refresh_ads",()=>{this.adRotation&&this.adRotation.loadAds().then(()=>{this._emit("ads_refreshed",{source:"socket"})})}),this.socketConnection.on("update_config",r=>{r&&r.sdk_config&&(this.sdkConfig=y(y({},this.sdkConfig),r.sdk_config),this._emit("config_updated",{config:this.sdkConfig,source:"socket"}))}),this.socketConnection.on("force_reload",()=>{this._emit("force_reload",{timestamp:new Date().toISOString()})}),this.socketConnection.on("content_update",r=>{this._emit("content_update",r),this.adRotation&&this.adRotation.loadAds()}),this.socketConnection.on("connect_error",r=>{this._emit("socket_error",{error:r.message})})}catch(r){console.warn("[Trillboards SDK] Socket.io setup failed:",r.message)}}nextAd(){this.adRotation&&this.adRotation.next()}pause(){this.adRotation&&this.adRotation.stop()}resume(){this.adRotation&&this.adRotation.start()}async requestAd(e={}){let r=e.container||Ct(this.containerId),n=e.timeout||1e4;if(!this.initialized||!this.fingerprint)throw new Error('Device not registered. Call init() first and wait for "ready" event.');let i=await Promise.race([At(this.fingerprint),new Promise((o,c)=>setTimeout(()=>c(new Error("Ad request timed out")),n))]);if(!i||!i.ads||i.ads.length===0)return{ad:null,controller:null,filled:!1};let a=i.ads[0],u=Rt(a,r,{muted:e.muted!==!1,onStart:o=>this._emit("ad_started",y({ad:a},o)),onComplete:o=>this._emit("ad_complete",y({ad:a},o)),onError:o=>this._emit("ad_error",{ad:a,error:o})});return Ot(a,this.fingerprint).catch(()=>{}),{ad:a,controller:u,filled:!0}}getState(){return{version:N,initialized:this.initialized,destroyed:this.destroyed,device:this.deviceTracker?this.deviceTracker.getState():null,adRotation:this.adRotation?this.adRotation.getStatus():null,offlineSync:this.autoSync?this.autoSync.getStatus():null,analytics:this.analytics?this.analytics.getStats():null,socket:this.socketConnection?{connected:this.socketConnection.connected,id:this.socketConnection.id}:null,config:this.sdkConfig}}async queueOfflineImpression(e){return Nt(k(y({},e),{device_fingerprint:this.fingerprint}))}async syncOffline(){return qt({batchSize:50,onError:e=>{this._emit("sync_error",e)}})}async cacheAdsOffline(e){var n;if(!this.fingerprint)return 0;let r=((n=this.sdkConfig)==null?void 0:n.cache_size)||this.options.cacheSize||10;return Pt(this.fingerprint,e,r)}async destroy(){this.destroyed||(this.destroyed=!0,this._emit("destroying",{timestamp:new Date().toISOString()}),this.adRotation&&(this.adRotation.stop(),this.adRotation=null),this.socketConnection&&(this.socketConnection.disconnect(),this.socketConnection=null),this.autoSync&&(this.autoSync.stop(),this.autoSync=null),this.analytics&&(await this.analytics.destroy(),this.analytics=null),this.deviceTracker&&(this.deviceTracker.destroy(),this.deviceTracker=null),Kt(),this.initialized=!1,this._listeners={})}},Y={version:N,init(t){Dt(t);let e=new q(t);return e.initialize().catch(r=>{console.error("[Trillboards SDK] Initialization failed:",r.message),e._emit("error",{phase:"init",error:r.message,fatal:!0})}),e},create(t){return Dt(t),new q(t)},device:{register:oe,generateFingerprint:xt,startHeartbeat:ae,DeviceTracker:Tt,DeviceStatus:se},auction:{fetchAds:At,renderAd:Rt,trackImpression:Ot,parseVast:ce,createAdRotation:Bt},offline:{cacheAds:Pt,getCachedAds:le,queueImpression:Nt,syncImpressions:qt,createAutoSync:jt,clearExpiredAds:de},branding:{applyBranding:Ft,injectDefaultBranding:ue,loadCustomCss:he,removeBranding:Kt},analytics:{createAnalytics:J,EventTypes:M}};z.exports=Y;z.exports.TrillboardsConnect=Y;z.exports.ConnectInstance=q;typeof window!="undefined"&&(window.TrillboardsConnect=Y)});return fe();})();
103
+ `;function St(){if(typeof document=="undefined")return null;if(document.getElementById(L))return document.getElementById(L);let t=document.createElement("style");return t.id=L,t.type="text/css",t.textContent=yt,document.head.appendChild(t),t}async function _t(t,e={}){if(typeof document=="undefined"||!t||typeof t!="string")return null;let r=e.timeout||5e3,n=e.onLoad||(()=>{}),i=e.onError||(()=>{}),o=document.getElementById(H);return o&&o.parentNode.removeChild(o),new Promise(u=>{let a=document.createElement("link");a.id=H,a.rel="stylesheet",a.type="text/css",a.href=t;let l=setTimeout(()=>{i({error:"CSS load timeout",url:t}),u(null)},r);a.onload=()=>{clearTimeout(l),n({url:t}),u(a)},a.onerror=()=>{clearTimeout(l),i({error:"CSS load failed",url:t}),u(null)},document.head.appendChild(a)})}function re(){if(typeof document=="undefined")return;let t=document.getElementById(L);t&&t.parentNode.removeChild(t);let e=document.getElementById(H);e&&e.parentNode.removeChild(e)}async function ne(t={}){let e={defaultApplied:!1,customApplied:!1,customUrl:null},r=St();if(e.defaultApplied=!!r,t.custom_css_url){e.customUrl=t.custom_css_url;let n=await _t(t.custom_css_url);e.customApplied=!!n}return e}wt.exports={injectDefaultBranding:St,loadCustomCss:_t,removeBranding:re,applyBranding:ne,DEFAULT_CSS:yt}});var Et=P((ve,It)=>{var vt="https://api.trillboards.com/v1/partner",w={AD_START:"ad_start",AD_COMPLETE:"ad_complete",AD_SKIP:"ad_skip",AD_ERROR:"ad_error",ERROR:"error",HEARTBEAT:"heartbeat",SDK_INIT:"sdk_init",SDK_ERROR:"sdk_error",DEVICE_REGISTERED:"device_registered",OFFLINE_SYNC:"offline_sync",AD_IMPRESSION:"ad_impression",VISIBILITY_CHANGE:"visibility_change"};function ie(t={}){let e=t.fingerprint||"unknown",r=t.apiKey||null,n=t.flushIntervalMs||3e4,i=t.maxBufferSize||50,o=t.onFlush||(()=>{}),u=t.onError||(()=>{}),a=t.enabled!==!1,l=[],c=null,s=!1,d=!1,h=0,f=0,S=0,I=T();function T(){let m=Date.now().toString(36),g=Math.random().toString(36).substring(2,8);return`sess_${m}_${g}`}function D(m,g={}){if(!a||!d)return null;let x={event:m,fingerprint:e,session_id:I,timestamp:new Date().toISOString(),data:k(y({},g),{sdk_version:"1.0.0"})};return l.push(x),h++,l.length>=i&&b(),x}async function b(){if(s||l.length===0)return{flushed:0,errors:0};s=!0;let m=l.splice(0);try{let g=m.filter(B=>[w.AD_START,w.AD_COMPLETE,w.AD_SKIP,w.AD_IMPRESSION].includes(B.event)),x=m.filter(B=>![w.AD_START,w.AD_COMPLETE,w.AD_SKIP,w.AD_IMPRESSION].includes(B.event)),E=0;if(g.length>0){let B=g.filter(_=>_.data&&_.data.ad_id).map(_=>({adid:_.data.ad_id,impid:_.data.impression_id||`sdk_${Date.now()}_${Math.random().toString(36).substr(2,6)}`,did:_.fingerprint,device_fingerprint:_.fingerprint,duration:_.data.duration||0,completed:_.event===w.AD_COMPLETE,timestamp:_.timestamp}));if(B.length>0){let _={"Content-Type":"application/json","X-SDK-Version":"1.0.0"};r&&(_.Authorization=`Bearer ${r}`);let Q=await fetch(`${vt}/impressions/batch`,{method:"POST",headers:_,body:JSON.stringify({impressions:B})});if(Q.ok)E+=B.length;else throw new Error(`Batch send failed: ${Q.status}`)}E+=g.length-g.filter(_=>_.data&&_.data.ad_id).length}E+=x.length,f+=E;let X={flushed:E,errors:0,timestamp:new Date().toISOString()};return o(X),X}catch(g){S++,l.unshift(...m),l.length>i*3&&(l=l.slice(-i*2));let x={flushed:0,errors:m.length,error:g.message};return u(x),x}finally{s=!1}}function v(){d||(d=!0,I=T(),c=setInterval(()=>{b()},n),typeof window!="undefined"&&(window.addEventListener("beforeunload",F),document.addEventListener("visibilitychange",K)),D(w.SDK_INIT,{fingerprint:e,flush_interval_ms:n,max_buffer_size:i}))}async function j(){d=!1,c&&(clearInterval(c),c=null),typeof window!="undefined"&&(window.removeEventListener("beforeunload",F),document.removeEventListener("visibilitychange",K)),await b()}function F(){if(l.length>0&&typeof navigator!="undefined"&&navigator.sendBeacon){let m=l.filter(g=>g.data&&g.data.ad_id);if(m.length>0){let g=m.map(E=>({adid:E.data.ad_id,impid:E.data.impression_id||`sdk_${Date.now()}_${Math.random().toString(36).substr(2,6)}`,did:E.fingerprint,duration:E.data.duration||0,completed:E.event===w.AD_COMPLETE,timestamp:E.timestamp})),x=new Blob([JSON.stringify({impressions:g})],{type:"application/json"});navigator.sendBeacon(`${vt}/impressions/batch`,x)}l=[]}}function K(){document.visibilityState==="hidden"?(D(w.VISIBILITY_CHANGE,{visible:!1}),b()):D(w.VISIBILITY_CHANGE,{visible:!0})}function $(){return{running:d,enabled:a,sessionId:I,bufferSize:l.length,totalTracked:h,totalFlushed:f,totalErrors:S,fingerprint:e}}async function p(){await j(),l=[],h=0,f=0,S=0}return{track:D,flush:b,start:v,stop:j,destroy:p,getStats:$,EventTypes:w}}It.exports={createAnalytics:ie,EventTypes:w}});var fe=P((Ee,z)=>{var{DeviceTracker:Tt,DeviceStatus:se,generateFingerprint:xt,registerDevice:oe,startHeartbeat:ae}=it(),{fetchAds:At,renderAd:Rt,trackImpression:Ot,parseVast:ce,createAdRotation:Bt}=lt(),{cacheAds:Pt,getCachedAds:le,queueImpression:Nt,syncImpressions:qt,createAutoSync:jt,clearExpiredAds:de}=gt(),{applyBranding:Ft,injectDefaultBranding:ue,loadCustomCss:he,removeBranding:Kt}=bt(),{createAnalytics:J,EventTypes:M}=Et(),N="1.0.0",kt="https://api.trillboards.com/v1/partner";function Dt(t){if(!t)throw new Error("TrillboardsConnect.init() requires a configuration object");if(!t.apiKey)throw new Error("apiKey is required. Get your API key from https://trillboards.com/earner");if(!t.deviceId)throw new Error("deviceId is required. Provide a unique identifier for this device.")}function Ct(t){return t?typeof t=="string"?typeof document!="undefined"?document.getElementById(t):null:t:null}var q=class{constructor(e){this.config=e,this.apiKey=e.apiKey,this.deviceId=e.deviceId,this.containerId=e.containerId,this.options=e.options||{},this.deviceTracker=null,this.adRotation=null,this.autoSync=null,this.analytics=null,this.socketConnection=null,this.initialized=!1,this.destroyed=!1,this.fingerprint=null,this.screenId=null,this.embedUrl=null,this.sdkConfig=null,this._listeners={}}on(e,r){return this._listeners[e]||(this._listeners[e]=[]),this._listeners[e].push(r),this}off(e,r){return this._listeners[e]&&(this._listeners[e]=this._listeners[e].filter(n=>n!==r)),this}_emit(e,r){this._listeners[e]&&this._listeners[e].forEach(n=>{try{n(r)}catch(i){console.error(`[Trillboards SDK] Listener error for '${e}':`,i)}})}async initialize(){if(this.initialized)return console.warn("[Trillboards SDK] Already initialized"),this;if(this._emit("initializing",{deviceId:this.deviceId,timestamp:new Date().toISOString()}),this.options.analytics!==!1){let r=xt(this.deviceId);this.analytics=J({fingerprint:r,apiKey:this.apiKey,flushIntervalMs:this.options.analyticsFlushInterval||3e4,maxBufferSize:this.options.analyticsBufferSize||50,onFlush:n=>{this._emit("analytics_flush",n)},onError:n=>{this._emit("analytics_error",n)}}),this.analytics.start()}this.deviceTracker=new Tt(this.deviceId),this.deviceTracker.on("status_change",r=>this._emit("device_status",r)),this.deviceTracker.on("registered",r=>this._emit("device_registered",r)),this.deviceTracker.on("error",r=>this._emit("device_error",r)),this.deviceTracker.on("heartbeat",r=>this._emit("heartbeat",r)),this.deviceTracker.on("heartbeat_error",r=>this._emit("heartbeat_error",r));try{let r=await this.deviceTracker.register(this.apiKey,{device_type:this.options.deviceType||"digital_signage",name:this.options.deviceName||`SDK Device: ${this.deviceId}`,display:this.options.display,location:this.options.location,custom:y({sdk_version:N},this.options.metadata||{})},{interval:this.options.heartbeatInterval||6e4,maxRetries:this.options.heartbeatMaxRetries||10,retryBackoff:1.5});this.fingerprint=r.fingerprint,this.screenId=r.screen_id,this.embedUrl=r.embed_url,this.analytics&&(this.analytics.destroy(),this.analytics=J({fingerprint:this.fingerprint,apiKey:this.apiKey,flushIntervalMs:this.options.analyticsFlushInterval||3e4,maxBufferSize:this.options.analyticsBufferSize||50,onFlush:n=>this._emit("analytics_flush",n),onError:n=>this._emit("analytics_error",n)}),this.analytics.start(),this.analytics.track(M.DEVICE_REGISTERED,{fingerprint:this.fingerprint,screen_id:this.screenId}))}catch(r){throw this._emit("error",{phase:"device_registration",error:r.message,statusCode:r.statusCode}),this.analytics&&this.analytics.track(M.SDK_ERROR,{phase:"device_registration",error:r.message}),r}try{let r=await fetch(`${kt}/info`,{headers:{Authorization:`Bearer ${this.apiKey}`,"X-SDK-Version":N}});if(r.ok){let n=await r.json();this.sdkConfig=n.sdk_config||{}}}catch(r){this.sdkConfig={}}try{await Ft(this.sdkConfig)}catch(r){console.warn("[Trillboards SDK] Branding error:",r.message)}let e=Ct(this.containerId);return e&&this.fingerprint&&(this.adRotation=Bt({fingerprint:this.fingerprint,container:e,intervalSeconds:this.sdkConfig.ad_interval||this.options.adInterval||60,refreshMinutes:this.options.adRefreshMinutes||5,muted:this.options.muted!==!1,objectFit:this.options.objectFit||"cover",analytics:this.analytics,onAdStart:r=>{this._emit("ad_start",r)},onAdComplete:r=>{this._emit("ad_complete",r)},onError:r=>{this._emit("ad_error",r)},onImpression:r=>{this._emit("impression",r)}}),this.adRotation.start()),this.options.offlineCache!==!1&&typeof indexedDB!="undefined"&&(this.autoSync=jt({syncIntervalMs:this.options.syncInterval||300*1e3,onSyncComplete:r=>{this._emit("sync_complete",r),this.analytics&&this.analytics.track(M.OFFLINE_SYNC,{synced:r.synced,failed:r.failed})},onStatusChange:r=>{this._emit("connectivity_change",r)}}),this.autoSync.start()),this._setupSocket(),this.initialized=!0,this._emit("ready",{deviceId:this.deviceId,fingerprint:this.fingerprint,screenId:this.screenId,embedUrl:this.embedUrl,timestamp:new Date().toISOString()}),this}_setupSocket(){let e=typeof window!="undefined"&&window.io?window.io:null;if(!(!e||!this.fingerprint))try{this.socketConnection=e(kt.replace("/v1/partner",""),{transports:["websocket","polling"],query:{fingerprint:this.fingerprint,sdk_version:N,type:"partner_sdk"},reconnection:!0,reconnectionAttempts:10,reconnectionDelay:1e3,reconnectionDelayMax:3e4}),this.socketConnection.on("connect",()=>{this._emit("socket_connected",{socketId:this.socketConnection.id}),this.socketConnection.emit("join_screen",{fingerprint:this.fingerprint,screen_id:this.screenId})}),this.socketConnection.on("disconnect",r=>{this._emit("socket_disconnected",{reason:r})}),this.socketConnection.on("refresh_ads",()=>{this.adRotation&&this.adRotation.loadAds().then(()=>{this._emit("ads_refreshed",{source:"socket"})})}),this.socketConnection.on("update_config",r=>{r&&r.sdk_config&&(this.sdkConfig=y(y({},this.sdkConfig),r.sdk_config),this._emit("config_updated",{config:this.sdkConfig,source:"socket"}))}),this.socketConnection.on("force_reload",()=>{this._emit("force_reload",{timestamp:new Date().toISOString()})}),this.socketConnection.on("content_update",r=>{this._emit("content_update",r),this.adRotation&&this.adRotation.loadAds()}),this.socketConnection.on("connect_error",r=>{this._emit("socket_error",{error:r.message})})}catch(r){console.warn("[Trillboards SDK] Socket.io setup failed:",r.message)}}nextAd(){this.adRotation&&this.adRotation.next()}pause(){this.adRotation&&this.adRotation.stop()}resume(){this.adRotation&&this.adRotation.start()}async requestAd(e={}){let r=e.container||Ct(this.containerId),n=e.timeout||1e4;if(!this.initialized||!this.fingerprint)throw new Error('Device not registered. Call init() first and wait for "ready" event.');let i=await Promise.race([At(this.fingerprint),new Promise((a,l)=>setTimeout(()=>l(new Error("Ad request timed out")),n))]);if(!i||!i.ads||i.ads.length===0)return{ad:null,controller:null,filled:!1};let o=i.ads[0],u=Rt(o,r,{muted:e.muted!==!1,onStart:a=>this._emit("ad_started",y({ad:o},a)),onComplete:a=>this._emit("ad_complete",y({ad:o},a)),onError:a=>this._emit("ad_error",{ad:o,error:a})});return Ot(o,this.fingerprint).catch(()=>{}),{ad:o,controller:u,filled:!0}}getState(){return{version:N,initialized:this.initialized,destroyed:this.destroyed,device:this.deviceTracker?this.deviceTracker.getState():null,adRotation:this.adRotation?this.adRotation.getStatus():null,offlineSync:this.autoSync?this.autoSync.getStatus():null,analytics:this.analytics?this.analytics.getStats():null,socket:this.socketConnection?{connected:this.socketConnection.connected,id:this.socketConnection.id}:null,config:this.sdkConfig}}async queueOfflineImpression(e){return Nt(k(y({},e),{device_fingerprint:this.fingerprint}))}async syncOffline(){return qt({batchSize:50,onError:e=>{this._emit("sync_error",e)}})}async cacheAdsOffline(e){var n;if(!this.fingerprint)return 0;let r=((n=this.sdkConfig)==null?void 0:n.cache_size)||this.options.cacheSize||10;return Pt(this.fingerprint,e,r)}async destroy(){this.destroyed||(this.destroyed=!0,this._emit("destroying",{timestamp:new Date().toISOString()}),this.adRotation&&(this.adRotation.stop(),this.adRotation=null),this.socketConnection&&(this.socketConnection.disconnect(),this.socketConnection=null),this.autoSync&&(this.autoSync.stop(),this.autoSync=null),this.analytics&&(await this.analytics.destroy(),this.analytics=null),this.deviceTracker&&(this.deviceTracker.destroy(),this.deviceTracker=null),Kt(),this.initialized=!1,this._listeners={})}},Y={version:N,init(t){Dt(t);let e=new q(t);return e.initialize().catch(r=>{console.error("[Trillboards SDK] Initialization failed:",r.message),e._emit("error",{phase:"init",error:r.message,fatal:!0})}),e},create(t){return Dt(t),new q(t)},device:{register:oe,generateFingerprint:xt,startHeartbeat:ae,DeviceTracker:Tt,DeviceStatus:se},auction:{fetchAds:At,renderAd:Rt,trackImpression:Ot,parseVast:ce,createAdRotation:Bt},offline:{cacheAds:Pt,getCachedAds:le,queueImpression:Nt,syncImpressions:qt,createAutoSync:jt,clearExpiredAds:de},branding:{applyBranding:Ft,injectDefaultBranding:ue,loadCustomCss:he,removeBranding:Kt},analytics:{createAnalytics:J,EventTypes:M}};z.exports=Y;z.exports.TrillboardsConnect=Y;z.exports.ConnectInstance=q;typeof window!="undefined"&&(window.TrillboardsConnect=Y)});return fe();})();
104
104
  //# sourceMappingURL=trillboards-connect.global.js.map