adgent-sdk 0.1.2 → 0.1.4

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,17 +1,14 @@
1
- var R = Object.defineProperty;
2
- var S = (i, e, r) => e in i ? R(i, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : i[e] = r;
3
- var l = (i, e, r) => S(i, typeof e != "symbol" ? e + "" : e, r);
4
1
  import { XMLParser as T } from "fast-xml-parser";
5
- var d = /* @__PURE__ */ ((i) => (i.Idle = "idle", i.Loading = "loading", i.Ready = "ready", i.Playing = "playing", i.Paused = "paused", i.Completed = "completed", i.Error = "error", i.WaitingForInteraction = "waiting_for_interaction", i))(d || {}), u = /* @__PURE__ */ ((i) => (i[i.XML_PARSING_ERROR = 100] = "XML_PARSING_ERROR", i[i.VAST_SCHEMA_VALIDATION_ERROR = 101] = "VAST_SCHEMA_VALIDATION_ERROR", i[i.VAST_VERSION_NOT_SUPPORTED = 102] = "VAST_VERSION_NOT_SUPPORTED", i[i.GENERAL_WRAPPER_ERROR = 300] = "GENERAL_WRAPPER_ERROR", i[i.WRAPPER_TIMEOUT = 301] = "WRAPPER_TIMEOUT", i[i.WRAPPER_LIMIT_REACHED = 302] = "WRAPPER_LIMIT_REACHED", i[i.NO_VAST_RESPONSE = 303] = "NO_VAST_RESPONSE", i[i.GENERAL_LINEAR_ERROR = 400] = "GENERAL_LINEAR_ERROR", i[i.FILE_NOT_FOUND = 401] = "FILE_NOT_FOUND", i[i.MEDIA_TIMEOUT = 402] = "MEDIA_TIMEOUT", i[i.MEDIA_NOT_SUPPORTED = 403] = "MEDIA_NOT_SUPPORTED", i[i.GENERAL_COMPANION_ERROR = 600] = "GENERAL_COMPANION_ERROR", i[i.UNDEFINED_ERROR = 900] = "UNDEFINED_ERROR", i))(u || {});
2
+ var c = /* @__PURE__ */ ((r) => (r.Idle = "idle", r.Loading = "loading", r.Ready = "ready", r.Playing = "playing", r.Paused = "paused", r.Completed = "completed", r.Error = "error", r.WaitingForInteraction = "waiting_for_interaction", r))(c || {}), p = /* @__PURE__ */ ((r) => (r[r.XML_PARSING_ERROR = 100] = "XML_PARSING_ERROR", r[r.VAST_SCHEMA_VALIDATION_ERROR = 101] = "VAST_SCHEMA_VALIDATION_ERROR", r[r.VAST_VERSION_NOT_SUPPORTED = 102] = "VAST_VERSION_NOT_SUPPORTED", r[r.GENERAL_WRAPPER_ERROR = 300] = "GENERAL_WRAPPER_ERROR", r[r.WRAPPER_TIMEOUT = 301] = "WRAPPER_TIMEOUT", r[r.WRAPPER_LIMIT_REACHED = 302] = "WRAPPER_LIMIT_REACHED", r[r.NO_VAST_RESPONSE = 303] = "NO_VAST_RESPONSE", r[r.GENERAL_LINEAR_ERROR = 400] = "GENERAL_LINEAR_ERROR", r[r.FILE_NOT_FOUND = 401] = "FILE_NOT_FOUND", r[r.MEDIA_TIMEOUT = 402] = "MEDIA_TIMEOUT", r[r.MEDIA_NOT_SUPPORTED = 403] = "MEDIA_NOT_SUPPORTED", r[r.GENERAL_COMPANION_ERROR = 600] = "GENERAL_COMPANION_ERROR", r[r.UNDEFINED_ERROR = 900] = "UNDEFINED_ERROR", r))(p || {}), P = Object.defineProperty, x = (r, e, t) => e in r ? P(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t, b = (r, e, t) => x(r, typeof e != "symbol" ? e + "" : e, t);
6
3
  class A {
7
4
  constructor(e = {}) {
8
- l(this, "config");
9
- l(this, "xmlParser");
5
+ b(this, "config"), b(this, "xmlParser");
6
+ var t, i, s, a;
10
7
  this.config = {
11
- maxWrapperDepth: e.maxWrapperDepth ?? 5,
12
- timeout: e.timeout ?? 1e4,
13
- debug: e.debug ?? !1,
14
- fetchFn: e.fetchFn ?? fetch.bind(globalThis)
8
+ maxWrapperDepth: (t = e.maxWrapperDepth) != null ? t : 5,
9
+ timeout: (i = e.timeout) != null ? i : 1e4,
10
+ debug: (s = e.debug) != null ? s : !1,
11
+ fetchFn: (a = e.fetchFn) != null ? a : fetch.bind(globalThis)
15
12
  }, this.xmlParser = new T({
16
13
  ignoreAttributes: !1,
17
14
  attributeNamePrefix: "@_",
@@ -27,13 +24,13 @@ class A {
27
24
  async parse(e) {
28
25
  try {
29
26
  return { success: !0, response: await this.fetchAndParse(e, 0) };
30
- } catch (r) {
31
- const t = r instanceof Error ? r.message : "Unknown error";
27
+ } catch (t) {
28
+ const i = t instanceof Error ? t.message : "Unknown error";
32
29
  return {
33
30
  success: !1,
34
31
  error: {
35
- code: u.GENERAL_WRAPPER_ERROR,
36
- message: t
32
+ code: p.GENERAL_WRAPPER_ERROR,
33
+ message: i
37
34
  }
38
35
  };
39
36
  }
@@ -41,16 +38,16 @@ class A {
41
38
  /**
42
39
  * Fetch and parse VAST document with wrapper resolution
43
40
  */
44
- async fetchAndParse(e, r) {
45
- if (r >= this.config.maxWrapperDepth)
41
+ async fetchAndParse(e, t) {
42
+ if (t >= this.config.maxWrapperDepth)
46
43
  throw new Error(
47
44
  `Wrapper limit exceeded (max: ${this.config.maxWrapperDepth})`
48
45
  );
49
- this.log(`Fetching VAST (depth: ${r}): ${e}`);
50
- const t = await this.fetchWithTimeout(e), s = this.parseXml(t), a = await Promise.all(
46
+ this.log(`Fetching VAST (depth: ${t}): ${e}`);
47
+ const i = await this.fetchWithTimeout(e), s = this.parseXml(i), a = await Promise.all(
51
48
  s.ads.map(async (n) => {
52
- var h;
53
- return (h = n.wrapper) != null && h.vastAdTagURI ? this.resolveWrapper(n, r + 1) : n;
49
+ var d;
50
+ return (d = n.wrapper) != null && d.vastAdTagURI ? this.resolveWrapper(n, t + 1) : n;
54
51
  })
55
52
  );
56
53
  return {
@@ -61,14 +58,14 @@ class A {
61
58
  /**
62
59
  * Resolve a wrapper ad by fetching the nested VAST
63
60
  */
64
- async resolveWrapper(e, r) {
65
- var t;
66
- if (!((t = e.wrapper) != null && t.vastAdTagURI))
61
+ async resolveWrapper(e, t) {
62
+ var i;
63
+ if (!((i = e.wrapper) != null && i.vastAdTagURI))
67
64
  return [e];
68
65
  try {
69
66
  return (await this.fetchAndParse(
70
67
  e.wrapper.vastAdTagURI,
71
- r
68
+ t
72
69
  )).ads.map(
73
70
  (a) => this.mergeWrapperTracking(e, a)
74
71
  );
@@ -81,21 +78,21 @@ class A {
81
78
  /**
82
79
  * Merge tracking events from wrapper into nested ad
83
80
  */
84
- mergeWrapperTracking(e, r) {
81
+ mergeWrapperTracking(e, t) {
85
82
  return {
86
- ...r,
83
+ ...t,
87
84
  impressions: [
88
85
  ...e.impressions,
89
- ...r.impressions
86
+ ...t.impressions
90
87
  ],
91
- errors: [...e.errors, ...r.errors],
92
- creatives: r.creatives.map((t) => ({
93
- ...t,
94
- linear: t.linear ? {
95
- ...t.linear,
88
+ errors: [...e.errors, ...t.errors],
89
+ creatives: t.creatives.map((i) => ({
90
+ ...i,
91
+ linear: i.linear ? {
92
+ ...i.linear,
96
93
  trackingEvents: [
97
94
  ...this.getWrapperTrackingEvents(e),
98
- ...t.linear.trackingEvents
95
+ ...i.linear.trackingEvents
99
96
  ]
100
97
  } : void 0
101
98
  }))
@@ -106,79 +103,79 @@ class A {
106
103
  */
107
104
  getWrapperTrackingEvents(e) {
108
105
  var t;
109
- const r = [];
106
+ const i = [];
110
107
  for (const s of e.creatives)
111
- (t = s.linear) != null && t.trackingEvents && r.push(...s.linear.trackingEvents);
112
- return r;
108
+ (t = s.linear) != null && t.trackingEvents && i.push(...s.linear.trackingEvents);
109
+ return i;
113
110
  }
114
111
  /**
115
112
  * Fetch URL with timeout
116
113
  */
117
114
  async fetchWithTimeout(e) {
118
- const r = new AbortController(), t = setTimeout(
119
- () => r.abort(),
115
+ const t = new AbortController(), i = setTimeout(
116
+ () => t.abort(),
120
117
  this.config.timeout
121
118
  );
122
119
  try {
123
120
  const s = await this.config.fetchFn(e, {
124
- signal: r.signal
121
+ signal: t.signal
125
122
  });
126
123
  if (!s.ok)
127
124
  throw new Error(`HTTP ${s.status}: ${s.statusText}`);
128
125
  return s.text();
129
126
  } finally {
130
- clearTimeout(t);
127
+ clearTimeout(i);
131
128
  }
132
129
  }
133
130
  /**
134
131
  * Parse raw VAST XML into structured response
135
132
  */
136
133
  parseXml(e) {
137
- const t = this.xmlParser.parse(e).VAST;
138
- if (!t)
134
+ const i = this.xmlParser.parse(e).VAST;
135
+ if (!i)
139
136
  throw new Error("Invalid VAST: missing VAST element");
140
- const s = t["@_version"] || "4.0", a = this.parseAds(t.Ad);
137
+ const s = i["@_version"] || "4.0", a = this.parseAds(i.Ad);
141
138
  return {
142
139
  version: s,
143
140
  ads: a,
144
- errors: this.parseErrors(t.Error)
141
+ errors: this.parseErrors(i.Error)
145
142
  };
146
143
  }
147
144
  /**
148
145
  * Parse Ad elements
149
146
  */
150
147
  parseAds(e) {
151
- return e ? (Array.isArray(e) ? e : [e]).map((t) => this.parseAd(t)) : [];
148
+ return e ? (Array.isArray(e) ? e : [e]).map((i) => this.parseAd(i)) : [];
152
149
  }
153
150
  /**
154
151
  * Parse a single Ad element
155
152
  */
156
153
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
157
154
  parseAd(e) {
158
- var s, a, n;
159
- const r = !!e.Wrapper, t = e.InLine || e.Wrapper;
155
+ var t, i, s;
156
+ const a = !!e.Wrapper, n = e.InLine || e.Wrapper;
160
157
  return {
161
158
  id: e["@_id"] || "",
162
159
  sequence: e["@_sequence"],
163
- adSystem: t != null && t.AdSystem ? {
164
- name: typeof t.AdSystem == "string" ? t.AdSystem : t.AdSystem["#text"] || "",
165
- version: (s = t.AdSystem) == null ? void 0 : s["@_version"]
160
+ adSystem: n != null && n.AdSystem ? {
161
+ name: typeof n.AdSystem == "string" ? n.AdSystem : n.AdSystem["#text"] || "",
162
+ version: (t = n.AdSystem) == null ? void 0 : t["@_version"]
166
163
  } : void 0,
167
- adTitle: t == null ? void 0 : t.AdTitle,
168
- impressions: this.parseImpressions(t == null ? void 0 : t.Impression),
169
- errors: this.parseErrors(t == null ? void 0 : t.Error),
170
- creatives: this.parseCreatives((a = t == null ? void 0 : t.Creatives) == null ? void 0 : a.Creative),
171
- wrapper: r ? {
172
- vastAdTagURI: t.VASTAdTagURI,
173
- followAdditionalWrappers: t["@_followAdditionalWrappers"] !== !1,
174
- allowMultipleAds: t["@_allowMultipleAds"],
175
- fallbackOnNoAd: t["@_fallbackOnNoAd"]
164
+ adTitle: n == null ? void 0 : n.AdTitle,
165
+ impressions: this.parseImpressions(n == null ? void 0 : n.Impression),
166
+ errors: this.parseErrors(n == null ? void 0 : n.Error),
167
+ creatives: this.parseCreatives((i = n == null ? void 0 : n.Creatives) == null ? void 0 : i.Creative),
168
+ wrapper: a ? {
169
+ vastAdTagURI: n.VASTAdTagURI,
170
+ followAdditionalWrappers: n["@_followAdditionalWrappers"] !== !1,
171
+ allowMultipleAds: n["@_allowMultipleAds"],
172
+ fallbackOnNoAd: n["@_fallbackOnNoAd"]
176
173
  } : void 0,
177
- inLine: r ? void 0 : {
178
- adTitle: (t == null ? void 0 : t.AdTitle) || "",
179
- description: t == null ? void 0 : t.Description,
180
- advertiser: t == null ? void 0 : t.Advertiser,
181
- creatives: this.parseCreatives((n = t == null ? void 0 : t.Creatives) == null ? void 0 : n.Creative)
174
+ inLine: a ? void 0 : {
175
+ adTitle: (n == null ? void 0 : n.AdTitle) || "",
176
+ description: n == null ? void 0 : n.Description,
177
+ advertiser: n == null ? void 0 : n.Advertiser,
178
+ creatives: this.parseCreatives((s = n == null ? void 0 : n.Creatives) == null ? void 0 : s.Creative)
182
179
  }
183
180
  };
184
181
  }
@@ -186,20 +183,20 @@ class A {
186
183
  * Parse Impression elements
187
184
  */
188
185
  parseImpressions(e) {
189
- return e ? (Array.isArray(e) ? e : [e]).map((t) => ({
190
- id: t["@_id"],
191
- url: typeof t == "string" ? t : t["#text"] || ""
186
+ return e ? (Array.isArray(e) ? e : [e]).map((i) => ({
187
+ id: i["@_id"],
188
+ url: typeof i == "string" ? i : i["#text"] || ""
192
189
  })) : [];
193
190
  }
194
191
  /**
195
192
  * Parse Creative elements
196
193
  */
197
194
  parseCreatives(e) {
198
- return e ? (Array.isArray(e) ? e : [e]).map((t) => ({
199
- id: t["@_id"],
200
- sequence: t["@_sequence"],
201
- adId: t["@_adId"],
202
- linear: t.Linear ? this.parseLinear(t.Linear) : void 0
195
+ return e ? (Array.isArray(e) ? e : [e]).map((i) => ({
196
+ id: i["@_id"],
197
+ sequence: i["@_sequence"],
198
+ adId: i["@_adId"],
199
+ linear: i.Linear ? this.parseLinear(i.Linear) : void 0
203
200
  })) : [];
204
201
  }
205
202
  /**
@@ -207,13 +204,13 @@ class A {
207
204
  */
208
205
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
209
206
  parseLinear(e) {
210
- var r, t;
207
+ var t, i;
211
208
  return {
212
209
  duration: this.parseDuration(e.Duration),
213
210
  skipOffset: e["@_skipoffset"] ? this.parseDuration(e["@_skipoffset"]) : void 0,
214
- mediaFiles: this.parseMediaFiles((r = e.MediaFiles) == null ? void 0 : r.MediaFile),
211
+ mediaFiles: this.parseMediaFiles((t = e.MediaFiles) == null ? void 0 : t.MediaFile),
215
212
  trackingEvents: this.parseTrackingEvents(
216
- (t = e.TrackingEvents) == null ? void 0 : t.Tracking
213
+ (i = e.TrackingEvents) == null ? void 0 : i.Tracking
217
214
  ),
218
215
  videoClicks: e.VideoClicks ? {
219
216
  clickThrough: e.VideoClicks.ClickThrough ? {
@@ -228,34 +225,34 @@ class A {
228
225
  * Parse MediaFile elements
229
226
  */
230
227
  parseMediaFiles(e) {
231
- return e ? (Array.isArray(e) ? e : [e]).map((t) => ({
232
- id: t["@_id"],
233
- url: typeof t == "string" ? t : t["#text"] || "",
234
- delivery: t["@_delivery"] || "progressive",
235
- type: t["@_type"] || "video/mp4",
236
- width: parseInt(t["@_width"], 10) || 0,
237
- height: parseInt(t["@_height"], 10) || 0,
238
- bitrate: t["@_bitrate"] ? parseInt(t["@_bitrate"], 10) : void 0,
239
- codec: t["@_codec"],
240
- scalable: t["@_scalable"],
241
- maintainAspectRatio: t["@_maintainAspectRatio"]
228
+ return e ? (Array.isArray(e) ? e : [e]).map((i) => ({
229
+ id: i["@_id"],
230
+ url: typeof i == "string" ? i : i["#text"] || "",
231
+ delivery: i["@_delivery"] || "progressive",
232
+ type: i["@_type"] || "video/mp4",
233
+ width: parseInt(i["@_width"], 10) || 0,
234
+ height: parseInt(i["@_height"], 10) || 0,
235
+ bitrate: i["@_bitrate"] ? parseInt(i["@_bitrate"], 10) : void 0,
236
+ codec: i["@_codec"],
237
+ scalable: i["@_scalable"],
238
+ maintainAspectRatio: i["@_maintainAspectRatio"]
242
239
  })) : [];
243
240
  }
244
241
  /**
245
242
  * Parse Tracking elements
246
243
  */
247
244
  parseTrackingEvents(e) {
248
- return e ? (Array.isArray(e) ? e : [e]).map((t) => ({
249
- event: t["@_event"],
250
- url: typeof t == "string" ? t : t["#text"] || "",
251
- offset: t["@_offset"] ? this.parseDuration(t["@_offset"]) : void 0
245
+ return e ? (Array.isArray(e) ? e : [e]).map((i) => ({
246
+ event: i["@_event"],
247
+ url: typeof i == "string" ? i : i["#text"] || "",
248
+ offset: i["@_offset"] ? this.parseDuration(i["@_offset"]) : void 0
252
249
  })) : [];
253
250
  }
254
251
  /**
255
252
  * Parse Error elements
256
253
  */
257
254
  parseErrors(e) {
258
- return e ? (Array.isArray(e) ? e : [e]).map((t) => typeof t == "string" ? t : t["#text"] || "") : [];
255
+ return e ? (Array.isArray(e) ? e : [e]).map((i) => typeof i == "string" ? i : i["#text"] || "") : [];
259
256
  }
260
257
  /**
261
258
  * Parse duration string (HH:MM:SS or seconds) to seconds
@@ -265,10 +262,10 @@ class A {
265
262
  if (typeof e != "string") return 0;
266
263
  if (e.endsWith("%"))
267
264
  return parseFloat(e) / 100;
268
- const r = e.match(/(\d+):(\d+):(\d+(?:\.\d+)?)/);
269
- if (r) {
270
- const [, t, s, a] = r;
271
- return parseInt(t, 10) * 3600 + parseInt(s, 10) * 60 + parseFloat(a);
265
+ const t = e.match(/(\d+):(\d+):(\d+(?:\.\d+)?)/);
266
+ if (t) {
267
+ const [, i, s, a] = t;
268
+ return parseInt(i, 10) * 3600 + parseInt(s, 10) * 60 + parseFloat(a);
272
269
  }
273
270
  return parseFloat(e) || 0;
274
271
  }
@@ -276,14 +273,14 @@ class A {
276
273
  * Select the best media file based on target bitrate
277
274
  * Prefers 1080p/720p over 4K for TV compatibility
278
275
  */
279
- selectBestMediaFile(e, r = 2500) {
276
+ selectBestMediaFile(e, t = 2500) {
280
277
  if (e.length === 0) return null;
281
- const t = e.filter(
278
+ const i = e.filter(
282
279
  (n) => n.type.includes("mp4") || n.type.includes("video/mp4")
283
280
  );
284
- return [...t.length > 0 ? t : e].sort((n, h) => {
285
- const p = n.bitrate || 0, f = h.bitrate || 0, E = n.height > 1080 ? 1e4 : 0, k = h.height > 1080 ? 1e4 : 0, w = Math.abs(p - r) + E, b = Math.abs(f - r) + k;
286
- return w - b;
281
+ return [...i.length > 0 ? i : e].sort((n, d) => {
282
+ const f = n.bitrate || 0, v = d.bitrate || 0, w = n.height > 1080 ? 1e4 : 0, k = d.height > 1080 ? 1e4 : 0, R = Math.abs(f - t) + w, S = Math.abs(v - t) + k;
283
+ return R - S;
287
284
  })[0] || null;
288
285
  }
289
286
  /**
@@ -291,21 +288,21 @@ class A {
291
288
  */
292
289
  aggregateTrackingEvents(e) {
293
290
  var t;
294
- const r = [];
291
+ const i = [];
295
292
  for (const s of e)
296
293
  for (const a of s.creatives)
297
- (t = a.linear) != null && t.trackingEvents && r.push(...a.linear.trackingEvents);
298
- return r;
294
+ (t = a.linear) != null && t.trackingEvents && i.push(...a.linear.trackingEvents);
295
+ return i;
299
296
  }
300
297
  /**
301
298
  * Get all impression URLs from parsed ads
302
299
  */
303
300
  aggregateImpressions(e) {
304
- const r = [];
305
- for (const t of e)
306
- for (const s of t.impressions)
307
- r.push(s.url);
308
- return r;
301
+ const t = [];
302
+ for (const i of e)
303
+ for (const s of i.impressions)
304
+ t.push(s.url);
305
+ return t;
309
306
  }
310
307
  /**
311
308
  * Debug logging
@@ -314,31 +311,31 @@ class A {
314
311
  this.config.debug && console.log(`[VASTParser] ${e}`);
315
312
  }
316
313
  }
317
- function m(i, e = {}) {
318
- let r = i;
319
- return r = r.replace(/\[TIMESTAMP\]/g, Date.now().toString()), r = r.replace(
314
+ function g(r, e = {}) {
315
+ let t = r;
316
+ return t = t.replace(/\[TIMESTAMP\]/g, Date.now().toString()), t = t.replace(
320
317
  /\[CACHEBUSTING\]/g,
321
318
  Math.random().toString(36).substring(2, 15)
322
- ), e.assetUri && (r = r.replace(
319
+ ), e.assetUri && (t = t.replace(
323
320
  /\[ASSETURI\]/g,
324
321
  encodeURIComponent(e.assetUri)
325
- )), e.contentPlayhead !== void 0 && (r = r.replace(
322
+ )), e.contentPlayhead !== void 0 && (t = t.replace(
326
323
  /\[CONTENTPLAYHEAD\]/g,
327
- v(e.contentPlayhead)
328
- )), e.adPlayhead !== void 0 && (r = r.replace(
324
+ E(e.contentPlayhead)
325
+ )), e.adPlayhead !== void 0 && (t = t.replace(
329
326
  /\[ADPLAYHEAD\]/g,
330
- v(e.adPlayhead)
331
- )), e.errorCode !== void 0 && (r = r.replace(/\[ERRORCODE\]/g, e.errorCode.toString())), e.breakPosition !== void 0 && (r = r.replace(
327
+ E(e.adPlayhead)
328
+ )), e.errorCode !== void 0 && (t = t.replace(/\[ERRORCODE\]/g, e.errorCode.toString())), e.breakPosition !== void 0 && (t = t.replace(
332
329
  /\[BREAKPOSITION\]/g,
333
330
  e.breakPosition.toString()
334
- )), e.adType && (r = r.replace(/\[ADTYPE\]/g, e.adType)), r;
331
+ )), e.adType && (t = t.replace(/\[ADTYPE\]/g, e.adType)), t;
335
332
  }
336
- function v(i) {
337
- const e = Math.floor(i / 3600), r = Math.floor(i % 3600 / 60), t = Math.floor(i % 60), s = Math.floor(i % 1 * 1e3);
338
- return e.toString().padStart(2, "0") + ":" + r.toString().padStart(2, "0") + ":" + t.toString().padStart(2, "0") + "." + s.toString().padStart(3, "0");
333
+ function E(r) {
334
+ const e = Math.floor(r / 3600), t = Math.floor(r % 3600 / 60), i = Math.floor(r % 60), s = Math.floor(r % 1 * 1e3);
335
+ return e.toString().padStart(2, "0") + ":" + t.toString().padStart(2, "0") + ":" + i.toString().padStart(2, "0") + "." + s.toString().padStart(3, "0");
339
336
  }
340
- var o = /* @__PURE__ */ ((i) => (i.WebOS = "webos", i.Tizen = "tizen", i.Vidaa = "vidaa", i.WhaleOS = "whaleos", i.FireTV = "firetv", i.Roku = "roku", i.Xbox = "xbox", i.PlayStation = "playstation", i.AndroidTV = "androidtv", i.Vizio = "vizio", i.Generic = "generic", i))(o || {}), c = /* @__PURE__ */ ((i) => (i.Enter = "enter", i.Back = "back", i.Left = "left", i.Right = "right", i.Up = "up", i.Down = "down", i.Play = "play", i.Pause = "pause", i.PlayPause = "playPause", i.Stop = "stop", i.FastForward = "fastForward", i.Rewind = "rewind", i.Menu = "menu", i.Info = "info", i.Red = "red", i.Green = "green", i.Yellow = "yellow", i.Blue = "blue", i.ChannelUp = "channelUp", i.ChannelDown = "channelDown", i.VolumeUp = "volumeUp", i.VolumeDown = "volumeDown", i.Mute = "mute", i))(c || {});
341
- const _ = {
337
+ var o = /* @__PURE__ */ ((r) => (r.WebOS = "webos", r.Tizen = "tizen", r.Vidaa = "vidaa", r.WhaleOS = "whaleos", r.FireTV = "firetv", r.Roku = "roku", r.Xbox = "xbox", r.PlayStation = "playstation", r.AndroidTV = "androidtv", r.Vizio = "vizio", r.Generic = "generic", r))(o || {}), u = /* @__PURE__ */ ((r) => (r.Enter = "enter", r.Back = "back", r.Left = "left", r.Right = "right", r.Up = "up", r.Down = "down", r.Play = "play", r.Pause = "pause", r.PlayPause = "playPause", r.Stop = "stop", r.FastForward = "fastForward", r.Rewind = "rewind", r.Menu = "menu", r.Info = "info", r.Red = "red", r.Green = "green", r.Yellow = "yellow", r.Blue = "blue", r.ChannelUp = "channelUp", r.ChannelDown = "channelDown", r.VolumeUp = "volumeUp", r.VolumeDown = "volumeDown", r.Mute = "mute", r))(u || {});
338
+ const O = {
342
339
  webos: {
343
340
  13: "enter",
344
341
  461: "back",
@@ -520,7 +517,7 @@ const _ = {
520
517
  /* Mute */
521
518
  // M key
522
519
  }
523
- }, P = {
520
+ }, I = {
524
521
  tizen: [
525
522
  /Tizen/i,
526
523
  /SMART-TV.*Samsung/i
@@ -575,14 +572,10 @@ const _ = {
575
572
  ],
576
573
  generic: []
577
574
  };
578
- class O {
575
+ var C = Object.defineProperty, M = (r, e, t) => e in r ? C(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t, h = (r, e, t) => M(r, typeof e != "symbol" ? e + "" : e, t);
576
+ class N {
579
577
  constructor() {
580
- l(this, "platform");
581
- l(this, "capabilities");
582
- l(this, "deviceInfo");
583
- l(this, "keyMap");
584
- l(this, "reverseKeyMap");
585
- this.platform = this.detectPlatform(), this.keyMap = _[this.platform], this.reverseKeyMap = this.buildReverseKeyMap(), this.capabilities = this.detectCapabilities(), this.deviceInfo = this.detectDeviceInfo();
578
+ h(this, "platform"), h(this, "capabilities"), h(this, "deviceInfo"), h(this, "keyMap"), h(this, "reverseKeyMap"), this.platform = this.detectPlatform(), this.keyMap = O[this.platform], this.reverseKeyMap = this.buildReverseKeyMap(), this.capabilities = this.detectCapabilities(), this.deviceInfo = this.detectDeviceInfo();
586
579
  }
587
580
  /**
588
581
  * Detect the current Smart TV platform using userAgent and global objects
@@ -590,16 +583,16 @@ class O {
590
583
  detectPlatform() {
591
584
  if (typeof window > "u" || typeof navigator > "u")
592
585
  return o.Generic;
593
- const e = navigator.userAgent, r = window;
594
- if (r.tizen)
586
+ const e = navigator.userAgent, t = window;
587
+ if (t.tizen)
595
588
  return o.Tizen;
596
- if (r.webOS || r.PalmSystem)
589
+ if (t.webOS || t.PalmSystem)
597
590
  return o.WebOS;
598
- for (const [t, s] of Object.entries(P))
599
- if (t !== o.Generic) {
591
+ for (const [i, s] of Object.entries(I))
592
+ if (i !== o.Generic) {
600
593
  for (const a of s)
601
594
  if (a.test(e))
602
- return t;
595
+ return i;
603
596
  }
604
597
  return o.Generic;
605
598
  }
@@ -607,11 +600,11 @@ class O {
607
600
  * Detect platform capabilities
608
601
  */
609
602
  detectCapabilities() {
610
- const e = typeof navigator < "u", r = typeof document < "u", t = typeof window < "u", s = {
603
+ const e = typeof navigator < "u", t = typeof document < "u", i = typeof window < "u", s = {
611
604
  sendBeacon: e && "sendBeacon" in navigator,
612
605
  fetchKeepalive: typeof fetch < "u",
613
606
  mutedAutoplayRequired: !0,
614
- fullscreen: r && ("fullscreenEnabled" in document || "webkitFullscreenEnabled" in document),
607
+ fullscreen: t && ("fullscreenEnabled" in document || "webkitFullscreenEnabled" in document),
615
608
  hardwareDecodeInfo: !1,
616
609
  hdr: !1,
617
610
  hdr10Plus: !1,
@@ -621,7 +614,7 @@ class O {
621
614
  vp9: this.isCodecSupported('video/webm; codecs="vp9"'),
622
615
  av1: this.isCodecSupported('video/mp4; codecs="av01.0.05M.08"'),
623
616
  maxResolution: this.detectMaxResolution(),
624
- touch: t && "ontouchstart" in window,
617
+ touch: i && "ontouchstart" in window,
625
618
  voice: !1
626
619
  };
627
620
  switch (this.platform) {
@@ -693,46 +686,46 @@ class O {
693
686
  * Detect device information
694
687
  */
695
688
  detectDeviceInfo() {
696
- var t, s, a;
697
- const e = {
689
+ var e, t, i;
690
+ const s = {
698
691
  platform: this.platform
699
692
  };
700
- typeof window < "u" && (e.screenWidth = (t = window.screen) == null ? void 0 : t.width, e.screenHeight = (s = window.screen) == null ? void 0 : s.height, e.devicePixelRatio = window.devicePixelRatio);
701
- const r = window;
702
- if (this.platform === o.Tizen && ((a = r.tizen) != null && a.systeminfo))
693
+ typeof window < "u" && (s.screenWidth = (e = window.screen) == null ? void 0 : e.width, s.screenHeight = (t = window.screen) == null ? void 0 : t.height, s.devicePixelRatio = window.devicePixelRatio);
694
+ const a = window;
695
+ if (this.platform === o.Tizen && ((i = a.tizen) != null && i.systeminfo))
703
696
  try {
704
- r.tizen.systeminfo.getPropertyValue("BUILD", (n) => {
705
- e.model = n.model, e.manufacturer = n.manufacturer || "Samsung";
697
+ a.tizen.systeminfo.getPropertyValue("BUILD", (n) => {
698
+ s.model = n.model, s.manufacturer = n.manufacturer || "Samsung";
706
699
  });
707
700
  } catch {
708
- e.manufacturer = "Samsung";
701
+ s.manufacturer = "Samsung";
709
702
  }
710
- if (this.platform === o.WebOS && r.webOSSystem)
703
+ if (this.platform === o.WebOS && a.webOSSystem)
711
704
  try {
712
- const n = r.webOSSystem.deviceInfo;
713
- e.model = n == null ? void 0 : n.modelName, e.manufacturer = "LG", e.osVersion = n == null ? void 0 : n.version;
705
+ const n = a.webOSSystem.deviceInfo;
706
+ s.model = n == null ? void 0 : n.modelName, s.manufacturer = "LG", s.osVersion = n == null ? void 0 : n.version;
714
707
  } catch {
715
- e.manufacturer = "LG";
708
+ s.manufacturer = "LG";
716
709
  }
717
- return e;
710
+ return s;
718
711
  }
719
712
  /**
720
713
  * Detect maximum supported resolution
721
714
  */
722
715
  detectMaxResolution() {
723
- var s, a;
716
+ var e, t;
724
717
  if (typeof window > "u") return "unknown";
725
- const e = ((s = window.screen) == null ? void 0 : s.width) || 0, r = ((a = window.screen) == null ? void 0 : a.height) || 0, t = Math.max(e, r);
726
- return t >= 3840 ? "4k" : t >= 1920 ? "1080p" : t >= 1280 ? "720p" : "unknown";
718
+ const i = ((e = window.screen) == null ? void 0 : e.width) || 0, s = ((t = window.screen) == null ? void 0 : t.height) || 0, a = Math.max(i, s);
719
+ return a >= 3840 ? "4k" : a >= 1920 ? "1080p" : a >= 1280 ? "720p" : "unknown";
727
720
  }
728
721
  /**
729
722
  * Build reverse mapping from KeyAction to key codes
730
723
  */
731
724
  buildReverseKeyMap() {
732
725
  const e = /* @__PURE__ */ new Map();
733
- for (const [r, t] of Object.entries(this.keyMap)) {
734
- const s = parseInt(r, 10), a = e.get(t) || [];
735
- a.push(s), e.set(t, a);
726
+ for (const [t, i] of Object.entries(this.keyMap)) {
727
+ const s = parseInt(t, 10), a = e.get(i) || [];
728
+ a.push(s), e.set(i, a);
736
729
  }
737
730
  return e;
738
731
  }
@@ -742,7 +735,8 @@ class O {
742
735
  * @returns KeyAction or null if not mapped
743
736
  */
744
737
  normalizeKeyCode(e) {
745
- return this.keyMap[e] ?? null;
738
+ var t;
739
+ return (t = this.keyMap[e]) != null ? t : null;
746
740
  }
747
741
  /**
748
742
  * Get all key codes that map to a specific action
@@ -760,8 +754,8 @@ class O {
760
754
  isCodecSupported(e) {
761
755
  if (typeof document > "u") return !1;
762
756
  try {
763
- const t = document.createElement("video").canPlayType(e);
764
- return t === "probably" || t === "maybe";
757
+ const i = document.createElement("video").canPlayType(e);
758
+ return i === "probably" || i === "maybe";
765
759
  } catch {
766
760
  return !1;
767
761
  }
@@ -785,9 +779,9 @@ class O {
785
779
  "ColorF2Yellow",
786
780
  "ColorF3Blue",
787
781
  "Info"
788
- ].forEach((t) => {
782
+ ].forEach((i) => {
789
783
  try {
790
- e.tvinputdevice.registerKey(t);
784
+ e.tvinputdevice.registerKey(i);
791
785
  } catch {
792
786
  }
793
787
  });
@@ -868,33 +862,51 @@ class O {
868
862
  };
869
863
  }
870
864
  }
865
+ /**
866
+ * Show debug message using platform-specific native notifications
867
+ * Falls back to console.log
868
+ */
869
+ debug(e) {
870
+ if (console.log(`[Adgent] ${e}`), this.platform === o.WebOS && typeof window < "u") {
871
+ const t = window;
872
+ t.webOS && t.webOS.service && t.webOS.service.request("luna://com.webos.notification", {
873
+ method: "createToast",
874
+ parameters: {
875
+ message: `[Adgent] ${e}`
876
+ },
877
+ onSuccess: () => {
878
+ },
879
+ onFailure: () => {
880
+ }
881
+ });
882
+ }
883
+ }
871
884
  }
872
- let g = null;
873
- function y() {
874
- return g || (g = new O()), g;
885
+ let y = null;
886
+ function _() {
887
+ return y || (y = new N()), y;
875
888
  }
876
- class x {
877
- constructor(e = [], r = {}) {
878
- l(this, "config");
879
- l(this, "trackingEvents");
880
- l(this, "firedEvents");
881
- l(this, "macroContext");
889
+ var F = Object.defineProperty, D = (r, e, t) => e in r ? F(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t, m = (r, e, t) => D(r, typeof e != "symbol" ? e + "" : e, t);
890
+ class L {
891
+ constructor(e = [], t = {}) {
892
+ m(this, "config"), m(this, "trackingEvents"), m(this, "firedEvents"), m(this, "macroContext");
893
+ var i, s, a;
882
894
  this.config = {
883
- debug: r.debug ?? !1,
884
- retry: r.retry ?? !1,
885
- maxRetries: r.maxRetries ?? 3
895
+ debug: (i = t.debug) != null ? i : !1,
896
+ retry: (s = t.retry) != null ? s : !1,
897
+ maxRetries: (a = t.maxRetries) != null ? a : 3
886
898
  }, this.trackingEvents = this.groupEventsByType(e), this.firedEvents = /* @__PURE__ */ new Set(), this.macroContext = {};
887
899
  }
888
900
  /**
889
901
  * Group tracking events by their event type
890
902
  */
891
903
  groupEventsByType(e) {
892
- const r = /* @__PURE__ */ new Map();
893
- for (const t of e) {
894
- const s = r.get(t.event) || [];
895
- s.push(t), r.set(t.event, s);
904
+ const t = /* @__PURE__ */ new Map();
905
+ for (const i of e) {
906
+ const s = t.get(i.event) || [];
907
+ s.push(i), t.set(i.event, s);
896
908
  }
897
- return r;
909
+ return t;
898
910
  }
899
911
  /**
900
912
  * Update macro context for URL replacement
@@ -907,20 +919,20 @@ class x {
907
919
  * @param eventType - The VAST event type to track
908
920
  * @param once - Only fire once per event type (default: true)
909
921
  */
910
- track(e, r = !0) {
911
- const t = this.trackingEvents.get(e);
912
- if (!t) {
922
+ track(e, t = !0) {
923
+ const i = this.trackingEvents.get(e);
924
+ if (!i) {
913
925
  this.log(`No tracking URLs for event: ${e}`);
914
926
  return;
915
927
  }
916
- for (const s of t) {
928
+ for (const s of i) {
917
929
  const a = `${e}:${s.url}`;
918
- if (r && this.firedEvents.has(a)) {
930
+ if (t && this.firedEvents.has(a)) {
919
931
  this.log(`Skipping duplicate event: ${e}`);
920
932
  continue;
921
933
  }
922
- const n = m(s.url, this.macroContext);
923
- this.firePixel(n), r && this.firedEvents.add(a);
934
+ const n = g(s.url, this.macroContext);
935
+ this.firePixel(n), t && this.firedEvents.add(a);
924
936
  }
925
937
  }
926
938
  /**
@@ -928,12 +940,12 @@ class x {
928
940
  * Uses sendBeacon when available, falls back to fetch with keepalive
929
941
  */
930
942
  firePixel(e) {
931
- const r = y();
943
+ const t = _();
932
944
  this.log(`Firing pixel: ${e}`);
933
945
  try {
934
- if (r.capabilities.sendBeacon && navigator.sendBeacon(e))
946
+ if (t.capabilities.sendBeacon && navigator.sendBeacon(e))
935
947
  return;
936
- if (r.capabilities.fetchKeepalive) {
948
+ if (t.capabilities.fetchKeepalive) {
937
949
  fetch(e, {
938
950
  method: "GET",
939
951
  keepalive: !0,
@@ -952,17 +964,17 @@ class x {
952
964
  * Image beacon fallback
953
965
  */
954
966
  fireImageBeacon(e) {
955
- const r = new Image(1, 1);
956
- r.src = e;
967
+ const t = new Image(1, 1);
968
+ t.src = e;
957
969
  }
958
970
  /**
959
971
  * Fire impression pixels
960
972
  * @param impressionUrls - Array of impression URLs
961
973
  */
962
974
  fireImpressions(e) {
963
- for (const r of e) {
964
- const t = m(r, this.macroContext);
965
- this.firePixel(t);
975
+ for (const t of e) {
976
+ const i = g(t, this.macroContext);
977
+ this.firePixel(i);
966
978
  }
967
979
  }
968
980
  /**
@@ -970,10 +982,10 @@ class x {
970
982
  * @param errorUrls - Array of error tracking URLs
971
983
  * @param errorCode - VAST error code
972
984
  */
973
- fireError(e, r) {
974
- const t = { ...this.macroContext, errorCode: r };
985
+ fireError(e, t) {
986
+ const i = { ...this.macroContext, errorCode: t };
975
987
  for (const s of e) {
976
- const a = m(s, t);
988
+ const a = g(s, i);
977
989
  this.firePixel(a);
978
990
  }
979
991
  }
@@ -990,34 +1002,22 @@ class x {
990
1002
  this.config.debug && console.log(`[AdTracker] ${e}`);
991
1003
  }
992
1004
  }
993
- const I = {
1005
+ var U = Object.defineProperty, W = (r, e, t) => e in r ? U(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t, l = (r, e, t) => W(r, typeof e != "symbol" ? e + "" : e, t);
1006
+ const B = {
994
1007
  targetBitrate: 2500,
995
1008
  maxWrapperDepth: 5,
996
1009
  timeout: 1e4,
997
1010
  debug: !1,
998
1011
  skipButtonText: "Skip Ad"
999
1012
  };
1000
- class N {
1013
+ class V {
1001
1014
  constructor(e) {
1002
- l(this, "config");
1003
- l(this, "platform");
1004
- l(this, "parser");
1005
- l(this, "videoElement", null);
1006
- l(this, "overlayElement", null);
1007
- l(this, "skipButtonElement", null);
1008
- l(this, "tracker", null);
1009
- l(this, "state");
1010
- l(this, "ads", []);
1011
- l(this, "listeners", /* @__PURE__ */ new Set());
1012
- l(this, "quartilesFired", /* @__PURE__ */ new Set());
1013
- l(this, "boundKeyHandler", null);
1014
- l(this, "focusTrap", null);
1015
- this.config = { ...I, ...e }, this.platform = y(), this.parser = new A({
1015
+ l(this, "config"), l(this, "platform"), l(this, "parser"), l(this, "videoElement", null), l(this, "overlayElement", null), l(this, "skipButtonElement", null), l(this, "progressElement", null), l(this, "tracker", null), l(this, "state"), l(this, "ads", []), l(this, "listeners", /* @__PURE__ */ new Set()), l(this, "quartilesFired", /* @__PURE__ */ new Set()), l(this, "boundKeyHandler", null), l(this, "focusTrap", null), this.config = { ...B, ...e }, this.platform = _(), this.parser = new A({
1016
1016
  maxWrapperDepth: this.config.maxWrapperDepth,
1017
1017
  timeout: this.config.timeout,
1018
1018
  debug: this.config.debug
1019
1019
  }), this.state = {
1020
- status: d.Idle,
1020
+ status: c.Idle,
1021
1021
  currentTime: 0,
1022
1022
  duration: 0,
1023
1023
  muted: !0,
@@ -1032,26 +1032,26 @@ class N {
1032
1032
  * Initialize the SDK: fetch VAST, create video element, attempt autoplay
1033
1033
  */
1034
1034
  async init() {
1035
- var e, r;
1035
+ var e, t;
1036
1036
  if (!this.config.container)
1037
1037
  throw new Error("Container element not found");
1038
- this.updateState({ status: d.Loading });
1038
+ this.updateState({ status: c.Loading });
1039
1039
  try {
1040
- const t = await this.parser.parse(this.config.vastUrl);
1041
- if (!t.success || !t.response)
1040
+ const i = await this.parser.parse(this.config.vastUrl);
1041
+ if (!i.success || !i.response)
1042
1042
  throw this.createError(
1043
- ((e = t.error) == null ? void 0 : e.code) || u.NO_VAST_RESPONSE,
1044
- ((r = t.error) == null ? void 0 : r.message) || "Failed to parse VAST"
1043
+ ((e = i.error) == null ? void 0 : e.code) || p.NO_VAST_RESPONSE,
1044
+ ((t = i.error) == null ? void 0 : t.message) || "Failed to parse VAST"
1045
1045
  );
1046
- if (this.ads = t.response.ads, this.ads.length === 0)
1046
+ if (this.ads = i.response.ads, this.ads.length === 0)
1047
1047
  throw this.createError(
1048
- u.NO_VAST_RESPONSE,
1048
+ p.NO_VAST_RESPONSE,
1049
1049
  "No ads in VAST response"
1050
1050
  );
1051
1051
  const s = this.getFirstLinearCreative();
1052
1052
  if (!s)
1053
1053
  throw this.createError(
1054
- u.GENERAL_LINEAR_ERROR,
1054
+ p.GENERAL_LINEAR_ERROR,
1055
1055
  "No linear creative found"
1056
1056
  );
1057
1057
  const a = this.parser.selectBestMediaFile(
@@ -1060,14 +1060,14 @@ class N {
1060
1060
  );
1061
1061
  if (!a)
1062
1062
  throw this.createError(
1063
- u.FILE_NOT_FOUND,
1063
+ p.FILE_NOT_FOUND,
1064
1064
  "No suitable media file found"
1065
1065
  );
1066
1066
  this.updateState({ mediaFile: a });
1067
1067
  const n = this.parser.aggregateTrackingEvents(this.ads);
1068
- this.tracker = new x(n, { debug: this.config.debug }), this.tracker.updateMacroContext({ assetUri: a.url }), this.createVideoElement(a), this.setupFocusManagement(), await this.attemptAutoplay();
1069
- } catch (t) {
1070
- const s = t instanceof Error ? this.createError(u.UNDEFINED_ERROR, t.message) : t;
1068
+ this.tracker = new L(n, { debug: this.config.debug }), this.tracker.updateMacroContext({ assetUri: a.url }), this.createVideoElement(a), this.setupFocusManagement(), await this.attemptAutoplay();
1069
+ } catch (i) {
1070
+ const s = i instanceof Error ? this.createError(p.UNDEFINED_ERROR, i.message) : i;
1071
1071
  this.handleError(s);
1072
1072
  }
1073
1073
  }
@@ -1076,9 +1076,9 @@ class N {
1076
1076
  */
1077
1077
  getFirstLinearCreative() {
1078
1078
  for (const e of this.ads)
1079
- for (const r of e.creatives)
1080
- if (r.linear)
1081
- return r.linear;
1079
+ for (const t of e.creatives)
1080
+ if (t.linear)
1081
+ return t.linear;
1082
1082
  return null;
1083
1083
  }
1084
1084
  /**
@@ -1086,37 +1086,39 @@ class N {
1086
1086
  * Applies muted, playsinline, autoplay for maximum TV compatibility
1087
1087
  */
1088
1088
  createVideoElement(e) {
1089
- const r = document.createElement("video"), t = this.platform.getVideoAttributes();
1090
- Object.entries(t).forEach(([s, a]) => {
1091
- typeof a == "boolean" ? a && r.setAttribute(s, "") : r.setAttribute(s, a);
1092
- }), r.src = e.url, r.style.cssText = `
1089
+ const t = document.createElement("video"), i = this.platform.getVideoAttributes();
1090
+ Object.entries(i).forEach(([a, n]) => {
1091
+ typeof n == "boolean" ? n && t.setAttribute(a, "") : t.setAttribute(a, n);
1092
+ }), t.removeAttribute("src"), t.innerHTML = "";
1093
+ const s = document.createElement("source");
1094
+ s.src = e.url, s.type = e.type || "video/mp4", t.appendChild(s), t.setAttribute("crossorigin", "anonymous"), t.style.cssText = `
1093
1095
  width: 100%;
1094
1096
  height: 100%;
1095
1097
  object-fit: contain;
1096
1098
  background: #000;
1097
- `, r.addEventListener("loadedmetadata", () => {
1099
+ `, t.addEventListener("loadedmetadata", () => {
1098
1100
  this.updateState({
1099
- duration: r.duration,
1100
- status: d.Ready
1101
+ duration: t.duration,
1102
+ status: c.Ready
1101
1103
  }), this.emit({ type: "loaded" });
1102
- }), r.addEventListener("timeupdate", () => {
1103
- this.handleTimeUpdate(r);
1104
- }), r.addEventListener("ended", () => {
1104
+ }), t.addEventListener("timeupdate", () => {
1105
+ this.handleTimeUpdate(t);
1106
+ }), t.addEventListener("ended", () => {
1105
1107
  this.handleComplete();
1106
- }), r.addEventListener("error", () => {
1107
- const s = r.error;
1108
+ }), t.addEventListener("error", () => {
1109
+ const a = t.error;
1108
1110
  this.handleError(
1109
1111
  this.createError(
1110
- u.MEDIA_NOT_SUPPORTED,
1111
- (s == null ? void 0 : s.message) || "Video playback error"
1112
+ p.MEDIA_NOT_SUPPORTED,
1113
+ (a == null ? void 0 : a.message) || "Video playback error"
1112
1114
  )
1113
1115
  );
1114
- }), r.addEventListener("play", () => {
1115
- this.updateState({ status: d.Playing });
1116
- }), r.addEventListener("pause", () => {
1117
- var s;
1118
- this.state.status !== d.Completed && (this.updateState({ status: d.Paused }), this.emit({ type: "pause" }), (s = this.tracker) == null || s.track("pause"));
1119
- }), this.config.container.appendChild(r), this.videoElement = r, this.log(`Video element created with src: ${e.url}`);
1116
+ }), t.addEventListener("play", () => {
1117
+ this.updateState({ status: c.Playing });
1118
+ }), t.addEventListener("pause", () => {
1119
+ var a;
1120
+ this.state.status !== c.Completed && (this.updateState({ status: c.Paused }), this.emit({ type: "pause" }), (a = this.tracker) == null || a.track("pause"));
1121
+ }), this.config.container.appendChild(t), this.videoElement = t, this.log(`Video element created with src: ${e.url}`);
1120
1122
  }
1121
1123
  /**
1122
1124
  * Attempt autoplay with soft-fail handling
@@ -1134,7 +1136,7 @@ class N {
1134
1136
  * Show interactive overlay for manual ad start (autoplay fallback)
1135
1137
  */
1136
1138
  showStartOverlay() {
1137
- if (this.updateState({ status: d.WaitingForInteraction }), this.config.customStartOverlay) {
1139
+ if (this.updateState({ status: c.WaitingForInteraction }), this.config.customStartOverlay) {
1138
1140
  this.overlayElement = this.config.customStartOverlay, this.config.container.appendChild(this.overlayElement);
1139
1141
  return;
1140
1142
  }
@@ -1146,28 +1148,32 @@ class N {
1146
1148
  left: 0;
1147
1149
  width: 100%;
1148
1150
  height: 100%;
1149
- display: flex;
1150
- align-items: center;
1151
- justify-content: center;
1152
- background: rgba(0, 0, 0, 0.7);
1151
+ display: table;
1152
+ background: rgba(0, 0, 0, 0.5);
1153
1153
  z-index: 100;
1154
1154
  ">
1155
- <button id="adgent-start-btn" style="
1156
- padding: 20px 40px;
1157
- font-size: 24px;
1158
- background: #fff;
1159
- color: #000;
1160
- border: none;
1161
- border-radius: 8px;
1162
- cursor: pointer;
1163
- font-weight: bold;
1164
- ">
1165
- Start Ad
1166
- </button>
1155
+ <div style="display: table-cell; vertical-align: middle; text-align: center;">
1156
+ <button id="adgent-start-btn" style="
1157
+ width: 80px;
1158
+ height: 80px;
1159
+ background: rgba(0, 0, 0, 0.7);
1160
+ border: 3px solid #fff;
1161
+ border-radius: 50%;
1162
+ cursor: pointer;
1163
+ display: inline-block;
1164
+ line-height: 80px;
1165
+ text-align: center;
1166
+ color: #fff;
1167
+ font-size: 40px;
1168
+ padding: 0 0 0 8px; /* Optical center for triangle */
1169
+ ">
1170
+
1171
+ </button>
1172
+ </div>
1167
1173
  </div>
1168
1174
  `, e.style.cssText = "position: absolute; top: 0; left: 0; width: 100%; height: 100%;";
1169
- const r = e.querySelector("#adgent-start-btn");
1170
- r == null || r.addEventListener("click", () => this.onStartClick()), this.config.container.style.position = "relative", this.config.container.appendChild(e), this.overlayElement = e, r == null || r.focus();
1175
+ const t = e.querySelector("#adgent-start-btn");
1176
+ t == null || t.addEventListener("click", () => this.onStartClick()), this.config.container.style.position = "relative", this.config.container.appendChild(e), this.overlayElement = e, t == null || t.focus();
1171
1177
  }
1172
1178
  /**
1173
1179
  * Handle start button click (from overlay)
@@ -1179,7 +1185,7 @@ class N {
1179
1185
  } catch (e) {
1180
1186
  this.handleError(
1181
1187
  this.createError(
1182
- u.GENERAL_LINEAR_ERROR,
1188
+ p.GENERAL_LINEAR_ERROR,
1183
1189
  `Playback failed: ${e}`
1184
1190
  )
1185
1191
  );
@@ -1195,30 +1201,30 @@ class N {
1195
1201
  * Handle successful playback start
1196
1202
  */
1197
1203
  handlePlaybackStart() {
1198
- var r, t, s, a, n;
1199
- this.updateState({ status: d.Playing }), this.emit({ type: "start" }), (t = (r = this.config).onStart) == null || t.call(r);
1200
- const e = this.parser.aggregateImpressions(this.ads);
1201
- (s = this.tracker) == null || s.fireImpressions(e), (a = this.tracker) == null || a.track("start"), (n = this.tracker) == null || n.track("creativeView"), this.setupSkipButton(), this.log("Playback started");
1204
+ var e, t, i, s, a;
1205
+ this.updateState({ status: c.Playing }), this.emit({ type: "start" }), (t = (e = this.config).onStart) == null || t.call(e);
1206
+ const n = this.parser.aggregateImpressions(this.ads);
1207
+ (i = this.tracker) == null || i.fireImpressions(n), (s = this.tracker) == null || s.track("start"), (a = this.tracker) == null || a.track("creativeView"), this.setupSkipButton(), this.setupProgressUI(), this.log("Playback started");
1202
1208
  }
1203
1209
  /**
1204
1210
  * Handle time updates for progress tracking
1205
1211
  */
1206
1212
  handleTimeUpdate(e) {
1207
- var h, p, f;
1208
- const r = e.currentTime, t = e.duration;
1209
- if (!t || isNaN(t)) return;
1210
- const s = r / t * 100, a = this.calculateQuartile(s);
1213
+ var t, i, s;
1214
+ const a = e.currentTime, n = e.duration;
1215
+ if (!n || isNaN(n)) return;
1216
+ const d = a / n * 100, f = this.calculateQuartile(d);
1211
1217
  this.updateState({
1212
- currentTime: r,
1213
- duration: t
1214
- }), this.updateSkipCountdown(r), (h = this.tracker) == null || h.updateMacroContext({ adPlayhead: r });
1215
- const n = {
1216
- currentTime: r,
1217
- duration: t,
1218
- percentage: s,
1219
- quartile: a
1218
+ currentTime: a,
1219
+ duration: n
1220
+ }), this.updateSkipCountdown(a), (t = this.tracker) == null || t.updateMacroContext({ adPlayhead: a }), this.updateProgressUI(a, n);
1221
+ const v = {
1222
+ currentTime: a,
1223
+ duration: n,
1224
+ percentage: d,
1225
+ quartile: f
1220
1226
  };
1221
- this.emit({ type: "progress", data: n }), (f = (p = this.config).onProgress) == null || f.call(p, n), this.fireQuartileEvents(s);
1227
+ this.emit({ type: "progress", data: v }), (s = (i = this.config).onProgress) == null || s.call(i, v), this.fireQuartileEvents(d);
1222
1228
  }
1223
1229
  /**
1224
1230
  * Calculate current quartile (0-4)
@@ -1231,24 +1237,25 @@ class N {
1231
1237
  */
1232
1238
  fireQuartileEvents(e) {
1233
1239
  var t;
1234
- const r = [
1240
+ const i = [
1235
1241
  { threshold: 25, event: "firstQuartile" },
1236
1242
  { threshold: 50, event: "midpoint" },
1237
1243
  { threshold: 75, event: "thirdQuartile" }
1238
1244
  ];
1239
- for (const { threshold: s, event: a } of r)
1245
+ for (const { threshold: s, event: a } of i)
1240
1246
  e >= s && !this.quartilesFired.has(s) && (this.quartilesFired.add(s), (t = this.tracker) == null || t.track(a), this.emit({ type: "quartile", data: { quartile: a } }), this.log(`Quartile fired: ${a}`));
1241
1247
  }
1242
1248
  /**
1243
1249
  * Set up skip button
1244
1250
  */
1245
1251
  setupSkipButton() {
1246
- const e = this.getFirstLinearCreative(), r = this.config.skipOffset ?? (e == null ? void 0 : e.skipOffset);
1247
- if (!r || r <= 0)
1252
+ var e;
1253
+ const t = this.getFirstLinearCreative(), i = (e = this.config.skipOffset) != null ? e : t == null ? void 0 : t.skipOffset;
1254
+ if (!i || i <= 0)
1248
1255
  return;
1249
- this.updateState({ skipCountdown: r, canSkip: !1 });
1250
- const t = document.createElement("button");
1251
- t.id = "adgent-skip-btn", t.style.cssText = `
1256
+ this.updateState({ skipCountdown: i, canSkip: !1 });
1257
+ const s = document.createElement("button");
1258
+ s.id = "adgent-skip-btn", s.style.cssText = `
1252
1259
  position: absolute;
1253
1260
  bottom: 20px;
1254
1261
  right: 20px;
@@ -1261,80 +1268,112 @@ class N {
1261
1268
  cursor: pointer;
1262
1269
  z-index: 101;
1263
1270
  transition: opacity 0.3s;
1264
- `, t.textContent = `Skip in ${r}s`, t.addEventListener("click", () => this.skip()), this.config.container.appendChild(t), this.skipButtonElement = t;
1271
+ `, s.textContent = `Skip in ${i}s`, s.addEventListener("click", () => this.skip()), this.config.container.appendChild(s), this.skipButtonElement = s;
1265
1272
  }
1266
1273
  /**
1267
1274
  * Update skip countdown
1268
1275
  */
1269
1276
  updateSkipCountdown(e) {
1270
- const r = this.getFirstLinearCreative(), t = this.config.skipOffset ?? (r == null ? void 0 : r.skipOffset);
1271
- if (!t || !this.skipButtonElement) return;
1272
- const s = Math.max(0, t - e);
1273
- this.updateState({ skipCountdown: s }), s <= 0 && !this.state.canSkip ? (this.updateState({ canSkip: !0 }), this.skipButtonElement.textContent = this.config.skipButtonText, this.skipButtonElement.style.opacity = "1") : s > 0 && (this.skipButtonElement.textContent = `Skip in ${Math.ceil(s)}s`, this.skipButtonElement.style.opacity = "0.6");
1277
+ var t;
1278
+ const i = this.getFirstLinearCreative(), s = (t = this.config.skipOffset) != null ? t : i == null ? void 0 : i.skipOffset;
1279
+ if (!s || !this.skipButtonElement) return;
1280
+ const a = Math.max(0, s - e);
1281
+ this.updateState({ skipCountdown: a }), a <= 0 && !this.state.canSkip ? (this.updateState({ canSkip: !0 }), this.skipButtonElement.textContent = this.config.skipButtonText, this.skipButtonElement.style.opacity = "1", this.skipButtonElement.focus()) : a > 0 && (this.skipButtonElement.textContent = `Skip in ${Math.ceil(a)}s`, this.skipButtonElement.style.opacity = "0.6");
1274
1282
  }
1275
1283
  /**
1276
1284
  * Skip the ad
1277
1285
  */
1278
1286
  skip() {
1279
- var e, r, t;
1287
+ var e, t, i;
1280
1288
  if (!this.state.canSkip) {
1281
1289
  this.log("Skip not available yet");
1282
1290
  return;
1283
1291
  }
1284
- (e = this.tracker) == null || e.track("skip"), this.emit({ type: "skip" }), (t = (r = this.config).onSkip) == null || t.call(r), this.destroy(), this.log("Ad skipped");
1292
+ (e = this.tracker) == null || e.track("skip"), this.emit({ type: "skip" }), (i = (t = this.config).onSkip) == null || i.call(t), this.destroy(), this.log("Ad skipped");
1285
1293
  }
1286
1294
  /**
1287
1295
  * Handle ad completion
1288
1296
  */
1289
1297
  handleComplete() {
1290
- var e, r, t;
1291
- this.updateState({ status: d.Completed }), (e = this.tracker) == null || e.track("complete"), this.emit({ type: "complete" }), (t = (r = this.config).onComplete) == null || t.call(r), this.log("Ad completed");
1298
+ var e, t, i;
1299
+ this.updateState({ status: c.Completed }), (e = this.tracker) == null || e.track("complete"), this.emit({ type: "complete" }), (i = (t = this.config).onComplete) == null || i.call(t), this.log("Ad completed");
1292
1300
  }
1293
1301
  /**
1294
1302
  * Handle errors with recovery attempt or callback
1295
1303
  */
1296
1304
  handleError(e) {
1297
- var t, s, a;
1305
+ var t, i, s;
1298
1306
  this.updateState({
1299
- status: d.Error,
1307
+ status: c.Error,
1300
1308
  error: e
1301
1309
  });
1302
- const r = [];
1310
+ const a = [];
1303
1311
  for (const n of this.ads)
1304
- r.push(...n.errors);
1305
- (t = this.tracker) == null || t.fireError(r, e.code), this.emit({ type: "error", data: e }), (a = (s = this.config).onError) == null || a.call(s, e), this.log(`Error: ${e.message}`);
1312
+ a.push(...n.errors);
1313
+ (t = this.tracker) == null || t.fireError(a, e.code), this.emit({ type: "error", data: e }), (s = (i = this.config).onError) == null || s.call(i, e), this.log(`Error: ${e.message}`);
1306
1314
  }
1307
1315
  /**
1308
1316
  * Set up focus management to capture remote keys
1309
1317
  */
1310
1318
  setupFocusManagement() {
1311
1319
  this.focusTrap = document.createElement("div"), this.focusTrap.tabIndex = 0, this.focusTrap.style.cssText = "position: absolute; opacity: 0; width: 0; height: 0;", this.config.container.appendChild(this.focusTrap), this.focusTrap.focus(), this.boundKeyHandler = (e) => {
1312
- const r = this.platform.normalizeKeyCode(e.keyCode);
1313
- r && (e.preventDefault(), e.stopPropagation(), this.handleKeyAction(r));
1320
+ const t = this.platform.normalizeKeyCode(e.keyCode);
1321
+ t && (e.preventDefault(), e.stopPropagation(), this.handleKeyAction(t));
1314
1322
  }, document.addEventListener("keydown", this.boundKeyHandler, !0);
1315
1323
  }
1324
+ /**
1325
+ * Set up progress UI in top-left
1326
+ */
1327
+ setupProgressUI() {
1328
+ const e = document.createElement("div");
1329
+ e.style.cssText = `
1330
+ position: absolute;
1331
+ top: 20px;
1332
+ left: 20px;
1333
+ background: rgba(0, 0, 0, 0.7);
1334
+ color: #fff;
1335
+ padding: 6px 12px;
1336
+ border-radius: 4px;
1337
+ font-size: 14px;
1338
+ font-family: sans-serif;
1339
+ z-index: 101;
1340
+ display: block;
1341
+ white-space: nowrap;
1342
+ `, e.innerHTML = `
1343
+ <span style="display: inline-block; vertical-align: middle; margin-right: 8px; background: #f4b400; color: #000; padding: 2px 4px; border-radius: 2px; font-weight: bold; font-size: 12px;">Ad</span>
1344
+ <span id="adgent-progress-text" style="display: inline-block; vertical-align: middle;">1 of ${this.ads.length} • 0:00</span>
1345
+ `, this.config.container.appendChild(e), this.progressElement = e;
1346
+ }
1347
+ /**
1348
+ * Update progress UI text
1349
+ */
1350
+ updateProgressUI(e, t) {
1351
+ if (!this.progressElement) return;
1352
+ const i = Math.ceil(t - e), s = Math.floor(i / 60), a = i % 60, n = `${s}:${a.toString().padStart(2, "0")}`, d = this.progressElement.querySelector("#adgent-progress-text");
1353
+ d && (d.textContent = `1 of ${this.ads.length} • ${n}`);
1354
+ }
1316
1355
  /**
1317
1356
  * Handle key actions from remote control
1318
1357
  */
1319
1358
  handleKeyAction(e) {
1320
- var r, t;
1359
+ var t, i;
1321
1360
  switch (this.log(`Key action: ${e}`), e) {
1322
- case c.Enter:
1323
- this.state.status === d.WaitingForInteraction ? this.onStartClick() : this.state.canSkip && this.skip();
1361
+ case u.Enter:
1362
+ this.state.status === c.WaitingForInteraction ? this.onStartClick() : this.state.canSkip && this.skip();
1324
1363
  break;
1325
- case c.Back:
1364
+ case u.Back:
1326
1365
  this.log("Back pressed - ignoring during ad");
1327
1366
  break;
1328
- case c.Play:
1329
- (r = this.videoElement) == null || r.play();
1367
+ case u.Play:
1368
+ (t = this.videoElement) == null || t.play();
1330
1369
  break;
1331
- case c.Pause:
1332
- (t = this.videoElement) == null || t.pause();
1370
+ case u.Pause:
1371
+ (i = this.videoElement) == null || i.pause();
1333
1372
  break;
1334
- case c.Left:
1335
- case c.Right:
1336
- case c.Up:
1337
- case c.Down:
1373
+ case u.Left:
1374
+ case u.Right:
1375
+ case u.Up:
1376
+ case u.Down:
1338
1377
  break;
1339
1378
  }
1340
1379
  }
@@ -1368,8 +1407,8 @@ class N {
1368
1407
  * Clean up all resources
1369
1408
  */
1370
1409
  destroy() {
1371
- var e, r, t, s, a;
1372
- this.boundKeyHandler && (document.removeEventListener("keydown", this.boundKeyHandler, !0), this.boundKeyHandler = null), (e = this.videoElement) == null || e.remove(), (r = this.overlayElement) == null || r.remove(), (t = this.skipButtonElement) == null || t.remove(), (s = this.focusTrap) == null || s.remove(), this.videoElement = null, this.overlayElement = null, this.skipButtonElement = null, this.focusTrap = null, (a = this.tracker) == null || a.reset(), this.quartilesFired.clear(), this.listeners.clear(), this.ads = [], this.emit({ type: "destroy" }), this.log("Player destroyed");
1410
+ var e, t, i, s, a, n;
1411
+ this.boundKeyHandler && (document.removeEventListener("keydown", this.boundKeyHandler, !0), this.boundKeyHandler = null), (e = this.videoElement) == null || e.remove(), (t = this.overlayElement) == null || t.remove(), (i = this.skipButtonElement) == null || i.remove(), (s = this.progressElement) == null || s.remove(), (a = this.focusTrap) == null || a.remove(), this.videoElement = null, this.overlayElement = null, this.skipButtonElement = null, this.progressElement = null, this.focusTrap = null, (n = this.tracker) == null || n.reset(), this.quartilesFired.clear(), this.listeners.clear(), this.ads = [], this.emit({ type: "destroy" }), this.log("Player destroyed");
1373
1412
  }
1374
1413
  /**
1375
1414
  * Update internal state
@@ -1381,38 +1420,38 @@ class N {
1381
1420
  * Emit event to listeners
1382
1421
  */
1383
1422
  emit(e) {
1384
- for (const r of this.listeners)
1423
+ for (const t of this.listeners)
1385
1424
  try {
1386
- r(e);
1387
- } catch (t) {
1388
- this.log(`Listener error: ${t}`);
1425
+ t(e);
1426
+ } catch (i) {
1427
+ this.log(`Listener error: ${i}`);
1389
1428
  }
1390
1429
  }
1391
1430
  /**
1392
1431
  * Create error object
1393
1432
  */
1394
- createError(e, r, t = !1) {
1395
- return { code: e, message: r, recoverable: t };
1433
+ createError(e, t, i = !1) {
1434
+ return { code: e, message: t, recoverable: i };
1396
1435
  }
1397
1436
  /**
1398
1437
  * Debug logging
1399
1438
  */
1400
1439
  log(e) {
1401
- this.config.debug && console.log(`[AdPlayer] ${e}`);
1440
+ this.config.debug && this.platform.debug(e);
1402
1441
  }
1403
1442
  }
1404
1443
  export {
1405
- N as AdPlayer,
1406
- x as AdTracker,
1407
- N as AdgentSDK,
1408
- _ as DEFAULT_KEY_CODES,
1409
- c as KeyAction,
1410
- P as PLATFORM_DETECTION_PATTERNS,
1444
+ V as AdPlayer,
1445
+ L as AdTracker,
1446
+ V as AdgentSDK,
1447
+ O as DEFAULT_KEY_CODES,
1448
+ u as KeyAction,
1449
+ I as PLATFORM_DETECTION_PATTERNS,
1411
1450
  o as Platform,
1412
- O as PlatformAdapter,
1413
- d as PlaybackStatus,
1414
- u as VASTErrorCode,
1451
+ N as PlatformAdapter,
1452
+ c as PlaybackStatus,
1453
+ p as VASTErrorCode,
1415
1454
  A as VASTParser,
1416
- y as getPlatformAdapter,
1417
- m as replaceMacros
1455
+ _ as getPlatformAdapter,
1456
+ g as replaceMacros
1418
1457
  };