@firstlook-uat/sdk 0.2.0 โ†’ 0.3.0

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,11 +1,11 @@
1
- const y = [
1
+ const T = [
2
2
  'input[type="password"]',
3
3
  "[data-sensitive]",
4
4
  "[data-mask]",
5
5
  ".uat-mask"
6
6
  ];
7
- function S(a) {
8
- var t, e, s, i, n, o, c, l, h, d;
7
+ function C(a) {
8
+ var t, e, s, i, n, o, l, c, d, h, p;
9
9
  if (!a.endpoint)
10
10
  throw new Error("[FirstLook] 'endpoint' is required. Set your Supabase ingest-session URL.");
11
11
  return {
@@ -19,17 +19,18 @@ function S(a) {
19
19
  tapCount: ((t = a.triggers) == null ? void 0 : t.tapCount) ?? 5,
20
20
  deepLink: ((e = a.triggers) == null ? void 0 : e.deepLink) ?? !0,
21
21
  shake: ((s = a.triggers) == null ? void 0 : s.shake) ?? !0,
22
- customCheck: (i = a.triggers) == null ? void 0 : i.customCheck
22
+ keyboard: ((i = a.triggers) == null ? void 0 : i.keyboard) ?? !0,
23
+ customCheck: (n = a.triggers) == null ? void 0 : n.customCheck
23
24
  },
24
25
  security: {
25
- watermark: ((n = a.security) == null ? void 0 : n.watermark) ?? !0,
26
- maskSelectors: ((o = a.security) == null ? void 0 : o.maskSelectors) ?? y
26
+ watermark: ((o = a.security) == null ? void 0 : o.watermark) ?? !0,
27
+ maskSelectors: ((l = a.security) == null ? void 0 : l.maskSelectors) ?? T
27
28
  },
28
29
  recording: {
29
30
  domSnapshot: ((c = a.recording) == null ? void 0 : c.domSnapshot) ?? !0,
30
- voice: ((l = a.recording) == null ? void 0 : l.voice) ?? !0,
31
+ voice: ((d = a.recording) == null ? void 0 : d.voice) ?? !0,
31
32
  maxDuration: ((h = a.recording) == null ? void 0 : h.maxDuration) ?? 600,
32
- snapshotInterval: ((d = a.recording) == null ? void 0 : d.snapshotInterval) ?? 1e3
33
+ snapshotInterval: ((p = a.recording) == null ? void 0 : p.snapshotInterval) ?? 1e3
33
34
  }
34
35
  };
35
36
  }
@@ -44,7 +45,7 @@ function w() {
44
45
  touchSupport: "ontouchstart" in window || navigator.maxTouchPoints > 0
45
46
  };
46
47
  }
47
- class T {
48
+ class q {
48
49
  constructor() {
49
50
  this.listeners = /* @__PURE__ */ new Map();
50
51
  }
@@ -75,7 +76,7 @@ class T {
75
76
  this.listeners.clear();
76
77
  }
77
78
  }
78
- class C {
79
+ class I {
79
80
  constructor(t) {
80
81
  this.events = t, this.quests = [], this.results = [], this.currentIndex = -1, this.sessionStartTime = 0, this.blocked = !1, this.pendingFeedbacks = [];
81
82
  }
@@ -112,8 +113,10 @@ class C {
112
113
  status: "COMPLETED",
113
114
  timestamp: Date.now(),
114
115
  relativeTime: Date.now() - this.sessionStartTime,
115
- voiceMemoBlob: e,
116
+ voiceMemoBlob: e == null ? void 0 : e.voiceMemo,
116
117
  logs: t,
118
+ comment: e == null ? void 0 : e.comment,
119
+ concern: (e == null ? void 0 : e.concern) ?? !1,
117
120
  feedbacks: this.drainFeedbacks()
118
121
  };
119
122
  return this.results.push(i), this.events.emit({ type: "quest:completed", questId: s.id }), this.advance(), i;
@@ -129,6 +132,7 @@ class C {
129
132
  voiceMemoBlob: s,
130
133
  logs: t,
131
134
  comment: e,
135
+ concern: !1,
132
136
  feedbacks: this.drainFeedbacks()
133
137
  };
134
138
  return this.results.push(n), this.events.emit({ type: "quest:failed", questId: i.id }), i.blocking ? (this.blocked = !0, this.events.emit({ type: "quest:blocked", questId: i.id })) : this.advance(), n;
@@ -157,16 +161,19 @@ function r(a, t, e) {
157
161
  typeof i == "string" ? s.appendChild(document.createTextNode(i)) : s.appendChild(i);
158
162
  return s;
159
163
  }
160
- function I() {
164
+ function M() {
161
165
  return `fl_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
162
166
  }
163
- function q(a) {
167
+ function E(a) {
164
168
  const t = Math.floor(a / 60), e = a % 60;
165
169
  return `${t.toString().padStart(2, "0")}:${e.toString().padStart(2, "0")}`;
166
170
  }
167
- class M {
171
+ class R {
168
172
  constructor(t, e) {
169
- this.shadowRoot = t, this.callbacks = e, this.minimized = !1, this.timerInterval = null, this.startTime = 0, this.root = document.createElement("div"), this.root.className = "fl-quest-overlay", this.shadowRoot.appendChild(this.root);
173
+ this.shadowRoot = t, this.callbacks = e, this.minimized = !1, this.timerInterval = null, this.startTime = 0, this.root = document.createElement("div"), this.root.className = "fl-quest-overlay";
174
+ for (const s of ["click", "mousedown", "mouseup", "pointerdown", "pointerup", "touchstart", "touchend"])
175
+ this.root.addEventListener(s, (i) => i.stopPropagation());
176
+ this.shadowRoot.appendChild(this.root);
170
177
  }
171
178
  renderQuest(t, e, s) {
172
179
  this.minimized = !1, this.root.className = "fl-quest-overlay", this.root.innerHTML = "";
@@ -178,64 +185,95 @@ class M {
178
185
  this.createMinimizeBtn()
179
186
  ]);
180
187
  this.root.appendChild(n);
181
- const o = r("div", { className: "fl-quest-content" }), c = r("div", { className: "fl-quest-progress" });
182
- for (const f of e) {
183
- const m = f === "COMPLETED" ? "fl-completed" : f === "FAILED" ? "fl-failed" : f === "ACTIVE" ? "fl-active" : "";
184
- c.appendChild(r("div", { className: `fl-quest-progress-dot ${m}` }));
188
+ const o = r("div", { className: "fl-quest-content" }), l = r("div", { className: "fl-quest-progress" });
189
+ for (const p of e) {
190
+ const g = p === "COMPLETED" ? "fl-completed" : p === "FAILED" ? "fl-failed" : p === "ACTIVE" ? "fl-active" : "";
191
+ l.appendChild(r("div", { className: `fl-quest-progress-dot ${g}` }));
185
192
  }
186
- const l = r("div", { className: "fl-quest-body" }, [
187
- c,
193
+ const c = r("div", { className: "fl-quest-body" }, [
194
+ l,
188
195
  r("p", { className: "fl-quest-description" }, [t.description]),
189
196
  r("div", { className: "fl-quest-memo-row" }, [
190
- this.createButton("fl-btn fl-btn-memo", "๐Ÿ“ ใƒกใƒข", () => this.renderFeedbackModal(t.title))
197
+ this.createButton("fl-btn fl-btn-memo", "๐Ÿ“ ใƒกใƒขใ‚’ๆฎ‹ใ™", () => this.renderFeedbackModal(t.title))
191
198
  ]),
192
199
  r("div", { className: "fl-quest-actions" }, [
193
- this.createButton("fl-btn fl-btn-ok", "โœ“ OK", this.callbacks.onOk),
200
+ this.createButton("fl-btn fl-btn-ok", "โœ“ OK", () => this.renderFeedbackModal(t.title, "ok")),
201
+ this.createButton("fl-btn fl-btn-concern", "โš  ๆฐ—ใซใชใ‚‹", () => this.renderFeedbackModal(t.title, "concern")),
194
202
  this.createButton("fl-btn fl-btn-ng", "โœ— NG", this.callbacks.onNg)
195
203
  ])
196
204
  ]);
197
- o.appendChild(l), s && o.appendChild(
205
+ o.appendChild(c), s && o.appendChild(
198
206
  r("div", { className: "fl-voice-indicator" }, [
199
207
  r("span", { className: "fl-voice-dot" }),
200
208
  "Recording..."
201
209
  ])
202
210
  );
203
- const h = r("div", { className: "fl-status-bar" });
204
- s && h.appendChild(
211
+ const d = r("div", { className: "fl-status-bar" });
212
+ s && d.appendChild(
205
213
  r("span", { className: "fl-status-recording" }, [
206
214
  r("span", { className: "fl-voice-dot" }),
207
215
  "REC"
208
216
  ])
209
217
  );
210
- const d = r("span", { className: "fl-status-timer" }, ["00:00"]);
211
- h.appendChild(d), o.appendChild(h), this.root.appendChild(o), this.startTimer(d), this.root.onclick = () => {
212
- this.minimized && (this.minimized = !1, this.root.className = "fl-quest-overlay", this.root.innerHTML = "", this.root.appendChild(n), this.root.appendChild(o), this.startTimer(d));
218
+ const h = r("span", { className: "fl-status-timer" }, ["00:00"]);
219
+ d.appendChild(h), o.appendChild(d), this.root.appendChild(o), this.startTimer(h), this.root.onclick = () => {
220
+ this.minimized && (this.minimized = !1, this.root.className = "fl-quest-overlay", this.root.innerHTML = "", this.root.appendChild(n), this.root.appendChild(o), this.startTimer(h));
213
221
  };
214
222
  }
215
223
  renderFeedbackModal(t, e = "memo") {
216
- const s = r("div", { className: "fl-feedback-modal" }), i = e === "ng", l = r("div", { className: i ? "fl-quest-header fl-quest-header-ng" : "fl-quest-header" }, [
224
+ const s = r("div", { className: "fl-feedback-modal" }), i = {
225
+ ng: "fl-quest-header fl-quest-header-ng",
226
+ ok: "fl-quest-header fl-quest-header-ok",
227
+ concern: "fl-quest-header fl-quest-header-concern",
228
+ memo: "fl-quest-header"
229
+ }, n = {
230
+ ng: "NG",
231
+ ok: "โœ“ OK",
232
+ concern: "โš  ๆฐ—ใซใชใ‚‹",
233
+ memo: "๐Ÿ“"
234
+ }, o = {
235
+ ng: "fl-quest-badge fl-badge-ng",
236
+ ok: "fl-quest-badge fl-badge-ok",
237
+ concern: "fl-quest-badge fl-badge-concern",
238
+ memo: "fl-quest-badge"
239
+ }, l = r("div", { className: i[e] }, [
217
240
  r("div", { className: "fl-quest-header-left" }, [
218
- r("span", { className: i ? "fl-quest-badge fl-badge-ng" : "fl-quest-badge" }, [i ? "NG" : "๐Ÿ“"]),
241
+ r("span", { className: o[e] }, [n[e]]),
219
242
  r("span", { className: "fl-quest-title" }, [t])
220
243
  ])
221
244
  ]);
222
245
  s.appendChild(l);
223
- const h = r("div", { className: "fl-quest-content" }), d = document.createElement("textarea");
224
- d.className = "fl-feedback-textarea fl-feedback-textarea-modal", d.placeholder = i ? "ไฝ•ใŒใ†ใพใใ„ใ‹ใชใ‹ใฃใŸใ‹ๆ•™ใˆใฆใใ ใ•ใ„..." : "ๆฐ—ใฅใ„ใŸใ“ใจใ‚’ใƒกใƒข...๐Ÿ“", d.rows = 3, h.appendChild(d);
225
- const f = r("div", { className: "fl-quest-actions fl-feedback-modal-actions" }, [
226
- this.createButton("fl-btn fl-btn-finish", "้€ไฟก", () => {
227
- const m = d.value.trim();
228
- if (!m && !i) {
229
- s.remove();
230
- return;
231
- }
232
- i ? this.callbacks.onNgWithFeedback(m) : this.callbacks.onMemo(m), s.remove();
246
+ const c = r("div", { className: "fl-quest-content" }), d = {
247
+ ng: "ไฝ•ใŒใ†ใพใใ„ใ‹ใชใ‹ใฃใŸใ‹ๆ•™ใˆใฆใใ ใ•ใ„...",
248
+ ok: "ใ‚ณใƒกใƒณใƒˆ๏ผˆไปปๆ„๏ผ‰",
249
+ concern: "ๆฐ—ใซใชใฃใŸ็‚นใ‚’ๆ•™ใˆใฆใใ ใ•ใ„...",
250
+ memo: "ๆฐ—ใฅใ„ใŸใ“ใจใ‚’ใƒกใƒข...๐Ÿ“"
251
+ }, h = document.createElement("textarea");
252
+ h.className = "fl-feedback-textarea fl-feedback-textarea-modal", h.placeholder = d[e], h.rows = 3, c.appendChild(h);
253
+ const p = "้€ไฟก", g = e === "ok" ? "ใ‚นใ‚ญใƒƒใƒ—" : "ใ‚ญใƒฃใƒณใ‚ปใƒซ", f = r("div", { className: "fl-quest-actions fl-feedback-modal-actions" }, [
254
+ this.createButton("fl-btn fl-btn-skip", g, () => {
255
+ e === "ng" ? this.callbacks.onNgWithFeedback("") : e === "ok" && this.callbacks.onOkWithFeedback(""), s.remove();
233
256
  }),
234
- this.createButton("fl-btn fl-btn-skip", "ใ‚ญใƒฃใƒณใ‚ปใƒซ", () => {
235
- i && this.callbacks.onNgWithFeedback(""), s.remove();
257
+ this.createButton("fl-btn fl-btn-finish", p, () => {
258
+ const m = h.value.trim();
259
+ if (e === "ng")
260
+ this.callbacks.onNgWithFeedback(m);
261
+ else if (e === "ok")
262
+ this.callbacks.onOkWithFeedback(m);
263
+ else if (e === "concern") {
264
+ if (!m) return;
265
+ this.callbacks.onConcern(m);
266
+ } else {
267
+ if (!m) {
268
+ s.remove();
269
+ return;
270
+ }
271
+ this.callbacks.onMemo(m);
272
+ }
273
+ s.remove();
236
274
  })
237
275
  ]);
238
- h.appendChild(f), s.appendChild(h), this.root.appendChild(s), d.focus();
276
+ c.appendChild(f), s.appendChild(c), this.root.appendChild(s), h.focus();
239
277
  }
240
278
  renderSummary(t, e, s) {
241
279
  this.stopTimer(), this.root.className = "fl-quest-overlay", this.root.innerHTML = "";
@@ -293,14 +331,14 @@ class M {
293
331
  startTimer(t) {
294
332
  this.stopTimer(), this.startTime || (this.startTime = Date.now()), this.timerInterval = setInterval(() => {
295
333
  const e = Math.floor((Date.now() - this.startTime) / 1e3);
296
- t.textContent = q(e);
334
+ t.textContent = E(e);
297
335
  }, 1e3);
298
336
  }
299
337
  stopTimer() {
300
338
  this.timerInterval && (clearInterval(this.timerInterval), this.timerInterval = null);
301
339
  }
302
340
  }
303
- const E = 100, R = 2 * 1024 * 1024;
341
+ const L = 100, A = 2 * 1024 * 1024;
304
342
  class D {
305
343
  constructor(t, e, s) {
306
344
  this.config = t, this.events = e, this.maskSelector = s, this.actionLogs = [], this.snapshots = [], this.snapshotTimer = null, this.startTime = 0, this.running = !1, this.handleClick = this.onClick.bind(this), this.handleScroll = this.throttle(this.onScroll.bind(this), 500), this.handleInput = this.onInput.bind(this);
@@ -333,7 +371,7 @@ class D {
333
371
  const e = t.target;
334
372
  this.addLog({
335
373
  type: "click",
336
- target: x(e)
374
+ target: k(e)
337
375
  });
338
376
  }
339
377
  onScroll() {
@@ -345,12 +383,12 @@ class D {
345
383
  onInput(t) {
346
384
  const e = t.target;
347
385
  if (e.hasAttribute("data-fl-masked"))
348
- this.addLog({ type: "input", target: x(e), value: "[MASKED]" });
386
+ this.addLog({ type: "input", target: k(e), value: "[MASKED]" });
349
387
  else {
350
388
  const s = e.value;
351
389
  this.addLog({
352
390
  type: "input",
353
- target: x(e),
391
+ target: k(e),
354
392
  value: s == null ? void 0 : s.slice(0, 100)
355
393
  });
356
394
  }
@@ -368,8 +406,8 @@ class D {
368
406
  const s = t.querySelector("#firstlook-sdk-root");
369
407
  s == null || s.remove();
370
408
  const i = t.outerHTML;
371
- if (i.length > R) return;
372
- this.snapshots.length >= E && this.snapshots.shift(), this.snapshots.push({
409
+ if (i.length > A) return;
410
+ this.snapshots.length >= L && this.snapshots.shift(), this.snapshots.push({
373
411
  type: "dom-snapshot",
374
412
  timestamp: Date.now() - this.startTime,
375
413
  data: i
@@ -385,12 +423,12 @@ class D {
385
423
  };
386
424
  }
387
425
  }
388
- function x(a) {
426
+ function k(a) {
389
427
  var n;
390
428
  const t = a.tagName.toLowerCase(), e = a.id ? `#${a.id}` : "", s = a.className && typeof a.className == "string" ? `.${a.className.trim().split(/\s+/).slice(0, 2).join(".")}` : "", i = ((n = a.textContent) == null ? void 0 : n.trim().slice(0, 30)) || "";
391
429
  return `${t}${e}${s}${i ? ` "${i}"` : ""}`;
392
430
  }
393
- class L {
431
+ class N {
394
432
  constructor(t) {
395
433
  this.events = t, this.mediaRecorder = null, this.stream = null, this.chunks = [], this._recording = !1;
396
434
  }
@@ -449,7 +487,7 @@ class L {
449
487
  return "";
450
488
  }
451
489
  }
452
- class A {
490
+ class F {
453
491
  constructor(t, e) {
454
492
  this.shadowRoot = t, this.config = e, this.container = null, this.refreshInterval = null, this.cachedIp = null;
455
493
  }
@@ -471,15 +509,15 @@ class A {
471
509
  renderTiles() {
472
510
  if (!this.container) return;
473
511
  this.container.innerHTML = "";
474
- const t = this.cachedIp ?? "", e = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19), s = t ? `${this.config.userId} | ${e} | ${t}` : `${this.config.userId} | ${e}`, i = 320, n = 80, o = Math.ceil(window.innerWidth / i) + 1, c = Math.ceil(window.innerHeight / n) + 1;
475
- for (let l = 0; l < c; l++)
476
- for (let h = 0; h < o; h++) {
477
- const d = document.createElement("span");
478
- d.className = "fl-watermark-tile", d.textContent = s, d.style.left = `${h * i}px`, d.style.top = `${l * n}px`, this.container.appendChild(d);
512
+ const t = this.cachedIp ?? "", e = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19), s = t ? `${this.config.userId} | ${e} | ${t}` : `${this.config.userId} | ${e}`, i = 320, n = 80, o = Math.ceil(window.innerWidth / i) + 1, l = Math.ceil(window.innerHeight / n) + 1;
513
+ for (let c = 0; c < l; c++)
514
+ for (let d = 0; d < o; d++) {
515
+ const h = document.createElement("span");
516
+ h.className = "fl-watermark-tile", h.textContent = s, h.style.left = `${d * i}px`, h.style.top = `${c * n}px`, this.container.appendChild(h);
479
517
  }
480
518
  }
481
519
  }
482
- class N {
520
+ class z {
483
521
  constructor(t) {
484
522
  this.selectors = t, this.observer = null, this.maskedElements = /* @__PURE__ */ new Set();
485
523
  }
@@ -517,20 +555,20 @@ class N {
517
555
  }
518
556
  }
519
557
  }
520
- const F = "firstlook_uat", z = 1, u = {
558
+ const P = "firstlook_uat", O = 1, u = {
521
559
  sessions: "sessions",
522
560
  recordings: "recordings",
523
561
  annotations: "annotations",
524
562
  uploadQueue: "upload_queue"
525
563
  };
526
- class P {
564
+ class Q {
527
565
  constructor() {
528
566
  this.db = null;
529
567
  }
530
568
  async open() {
531
569
  if (!this.db)
532
570
  return new Promise((t, e) => {
533
- const s = indexedDB.open(F, z);
571
+ const s = indexedDB.open(P, O);
534
572
  s.onupgradeneeded = () => {
535
573
  const i = s.result;
536
574
  i.objectStoreNames.contains(u.sessions) || i.createObjectStore(u.sessions, { keyPath: "sessionId" }), i.objectStoreNames.contains(u.recordings) || i.createObjectStore(u.recordings, { autoIncrement: !0 }).createIndex("sessionId", "sessionId", { unique: !1 }), i.objectStoreNames.contains(u.annotations) || i.createObjectStore(u.annotations, { autoIncrement: !0 }).createIndex("sessionId", "sessionId", { unique: !1 }), i.objectStoreNames.contains(u.uploadQueue) || i.createObjectStore(u.uploadQueue, { autoIncrement: !0 });
@@ -564,15 +602,15 @@ class P {
564
602
  async getPendingUploads() {
565
603
  const t = this.ensureDb();
566
604
  return new Promise((e, s) => {
567
- const o = t.transaction(u.uploadQueue, "readonly").objectStore(u.uploadQueue).openCursor(), c = [];
605
+ const o = t.transaction(u.uploadQueue, "readonly").objectStore(u.uploadQueue).openCursor(), l = [];
568
606
  o.onsuccess = () => {
569
- const l = o.result;
570
- l ? (c.push({
571
- key: l.key,
572
- payload: l.value.payload,
573
- attempts: l.value.attempts,
574
- lastAttemptAt: l.value.lastAttemptAt
575
- }), l.continue()) : e(c);
607
+ const c = o.result;
608
+ c ? (l.push({
609
+ key: c.key,
610
+ payload: c.value.payload,
611
+ attempts: c.value.attempts,
612
+ lastAttemptAt: c.value.lastAttemptAt
613
+ }), c.continue()) : e(l);
576
614
  }, o.onerror = () => s(o.error);
577
615
  });
578
616
  }
@@ -586,10 +624,10 @@ class P {
586
624
  async incrementAttempts(t) {
587
625
  const e = this.ensureDb();
588
626
  return new Promise((s, i) => {
589
- const n = e.transaction(u.uploadQueue, "readwrite"), o = n.objectStore(u.uploadQueue), c = o.get(t);
590
- c.onsuccess = () => {
591
- const l = c.result;
592
- l && (l.attempts = (l.attempts ?? 0) + 1, l.lastAttemptAt = Date.now(), o.put(l, t));
627
+ const n = e.transaction(u.uploadQueue, "readwrite"), o = n.objectStore(u.uploadQueue), l = o.get(t);
628
+ l.onsuccess = () => {
629
+ const c = l.result;
630
+ c && (c.attempts = (c.attempts ?? 0) + 1, c.lastAttemptAt = Date.now(), o.put(c, t));
593
631
  }, n.oncomplete = () => s(), n.onerror = () => i(n.error);
594
632
  });
595
633
  }
@@ -600,10 +638,10 @@ class P {
600
638
  );
601
639
  s.objectStore(u.sessions).delete(t);
602
640
  for (const i of [u.recordings, u.annotations]) {
603
- const c = s.objectStore(i).index("sessionId").openCursor(IDBKeyRange.only(t));
604
- c.onsuccess = () => {
605
- const l = c.result;
606
- l && (l.delete(), l.continue());
641
+ const l = s.objectStore(i).index("sessionId").openCursor(IDBKeyRange.only(t));
642
+ l.onsuccess = () => {
643
+ const c = l.result;
644
+ c && (c.delete(), c.continue());
607
645
  };
608
646
  }
609
647
  return new Promise((i, n) => {
@@ -628,22 +666,22 @@ class P {
628
666
  async get(t, e) {
629
667
  const s = this.ensureDb();
630
668
  return new Promise((i, n) => {
631
- const c = s.transaction(t, "readonly").objectStore(t).get(e);
632
- c.onsuccess = () => i(c.result), c.onerror = () => n(c.error);
669
+ const l = s.transaction(t, "readonly").objectStore(t).get(e);
670
+ l.onsuccess = () => i(l.result), l.onerror = () => n(l.error);
633
671
  });
634
672
  }
635
673
  async getAllByIndex(t, e, s) {
636
674
  const i = this.ensureDb();
637
675
  return new Promise((n, o) => {
638
- const h = i.transaction(t, "readonly").objectStore(t).index(e).getAll(s);
639
- h.onsuccess = () => n(h.result), h.onerror = () => o(h.error);
676
+ const d = i.transaction(t, "readonly").objectStore(t).index(e).getAll(s);
677
+ d.onsuccess = () => n(d.result), d.onerror = () => o(d.error);
640
678
  });
641
679
  }
642
680
  }
643
- const k = ["#e17055", "#6c5ce7", "#00b894", "#fdcb6e", "#ffffff"];
644
- class O {
681
+ const y = ["#e17055", "#6c5ce7", "#00b894", "#fdcb6e", "#ffffff"];
682
+ class B {
645
683
  constructor(t) {
646
- this.shadowRoot = t, this.overlay = null, this.canvas = null, this.ctx = null, this.drawing = !1, this.currentPath = [], this.paths = [], this.selectedColor = k[0], this.screenshotDataUrl = "";
684
+ this.shadowRoot = t, this.overlay = null, this.canvas = null, this.ctx = null, this.drawing = !1, this.currentPath = [], this.paths = [], this.selectedColor = y[0], this.screenshotDataUrl = "";
647
685
  }
648
686
  async open() {
649
687
  return this.screenshotDataUrl = await this.captureScreenshot(), new Promise((t) => {
@@ -655,33 +693,33 @@ class O {
655
693
  type: "text",
656
694
  placeholder: "Add a comment..."
657
695
  }), i = r("div", { className: "fl-color-picker" });
658
- for (const l of k) {
659
- const h = r("div", { className: `fl-color-swatch ${l === this.selectedColor ? "fl-selected" : ""}` });
660
- h.style.background = l, h.onclick = () => {
661
- this.selectedColor = l, i.querySelectorAll(".fl-color-swatch").forEach((d) => d.classList.remove("fl-selected")), h.classList.add("fl-selected");
662
- }, i.appendChild(h);
696
+ for (const c of y) {
697
+ const d = r("div", { className: `fl-color-swatch ${c === this.selectedColor ? "fl-selected" : ""}` });
698
+ d.style.background = c, d.onclick = () => {
699
+ this.selectedColor = c, i.querySelectorAll(".fl-color-swatch").forEach((h) => h.classList.remove("fl-selected")), d.classList.add("fl-selected");
700
+ }, i.appendChild(d);
663
701
  }
664
702
  const n = r("button", { className: "fl-btn fl-btn-ok" }, ["Submit"]);
665
703
  n.onclick = () => {
666
- const l = {
704
+ const c = {
667
705
  screenshotDataUrl: this.getAnnotatedImage(),
668
706
  drawings: [...this.paths],
669
707
  comment: s.value,
670
708
  timestamp: Date.now()
671
709
  };
672
- this.close(), t(l);
710
+ this.close(), t(c);
673
711
  };
674
712
  const o = r("button", { className: "fl-btn fl-btn-ng" }, ["Cancel"]);
675
713
  o.onclick = () => {
676
714
  this.close(), t(null);
677
715
  };
678
- const c = r("div", { className: "fl-annotation-toolbar" }, [
716
+ const l = r("div", { className: "fl-annotation-toolbar" }, [
679
717
  i,
680
718
  s,
681
719
  n,
682
720
  o
683
721
  ]);
684
- this.overlay.appendChild(c), this.shadowRoot.appendChild(this.overlay), this.initCanvas();
722
+ this.overlay.appendChild(l), this.shadowRoot.appendChild(this.overlay), this.initCanvas();
685
723
  });
686
724
  }
687
725
  close() {
@@ -693,28 +731,28 @@ class O {
693
731
  const t = window.innerWidth, e = window.innerHeight, s = document.documentElement.cloneNode(!0), i = s.querySelector("#firstlook-sdk-root");
694
732
  i == null || i.remove();
695
733
  const n = s.querySelectorAll('[data-fl-masked], input[type="password"]');
696
- for (const p of n)
697
- (p instanceof HTMLInputElement || p instanceof HTMLTextAreaElement) && (p.value = "[MASKED]"), p.textContent = "[MASKED]";
698
- for (const p of s.querySelectorAll("script")) p.remove();
734
+ for (const f of n)
735
+ (f instanceof HTMLInputElement || f instanceof HTMLTextAreaElement) && (f.value = "[MASKED]"), f.textContent = "[MASKED]";
736
+ for (const f of s.querySelectorAll("script")) f.remove();
699
737
  const o = s.querySelector("body");
700
738
  if (o) {
701
- const p = window.getComputedStyle(document.body);
702
- o.style.backgroundColor = p.backgroundColor, o.style.color = p.color, o.style.fontFamily = p.fontFamily, o.style.margin = "0", o.style.overflow = "hidden";
739
+ const f = window.getComputedStyle(document.body);
740
+ o.style.backgroundColor = f.backgroundColor, o.style.color = f.color, o.style.fontFamily = f.fontFamily, o.style.margin = "0", o.style.overflow = "hidden";
703
741
  }
704
- const c = new XMLSerializer().serializeToString(s), l = `<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${e}">
742
+ const l = new XMLSerializer().serializeToString(s), c = `<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${e}">
705
743
  <foreignObject width="100%" height="100%">
706
- ${c}
744
+ ${l}
707
745
  </foreignObject>
708
- </svg>`, h = new Blob([l], { type: "image/svg+xml;charset=utf-8" }), d = URL.createObjectURL(h), f = document.createElement("canvas");
709
- f.width = t * window.devicePixelRatio, f.height = e * window.devicePixelRatio;
710
- const m = f.getContext("2d");
711
- return m.scale(window.devicePixelRatio, window.devicePixelRatio), new Promise((p) => {
712
- const g = new Image();
713
- g.onload = () => {
714
- m.drawImage(g, 0, 0, t, e), URL.revokeObjectURL(d), p(f.toDataURL("image/png"));
715
- }, g.onerror = () => {
716
- URL.revokeObjectURL(d), p(this.captureScreenshotFallback(t, e));
717
- }, g.src = d;
746
+ </svg>`, d = new Blob([c], { type: "image/svg+xml;charset=utf-8" }), h = URL.createObjectURL(d), p = document.createElement("canvas");
747
+ p.width = t * window.devicePixelRatio, p.height = e * window.devicePixelRatio;
748
+ const g = p.getContext("2d");
749
+ return g.scale(window.devicePixelRatio, window.devicePixelRatio), new Promise((f) => {
750
+ const m = new Image();
751
+ m.onload = () => {
752
+ g.drawImage(m, 0, 0, t, e), URL.revokeObjectURL(h), f(p.toDataURL("image/png"));
753
+ }, m.onerror = () => {
754
+ URL.revokeObjectURL(h), f(this.captureScreenshotFallback(t, e));
755
+ }, m.src = h;
718
756
  });
719
757
  } catch {
720
758
  return this.captureScreenshotFallback(window.innerWidth, window.innerHeight);
@@ -759,7 +797,7 @@ class O {
759
797
  return ((t = this.canvas) == null ? void 0 : t.toDataURL("image/png")) || this.screenshotDataUrl;
760
798
  }
761
799
  }
762
- class Q {
800
+ class H {
763
801
  constructor(t) {
764
802
  this.onShake = t, this.lastX = 0, this.lastY = 0, this.lastZ = 0, this.shakeCount = 0, this.lastShakeTime = 0, this.handler = null, this.THRESHOLD = 15, this.SHAKE_INTERVAL = 400, this.REQUIRED_SHAKES = 2;
765
803
  }
@@ -786,11 +824,11 @@ class Q {
786
824
  this.lastX = e.x, this.lastY = e.y, this.lastZ = e.z;
787
825
  }
788
826
  }
789
- class B {
827
+ class U {
790
828
  constructor(t, e) {
791
829
  this.shadowRoot = t, this.events = e, this.annotations = [], this.active = !1, this.onKeydown = (s) => {
792
830
  s.ctrlKey && s.shiftKey && s.key === "R" && (s.preventDefault(), this.trigger());
793
- }, this.annotationCanvas = new O(t), this.shakeTrigger = new Q(() => this.trigger());
831
+ }, this.annotationCanvas = new B(t), this.shakeTrigger = new H(() => this.trigger());
794
832
  }
795
833
  async start() {
796
834
  await this.shakeTrigger.start(), document.addEventListener("keydown", this.onKeydown);
@@ -813,7 +851,7 @@ class B {
813
851
  }
814
852
  }
815
853
  }
816
- class H {
854
+ class j {
817
855
  constructor(t, e) {
818
856
  this.requiredTaps = t, this.onActivate = e, this.tapCount = 0, this.tapTimer = null, this.handler = null;
819
857
  }
@@ -830,30 +868,74 @@ class H {
830
868
  this.tapCount = 0, this.tapTimer && (clearTimeout(this.tapTimer), this.tapTimer = null);
831
869
  }
832
870
  }
833
- class U {
871
+ const x = "firstlook:uat-active";
872
+ class S {
834
873
  constructor(t) {
835
874
  this.onActivate = t, this.hashHandler = null;
836
875
  }
837
876
  start() {
838
- this.checkUrl() && this.onActivate(), this.hashHandler = () => {
839
- this.checkUrl() && this.onActivate();
877
+ if (this.checkUrl()) {
878
+ this.persist(), this.onActivate();
879
+ return;
880
+ }
881
+ if (this.hasPersisted()) {
882
+ this.onActivate();
883
+ return;
884
+ }
885
+ this.hashHandler = () => {
886
+ this.checkUrl() && (this.persist(), this.onActivate());
840
887
  }, window.addEventListener("hashchange", this.hashHandler);
841
888
  }
842
889
  stop() {
843
890
  this.hashHandler && (window.removeEventListener("hashchange", this.hashHandler), this.hashHandler = null);
844
891
  }
892
+ /** Clear the persisted flag (call on session end / destroy). */
893
+ static clearPersisted() {
894
+ try {
895
+ sessionStorage.removeItem(x);
896
+ } catch {
897
+ }
898
+ }
845
899
  checkUrl() {
846
900
  const t = new URLSearchParams(window.location.search);
847
- return t.has("firstlook") || t.has("uat-mode");
901
+ return t.has("firstlook") || t.has("uat-mode") || t.get("uat") === "1";
902
+ }
903
+ persist() {
904
+ try {
905
+ sessionStorage.setItem(x, "1");
906
+ } catch {
907
+ }
908
+ }
909
+ hasPersisted() {
910
+ try {
911
+ return sessionStorage.getItem(x) === "1";
912
+ } catch {
913
+ return !1;
914
+ }
848
915
  }
849
916
  }
850
- class j {
917
+ class $ {
918
+ constructor(t) {
919
+ this.onActivate = t, this.handler = null;
920
+ }
921
+ start() {
922
+ this.handler = (t) => {
923
+ t.key === "U" && t.shiftKey && (t.ctrlKey || t.metaKey) && (t.preventDefault(), this.onActivate());
924
+ }, window.addEventListener("keydown", this.handler);
925
+ }
926
+ stop() {
927
+ this.handler && (window.removeEventListener("keydown", this.handler), this.handler = null);
928
+ }
929
+ }
930
+ class K {
851
931
  constructor(t, e) {
852
932
  this.shadowRoot = t, this.callbacks = e, this.root = null, this.outsideClickHandler = null;
853
933
  }
854
934
  show() {
855
935
  if (this.root) return;
856
936
  this.root = r("div", { className: "fl-debug-menu" });
937
+ for (const e of ["click", "mousedown", "mouseup", "pointerdown", "pointerup", "touchstart", "touchend"])
938
+ this.root.addEventListener(e, (s) => s.stopPropagation());
857
939
  const t = [
858
940
  { icon: "โ–ถ", label: "Start Session", action: this.callbacks.onStartSession },
859
941
  { icon: "๐Ÿ“ธ", label: "Report Issue", action: this.callbacks.onReportIssue },
@@ -882,7 +964,7 @@ class j {
882
964
  return this.root !== null;
883
965
  }
884
966
  }
885
- const $ = (
967
+ const _ = (
886
968
  /* css */
887
969
  `
888
970
  :host {
@@ -1275,10 +1357,16 @@ const $ = (
1275
1357
  box-shadow: 0 2px 8px rgba(99, 110, 114, 0.3);
1276
1358
  }
1277
1359
 
1278
- /* === NG Voice Feedback Mode === */
1360
+ /* === Feedback modal header variants === */
1279
1361
  .fl-quest-header-ng { background: linear-gradient(135deg, #e17055, #d63031); }
1280
1362
  .fl-badge-ng { background: rgba(255, 255, 255, 0.25); }
1281
1363
 
1364
+ .fl-quest-header-ok { background: linear-gradient(135deg, #00b894, #00a381); }
1365
+ .fl-badge-ok { background: rgba(255, 255, 255, 0.25); }
1366
+
1367
+ .fl-quest-header-concern { background: linear-gradient(135deg, #fdcb6e, #e17055); }
1368
+ .fl-badge-concern { background: rgba(255, 255, 255, 0.25); }
1369
+
1282
1370
  .fl-feedback-textarea {
1283
1371
  width: calc(100% - 32px);
1284
1372
  margin: 8px 16px 16px;
@@ -1294,16 +1382,25 @@ const $ = (
1294
1382
  .fl-feedback-textarea:focus { border-color: #6c5ce7; }
1295
1383
  .fl-feedback-textarea-modal { width: calc(100% - 32px); margin: 16px 16px 12px; }
1296
1384
 
1385
+ /* === Concern button === */
1386
+ .fl-btn-concern {
1387
+ background: #fdcb6e;
1388
+ color: #2d3436;
1389
+ box-shadow: 0 2px 8px rgba(253, 203, 110, 0.3);
1390
+ }
1391
+ .fl-btn-concern:hover { box-shadow: 0 4px 12px rgba(253, 203, 110, 0.4); }
1392
+
1297
1393
  /* === Memo button === */
1298
1394
  .fl-quest-memo-row { display: flex; margin-bottom: 10px; }
1299
1395
  .fl-btn-memo {
1300
- flex: none;
1396
+ flex: 1;
1301
1397
  background: #f0f0f8;
1302
1398
  color: #4a4a5a;
1303
- font-size: 12px;
1304
- padding: 6px 12px;
1399
+ font-size: 14px;
1400
+ padding: 10px 16px;
1305
1401
  box-shadow: none;
1306
- border-radius: 8px;
1402
+ border-radius: 10px;
1403
+ border: 1px dashed #c8c8d8;
1307
1404
  }
1308
1405
  .fl-btn-memo:hover { background: #e4e4f0; }
1309
1406
 
@@ -1320,10 +1417,10 @@ const $ = (
1320
1417
  }
1321
1418
  .fl-feedback-modal-actions { padding: 0 16px 16px; }
1322
1419
  `
1323
- ), K = 5;
1324
- class _ {
1420
+ ), W = 5;
1421
+ class X {
1325
1422
  constructor() {
1326
- this.config = null, this.events = new T(), this.state = "idle", this.hostElement = null, this.shadowRoot = null, this.questManager = null, this.questOverlay = null, this.sessionRecorder = null, this.voiceRecorder = null, this.watermark = null, this.fieldMasker = null, this.storage = null, this.shakeReporter = null, this.debugMenu = null, this.tapTrigger = null, this.deepLinkTrigger = null, this.sessionId = null, this.sessionStartTime = 0, this.maxDurationTimer = null, this.backupTimer = null, this.isFlushing = !1;
1423
+ this.config = null, this.events = new q(), this.state = "idle", this.hostElement = null, this.shadowRoot = null, this.questManager = null, this.questOverlay = null, this.sessionRecorder = null, this.voiceRecorder = null, this.watermark = null, this.fieldMasker = null, this.storage = null, this.shakeReporter = null, this.debugMenu = null, this.tapTrigger = null, this.deepLinkTrigger = null, this.keyboardTrigger = null, this.sessionId = null, this.sessionStartTime = 0, this.maxDurationTimer = null, this.backupTimer = null, this.isFlushing = !1;
1327
1424
  }
1328
1425
  // ----------------------------------------------------------------
1329
1426
  // Public API
@@ -1337,7 +1434,7 @@ class _ {
1337
1434
  console.warn("[FirstLook] SDK already initialized.");
1338
1435
  return;
1339
1436
  }
1340
- this.config = S(t), this.storage = new P(), await this.storage.open(), this.createShadowHost(), this.setupTriggers(), this.fieldMasker = new N(this.config.security.maskSelectors), this.state = "initialized", this.events.emit({ type: "sdk:initialized" }), this.flushUploadQueue(!0);
1437
+ this.config = C(t), this.storage = new Q(), await this.storage.open(), this.createShadowHost(), this.setupTriggers(), this.fieldMasker = new z(this.config.security.maskSelectors), this.state = "initialized", this.events.emit({ type: "sdk:initialized" }), this.flushUploadQueue(!0);
1341
1438
  }
1342
1439
  /**
1343
1440
  * Manually activate the SDK UI (bypassing triggers).
@@ -1356,12 +1453,13 @@ class _ {
1356
1453
  var s;
1357
1454
  if (this.state !== "active")
1358
1455
  throw new Error("[FirstLook] Cannot start session: SDK not active. Call activate() first.");
1359
- (s = this.debugMenu) == null || s.hide(), this.sessionId = I(), this.sessionStartTime = Date.now(), this.questManager = new C(this.events), this.questManager.loadQuests(t), this.sessionRecorder = new D(
1456
+ (s = this.debugMenu) == null || s.hide(), this.sessionId = M(), this.sessionStartTime = Date.now(), this.questManager = new I(this.events), this.questManager.loadQuests(t), this.sessionRecorder = new D(
1360
1457
  this.config,
1361
1458
  this.events,
1362
1459
  this.fieldMasker.getCombinedSelector()
1363
- ), this.voiceRecorder = new L(this.events), this.shakeReporter = new B(this.shadowRoot, this.events), await this.shakeReporter.start(), this.sessionRecorder.start(), this.fieldMasker.start(), this.config.recording.voice && await this.voiceRecorder.start(), this.config.security.watermark && (this.watermark = new A(this.shadowRoot, this.config), this.watermark.show()), this.questOverlay = new M(this.shadowRoot, {
1364
- onOk: () => this.handleQuestOk(),
1460
+ ), this.voiceRecorder = new N(this.events), this.shakeReporter = new U(this.shadowRoot, this.events), await this.shakeReporter.start(), this.sessionRecorder.start(), this.fieldMasker.start(), this.config.recording.voice && await this.voiceRecorder.start(), this.config.security.watermark && (this.watermark = new F(this.shadowRoot, this.config), this.watermark.show()), this.questOverlay = new R(this.shadowRoot, {
1461
+ onOkWithFeedback: (i) => this.handleQuestOk(i),
1462
+ onConcern: (i) => this.handleConcern(i),
1365
1463
  onNg: () => this.handleQuestNg(),
1366
1464
  onNgWithFeedback: (i) => this.handleNgFeedbackSubmit(i),
1367
1465
  onMemo: (i) => this.handleMemo(i),
@@ -1392,9 +1490,9 @@ class _ {
1392
1490
  * End the current session, persist data, and trigger upload.
1393
1491
  */
1394
1492
  async endSession() {
1395
- var i, n, o, c, l, h, d, f, m, p, g;
1493
+ var i, n, o, l, c, d, h, p, g, f, m;
1396
1494
  if (this.state !== "recording" || !this.sessionId) return null;
1397
- this.maxDurationTimer && (clearTimeout(this.maxDurationTimer), this.maxDurationTimer = null), this.backupTimer && (clearInterval(this.backupTimer), this.backupTimer = null), (i = this.sessionRecorder) == null || i.stop(), await ((n = this.voiceRecorder) == null ? void 0 : n.stopAsync()), (o = this.shakeReporter) == null || o.stop(), (c = this.fieldMasker) == null || c.stop(), (l = this.watermark) == null || l.hide();
1495
+ this.maxDurationTimer && (clearTimeout(this.maxDurationTimer), this.maxDurationTimer = null), this.backupTimer && (clearInterval(this.backupTimer), this.backupTimer = null), (i = this.sessionRecorder) == null || i.stop(), await ((n = this.voiceRecorder) == null ? void 0 : n.stopAsync()), (o = this.shakeReporter) == null || o.stop(), (l = this.fieldMasker) == null || l.stop(), (c = this.watermark) == null || c.hide();
1398
1496
  const t = this.questManager.getResults();
1399
1497
  await Promise.allSettled(
1400
1498
  t.map(async (b) => {
@@ -1428,13 +1526,13 @@ class _ {
1428
1526
  endedAt: (/* @__PURE__ */ new Date()).toISOString(),
1429
1527
  duration: Math.floor((Date.now() - this.sessionStartTime) / 1e3),
1430
1528
  quests: t,
1431
- recordings: ((h = this.sessionRecorder) == null ? void 0 : h.getSnapshots()) ?? []
1529
+ recordings: ((d = this.sessionRecorder) == null ? void 0 : d.getSnapshots()) ?? []
1432
1530
  };
1433
- await ((d = this.storage) == null ? void 0 : d.saveSession(e));
1434
- const s = ((f = this.shakeReporter) == null ? void 0 : f.getAnnotations()) ?? [];
1531
+ await ((h = this.storage) == null ? void 0 : h.saveSession(e));
1532
+ const s = ((p = this.shakeReporter) == null ? void 0 : p.getAnnotations()) ?? [];
1435
1533
  for (const b of s)
1436
- await ((m = this.storage) == null ? void 0 : m.saveAnnotation(this.sessionId, b));
1437
- return await ((p = this.storage) == null ? void 0 : p.enqueueUpload({ session: e, annotations: s })), (g = this.questOverlay) == null || g.destroy(), this.questOverlay = null, this.state = "finished", this.events.emit({ type: "session:ended", sessionId: this.sessionId }), this.flushUploadQueue(!1), e;
1534
+ await ((g = this.storage) == null ? void 0 : g.saveAnnotation(this.sessionId, b));
1535
+ return await ((f = this.storage) == null ? void 0 : f.enqueueUpload({ session: e, annotations: s })), (m = this.questOverlay) == null || m.destroy(), this.questOverlay = null, this.state = "finished", this.events.emit({ type: "session:ended", sessionId: this.sessionId }), this.flushUploadQueue(!1), e;
1438
1536
  }
1439
1537
  /**
1440
1538
  * Subscribe to SDK events.
@@ -1452,42 +1550,50 @@ class _ {
1452
1550
  * Completely destroy the SDK instance and clean up all resources.
1453
1551
  */
1454
1552
  destroy() {
1455
- var t, e, s, i, n, o, c, l, h, d;
1456
- this.maxDurationTimer && (clearTimeout(this.maxDurationTimer), this.maxDurationTimer = null), this.backupTimer && (clearInterval(this.backupTimer), this.backupTimer = null), (t = this.tapTrigger) == null || t.stop(), (e = this.deepLinkTrigger) == null || e.stop(), (s = this.sessionRecorder) == null || s.stop(), (i = this.shakeReporter) == null || i.stop(), (n = this.fieldMasker) == null || n.stop(), (o = this.watermark) == null || o.hide(), (c = this.questOverlay) == null || c.destroy(), (l = this.debugMenu) == null || l.hide(), (h = this.hostElement) == null || h.remove(), (d = this.storage) == null || d.close(), this.events.removeAll(), this.state = "idle";
1553
+ var t, e, s, i, n, o, l, c, d, h, p;
1554
+ this.maxDurationTimer && (clearTimeout(this.maxDurationTimer), this.maxDurationTimer = null), this.backupTimer && (clearInterval(this.backupTimer), this.backupTimer = null), (t = this.tapTrigger) == null || t.stop(), (e = this.deepLinkTrigger) == null || e.stop(), (s = this.keyboardTrigger) == null || s.stop(), S.clearPersisted(), (i = this.sessionRecorder) == null || i.stop(), (n = this.shakeReporter) == null || n.stop(), (o = this.fieldMasker) == null || o.stop(), (l = this.watermark) == null || l.hide(), (c = this.questOverlay) == null || c.destroy(), (d = this.debugMenu) == null || d.hide(), (h = this.hostElement) == null || h.remove(), (p = this.storage) == null || p.close(), this.events.removeAll(), this.state = "idle";
1457
1555
  }
1458
1556
  // ----------------------------------------------------------------
1459
1557
  // Private methods
1460
1558
  // ----------------------------------------------------------------
1461
1559
  createShadowHost() {
1462
- this.hostElement = document.createElement("div"), this.hostElement.id = "firstlook-sdk-root", this.hostElement.style.cssText = "position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;", document.body.appendChild(this.hostElement), this.shadowRoot = this.hostElement.attachShadow({ mode: "closed" });
1560
+ this.hostElement = document.createElement("div"), this.hostElement.id = "firstlook-sdk-root", this.hostElement.style.cssText = "position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;", document.body.appendChild(this.hostElement), this.shadowRoot = this.hostElement.attachShadow({ mode: "closed" });
1463
1561
  const t = document.createElement("style");
1464
- t.textContent = $, this.shadowRoot.appendChild(t);
1465
- const e = document.createElement("div");
1466
- e.style.cssText = "pointer-events:auto;", this.shadowRoot.appendChild(e);
1562
+ t.textContent = _, this.shadowRoot.appendChild(t);
1467
1563
  }
1468
1564
  setupTriggers() {
1469
1565
  const t = this.config.triggers;
1470
- this.tapTrigger = new H(t.tapCount, () => this.onActivate()), this.tapTrigger.start(), t.deepLink && (this.deepLinkTrigger = new U(() => this.onActivate()), this.deepLinkTrigger.start()), t.customCheck && t.customCheck() && this.onActivate();
1566
+ this.tapTrigger = new j(t.tapCount, () => this.onActivate()), this.tapTrigger.start(), t.deepLink && (this.deepLinkTrigger = new S(() => this.onActivate()), this.deepLinkTrigger.start()), t.keyboard && (this.keyboardTrigger = new $(() => this.onActivate()), this.keyboardTrigger.start()), t.customCheck && t.customCheck() && this.onActivate();
1471
1567
  }
1472
1568
  onActivate() {
1473
- var t, e;
1474
- this.state === "initialized" && (this.state = "active", (t = this.tapTrigger) == null || t.stop(), (e = this.deepLinkTrigger) == null || e.stop(), this.events.emit({ type: "sdk:activated" }), this.debugMenu = new j(this.shadowRoot, {
1569
+ var t, e, s;
1570
+ this.state === "initialized" && (this.state = "active", (t = this.tapTrigger) == null || t.stop(), (e = this.deepLinkTrigger) == null || e.stop(), (s = this.keyboardTrigger) == null || s.stop(), this.events.emit({ type: "sdk:activated" }), this.debugMenu = new K(this.shadowRoot, {
1475
1571
  onStartSession: () => {
1476
1572
  this.events.emit({ type: "sdk:activated" });
1477
1573
  },
1478
1574
  onReportIssue: () => {
1479
- var s, i;
1480
- (i = (s = this.shakeReporter) == null ? void 0 : s.trigger) == null || i.call(s);
1575
+ var i, n;
1576
+ (n = (i = this.shakeReporter) == null ? void 0 : i.trigger) == null || n.call(i);
1481
1577
  },
1482
1578
  onClose: () => {
1483
1579
  this.destroy();
1484
1580
  }
1485
1581
  }), this.debugMenu.show());
1486
1582
  }
1487
- handleQuestOk() {
1583
+ handleQuestOk(t) {
1584
+ if (!this.questManager || !this.sessionRecorder) return;
1585
+ const e = this.sessionRecorder.getActionLogs();
1586
+ this.questManager.completeCurrentQuest(e, {
1587
+ comment: t || void 0
1588
+ }), this.renderCurrentQuest();
1589
+ }
1590
+ handleConcern(t) {
1488
1591
  if (!this.questManager || !this.sessionRecorder) return;
1489
- const t = this.sessionRecorder.getActionLogs();
1490
- this.questManager.completeCurrentQuest(t), this.renderCurrentQuest();
1592
+ const e = this.sessionRecorder.getActionLogs();
1593
+ this.questManager.completeCurrentQuest(e, {
1594
+ comment: t,
1595
+ concern: !0
1596
+ }), this.renderCurrentQuest();
1491
1597
  }
1492
1598
  handleQuestNg() {
1493
1599
  if (!this.questManager || !this.questOverlay) return;
@@ -1539,7 +1645,7 @@ class _ {
1539
1645
  }
1540
1646
  const e = await this.storage.getPendingUploads();
1541
1647
  for (const s of e) {
1542
- if (s.attempts >= K) {
1648
+ if (s.attempts >= W) {
1543
1649
  await this.storage.removeFromQueue(s.key);
1544
1650
  continue;
1545
1651
  }
@@ -1593,6 +1699,6 @@ class _ {
1593
1699
  }
1594
1700
  }
1595
1701
  export {
1596
- _ as FirstLookSDK
1702
+ X as FirstLookSDK
1597
1703
  };
1598
1704
  //# sourceMappingURL=firstlook.es.js.map