@sphoro/bugcatch-web-sdk 0.19.0 → 0.21.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,10 +1,10 @@
1
- var be = (t) => {
1
+ var ke = (t) => {
2
2
  throw TypeError(t);
3
3
  };
4
- var xt = (t, e, n) => e.has(t) || be("Cannot " + n);
5
- var xe = (t, e, n) => e.has(t) ? be("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, n);
4
+ var xt = (t, e, n) => e.has(t) || ke("Cannot " + n);
5
+ var ve = (t, e, n) => e.has(t) ? ke("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, n);
6
6
  var x = (t, e, n) => (xt(t, e, "access private method"), n);
7
- const Q = "[REDACTED]", kt = /* @__PURE__ */ new Set([
7
+ const ee = "[REDACTED]", kt = /* @__PURE__ */ new Set([
8
8
  "auth",
9
9
  "bearer",
10
10
  "session",
@@ -28,7 +28,7 @@ const Q = "[REDACTED]", kt = /* @__PURE__ */ new Set([
28
28
  "privatekey",
29
29
  "accesskey",
30
30
  "authorization"
31
- ], It = /* @__PURE__ */ new Set(["key", "code", "state", "nonce", "salt", "hash"]), Ne = [
31
+ ], Ct = /* @__PURE__ */ new Set(["key", "code", "state", "nonce", "salt", "hash"]), Ne = [
32
32
  /eyJ[\w-]{8,}\.[\w-]{8,}\.[\w-]+/g,
33
33
  // JWT
34
34
  /(?:AKIA|ASIA|AROA|AIDA|AGPA|ANPA|ANVA|APKA)[0-9A-Z]{16}/g,
@@ -51,7 +51,7 @@ const Q = "[REDACTED]", kt = /* @__PURE__ */ new Set([
51
51
  // GitLab
52
52
  /shp(?:at|ss|ca|pa)_[A-Za-z0-9]{32}/g
53
53
  // Shopify
54
- ], Ct = /\bBearer\s+[\w.~+/=-]{8,}/gi, St = /^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#@]+)@/;
54
+ ], It = /\bBearer\s+[\w.~+/=-]{8,}/gi, St = /^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#@]+)@/;
55
55
  function Ue(t) {
56
56
  try {
57
57
  return decodeURIComponent(t.replace(/\+/g, " "));
@@ -70,42 +70,42 @@ function $t(t, e) {
70
70
  if (!n) return !1;
71
71
  if (kt.has(n)) return !0;
72
72
  for (const i of vt) if (n.includes(i)) return !0;
73
- return It.has(n) ? Et(Ue(e)) : !1;
73
+ return Ct.has(n) ? Et(Ue(e)) : !1;
74
74
  }
75
- function ie(t) {
75
+ function oe(t) {
76
76
  return t.split("&").map((e) => {
77
77
  const n = e.indexOf("=");
78
78
  if (n === -1) return e;
79
79
  const i = e.slice(0, n), r = e.slice(n + 1);
80
- return r && $t(i, r) ? `${i}=${Q}` : e;
80
+ return r && $t(i, r) ? `${i}=${ee}` : e;
81
81
  }).join("&");
82
82
  }
83
- function Pe(t) {
83
+ function De(t) {
84
84
  let e = t;
85
85
  for (const n of Ne)
86
- n.lastIndex = 0, e = e.replace(n, Q);
86
+ n.lastIndex = 0, e = e.replace(n, ee);
87
87
  return e;
88
88
  }
89
- function De(t) {
89
+ function Pe(t) {
90
90
  if (t == null) return t;
91
91
  let e = String(t);
92
92
  if (!e) return e;
93
- e = e.replace(St, `$1${Q}@`);
93
+ e = e.replace(St, `$1${ee}@`);
94
94
  const n = e.indexOf("#");
95
95
  let i = n === -1 ? e : e.slice(0, n), r = n === -1 ? "" : e.slice(n);
96
96
  const o = i.indexOf("?");
97
- if (o !== -1 && (i = i.slice(0, o + 1) + ie(i.slice(o + 1))), r.length > 1) {
97
+ if (o !== -1 && (i = i.slice(0, o + 1) + oe(i.slice(o + 1))), r.length > 1) {
98
98
  const a = r.slice(1), s = a.indexOf("?");
99
- s !== -1 ? r = `#${a.slice(0, s + 1)}${ie(a.slice(s + 1))}` : a.includes("=") && (r = `#${ie(a)}`);
99
+ s !== -1 ? r = `#${a.slice(0, s + 1)}${oe(a.slice(s + 1))}` : a.includes("=") && (r = `#${oe(a)}`);
100
100
  }
101
- return Pe(i + r);
101
+ return De(i + r);
102
102
  }
103
103
  function Tt(t) {
104
104
  if (t == null) return t;
105
105
  let e = String(t);
106
- return e && (e = e.replace(/[A-Za-z][A-Za-z0-9+.-]{0,30}:\/\/[^\s"'<>)\]]+/g, (n) => De(n)), e = e.replace(Ct, `Bearer ${Q}`), Pe(e));
106
+ return e && (e = e.replace(/[A-Za-z][A-Za-z0-9+.-]{0,30}:\/\/[^\s"'<>)\]]+/g, (n) => Pe(n)), e = e.replace(It, `Bearer ${ee}`), De(e));
107
107
  }
108
- function z(t) {
108
+ function F(t) {
109
109
  const e = [];
110
110
  return {
111
111
  push(n) {
@@ -120,10 +120,10 @@ function z(t) {
120
120
  }
121
121
  };
122
122
  }
123
- const ke = ["log", "info", "warn", "error", "debug"];
123
+ const Ce = ["log", "info", "warn", "error", "debug"];
124
124
  function At(t, { levels: e = ["warn", "error", "log", "info"] } = {}) {
125
125
  const n = {};
126
- for (const i of ke)
126
+ for (const i of Ce)
127
127
  n[i] = console[i], e.includes(i) && (console[i] = (...r) => {
128
128
  try {
129
129
  t.push({
@@ -136,25 +136,25 @@ function At(t, { levels: e = ["warn", "error", "log", "info"] } = {}) {
136
136
  n[i].apply(console, r);
137
137
  });
138
138
  return () => {
139
- for (const i of ke) console[i] = n[i];
139
+ for (const i of Ce) console[i] = n[i];
140
140
  };
141
141
  }
142
142
  function jt(t, { slowMs: e = 2e3 } = {}) {
143
143
  const n = window.fetch, i = XMLHttpRequest.prototype.open, r = XMLHttpRequest.prototype.send;
144
144
  return n && (window.fetch = async function(...a) {
145
- var h, f, d;
146
- const s = performance.now(), c = typeof a[0] == "string" ? a[0] : (h = a[0]) == null ? void 0 : h.url, l = ((f = a[1]) == null ? void 0 : f.method) || (typeof a[0] == "object" ? (d = a[0]) == null ? void 0 : d.method : "GET") || "GET";
145
+ var h, f, u;
146
+ const s = performance.now(), c = typeof a[0] == "string" ? a[0] : (h = a[0]) == null ? void 0 : h.url, l = ((f = a[1]) == null ? void 0 : f.method) || (typeof a[0] == "object" ? (u = a[0]) == null ? void 0 : u.method : "GET") || "GET";
147
147
  try {
148
- const u = await n.apply(this, a);
149
- return oe(t, { url: c, method: l, status: u.status, ms: Math.round(performance.now() - s), slowMs: e }), u;
150
- } catch (u) {
151
- throw oe(t, { url: c, method: l, status: 0, error: String((u == null ? void 0 : u.message) || u), ms: Math.round(performance.now() - s), slowMs: e }), u;
148
+ const d = await n.apply(this, a);
149
+ return re(t, { url: c, method: l, status: d.status, ms: Math.round(performance.now() - s), slowMs: e }), d;
150
+ } catch (d) {
151
+ throw re(t, { url: c, method: l, status: 0, error: String((d == null ? void 0 : d.message) || d), ms: Math.round(performance.now() - s), slowMs: e }), d;
152
152
  }
153
153
  }), XMLHttpRequest.prototype.open = function(a, s, ...c) {
154
154
  return this.__bc = { method: a, url: s, started: 0 }, i.call(this, a, s, ...c);
155
155
  }, XMLHttpRequest.prototype.send = function(...a) {
156
156
  return this.__bc && (this.__bc.started = performance.now(), this.addEventListener("loadend", () => {
157
- oe(t, {
157
+ re(t, {
158
158
  url: this.__bc.url,
159
159
  method: this.__bc.method,
160
160
  status: this.status,
@@ -166,7 +166,7 @@ function jt(t, { slowMs: e = 2e3 } = {}) {
166
166
  n && (window.fetch = n), XMLHttpRequest.prototype.open = i, XMLHttpRequest.prototype.send = r;
167
167
  };
168
168
  }
169
- function oe(t, { url: e, method: n, status: i, ms: r, error: o, slowMs: a }) {
169
+ function re(t, { url: e, method: n, status: i, ms: r, error: o, slowMs: a }) {
170
170
  try {
171
171
  t.push({
172
172
  // Scrubbed before it is buffered, not before it is sent: a credential
@@ -175,7 +175,7 @@ function oe(t, { url: e, method: n, status: i, ms: r, error: o, slowMs: a }) {
175
175
  // then truncate — truncating first would split a token into something
176
176
  // no pattern recognises, and the fragment would still be a fragment of
177
177
  // a live credential.
178
- url: De(String(e)).slice(0, 500),
178
+ url: Pe(String(e)).slice(0, 500),
179
179
  method: n,
180
180
  status: i,
181
181
  ms: r,
@@ -207,7 +207,7 @@ function Ot(t) {
207
207
  window.removeEventListener("error", e), window.removeEventListener("unhandledrejection", n);
208
208
  };
209
209
  }
210
- async function ve() {
210
+ async function ae() {
211
211
  const t = _e();
212
212
  try {
213
213
  if (navigator.getBattery) {
@@ -269,8 +269,8 @@ function He(t) {
269
269
  return String(t);
270
270
  }
271
271
  }
272
- const hi = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11.5a7.5 7 0 0 1 7.5-7h1a7.5 7 0 0 1 0 14H9l-4.2 2.6a.5.5 0 0 1-.76-.5l.5-3.1A7 7 0 0 1 4 11.5z"/><path d="M8.5 11.5h.01M12 11.5h.01M15.5 11.5h.01" stroke-width="2.6"/></svg>', Mt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9.5l6 6 6-6"/></svg>', Rt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4.2"/><path d="M12 2.6v2.2M12 19.2v2.2M2.6 12h2.2M19.2 12h2.2M5.4 5.4l1.6 1.6M17 17l1.6 1.6M18.6 5.4L17 7M7 17l-1.6 1.6"/></svg>', Lt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13.4A8.2 8.2 0 1 1 10.6 4a6.6 6.6 0 0 0 9.4 9.4z"/></svg>', Kt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="2.8" y="4.4" width="18.4" height="12.6" rx="2.2"/><path d="M8.6 20.2h6.8"/><path d="M12 4.4v12.6"/><path d="M12 7.2a3.6 3.6 0 0 1 0 7.2z" fill="currentColor" stroke="none"/></svg>', ze = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7.5v5.2M12 16.3h.01"/></svg>', qe = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>', Nt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.8l4.6 4.4L19 7"/></svg>', Fe = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v5.5M12 7.7h.01"/></svg>', Ut = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.3 4.2a2 2 0 0 1 3.4 0l7.6 13.1a2 2 0 0 1-1.7 3H4.4a2 2 0 0 1-1.7-3z"/><path d="M12 9.5v4.2M12 17h.01"/></svg>';
273
- function Xe(t, e) {
272
+ const yi = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11.5a7.5 7 0 0 1 7.5-7h1a7.5 7 0 0 1 0 14H9l-4.2 2.6a.5.5 0 0 1-.76-.5l.5-3.1A7 7 0 0 1 4 11.5z"/><path d="M8.5 11.5h.01M12 11.5h.01M15.5 11.5h.01" stroke-width="2.6"/></svg>', Mt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9.5l6 6 6-6"/></svg>', Rt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4.2"/><path d="M12 2.6v2.2M12 19.2v2.2M2.6 12h2.2M19.2 12h2.2M5.4 5.4l1.6 1.6M17 17l1.6 1.6M18.6 5.4L17 7M7 17l-1.6 1.6"/></svg>', Lt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13.4A8.2 8.2 0 1 1 10.6 4a6.6 6.6 0 0 0 9.4 9.4z"/></svg>', Kt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="2.8" y="4.4" width="18.4" height="12.6" rx="2.2"/><path d="M8.6 20.2h6.8"/><path d="M12 4.4v12.6"/><path d="M12 7.2a3.6 3.6 0 0 1 0 7.2z" fill="currentColor" stroke="none"/></svg>', ze = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7.5v5.2M12 16.3h.01"/></svg>', Fe = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>', Nt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.8l4.6 4.4L19 7"/></svg>', Xe = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v5.5M12 7.7h.01"/></svg>', Ut = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.3 4.2a2 2 0 0 1 3.4 0l7.6 13.1a2 2 0 0 1-1.7 3H4.4a2 2 0 0 1-1.7-3z"/><path d="M12 9.5v4.2M12 17h.01"/></svg>';
273
+ function qe(t, e) {
274
274
  console.warn(`[BugCatch] ${t}`, ...e ? [e] : []);
275
275
  const n = new Error("[BugCatch] part of the widget could not be loaded — check the connection and try again.");
276
276
  return e && (n.cause = e), n;
@@ -282,20 +282,20 @@ function We(t) {
282
282
  })), e);
283
283
  }
284
284
  const Ie = We(() => import("./bugcatch-panel.es.js").catch((t) => {
285
- throw Xe("the report panel could not be loaded.", t);
286
- })), q = We(() => import("./bugcatch-call.es.js").catch((t) => {
287
- throw Xe("the calling code could not be loaded.", t);
288
- })), Pt = {
289
- info: Fe,
285
+ throw qe("the report panel could not be loaded.", t);
286
+ })), X = We(() => import("./bugcatch-call.es.js").catch((t) => {
287
+ throw qe("the calling code could not be loaded.", t);
288
+ })), Dt = {
289
+ info: Xe,
290
290
  success: Nt,
291
291
  warning: Ut,
292
292
  critical: ze
293
293
  };
294
- function Dt(t, { where: e, onDismiss: n }) {
294
+ function Pt(t, { where: e, onDismiss: n }) {
295
295
  const i = document.createElement("div");
296
296
  i.className = `notice tone-${t.tone} at-${e}`, i.setAttribute("role", "status");
297
297
  const r = document.createElement("span");
298
- r.className = "notice-ico", r.setAttribute("aria-hidden", "true"), r.innerHTML = Pt[t.tone] || Fe;
298
+ r.className = "notice-ico", r.setAttribute("aria-hidden", "true"), r.innerHTML = Dt[t.tone] || Xe;
299
299
  const o = document.createElement("div");
300
300
  o.className = "notice-text";
301
301
  const a = document.createElement("strong");
@@ -309,26 +309,26 @@ function Dt(t, { where: e, onDismiss: n }) {
309
309
  }
310
310
  if (i.append(r, o), t.dismissible && n) {
311
311
  const s = document.createElement("button");
312
- s.type = "button", s.className = "notice-x", s.setAttribute("aria-label", "Dismiss this notice"), s.innerHTML = qe, s.addEventListener("click", () => n(t)), i.append(s);
312
+ s.type = "button", s.className = "notice-x", s.setAttribute("aria-label", "Dismiss this notice"), s.innerHTML = Fe, s.addEventListener("click", () => n(t)), i.append(s);
313
313
  }
314
314
  return i;
315
315
  }
316
- const Je = "#0e0e10", re = "#ffffff";
316
+ const Je = "#0e0e10", ce = "#ffffff";
317
317
  function Ye(t) {
318
318
  const e = _t(t);
319
- if (!e) return re;
319
+ if (!e) return ce;
320
320
  const [n, i, r] = e.map((a) => {
321
321
  const s = a / 255;
322
322
  return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
323
323
  });
324
- return 0.2126 * n + 0.7152 * i + 0.0722 * r > 0.179 ? Je : re;
324
+ return 0.2126 * n + 0.7152 * i + 0.0722 * r > 0.179 ? Je : ce;
325
325
  }
326
326
  function _t(t) {
327
327
  const e = String(t || "").trim();
328
328
  let n = /^#([0-9a-f]{3})$/i.exec(e);
329
329
  return n ? [...n[1]].map((i) => parseInt(i + i, 16)) : (n = /^#([0-9a-f]{6})$/i.exec(e), n ? [0, 2, 4].map((i) => parseInt(n[1].slice(i, i + 2), 16)) : (n = /^rgba?\(\s*(\d+)[\s,]+(\d+)[\s,]+(\d+)/i.exec(e), n ? [n[1], n[2], n[3]].map(Number) : null));
330
330
  }
331
- const Ce = {
331
+ const Se = {
332
332
  "bottom-right": "bottom:20px;right:20px;",
333
333
  "bottom-left": "bottom:20px;left:20px;",
334
334
  "top-right": "top:20px;right:20px;",
@@ -352,7 +352,7 @@ function zt(t) {
352
352
  } catch {
353
353
  }
354
354
  }
355
- const Se = `
355
+ const Be = `
356
356
  --bc-bg: #151517;
357
357
  --bc-elevated: #1c1c1f;
358
358
  --bc-fg: #f3f2ef;
@@ -370,7 +370,7 @@ const Se = `
370
370
  --bc-brand-mark: #a59cff;
371
371
  --bc-shadow: 0 0 0 1px rgba(255,255,255,.08), 0 30px 70px -20px rgba(0,0,0,.8), 0 8px 20px -8px rgba(0,0,0,.5);
372
372
  --bc-shadow-sm: 0 0 0 1px rgba(255,255,255,.07), 0 1px 2px rgba(0,0,0,.4);
373
- --bc-accent-soft: color-mix(in srgb, var(--bc-accent) 14%, var(--bc-bg));`, qt = (t) => `
373
+ --bc-accent-soft: color-mix(in srgb, var(--bc-accent) 14%, var(--bc-bg));`, Ft = (t) => `
374
374
  :host { all: initial; }
375
375
  :host {
376
376
  --bc-accent: ${t || "var(--bc-fg)"};
@@ -422,10 +422,10 @@ const Se = `
422
422
  --bc-fs-lg: 15px;
423
423
  --bc-pad: 18px;
424
424
  }
425
- :host(.bc-dark) {${Se}
425
+ :host(.bc-dark) {${Be}
426
426
  }
427
427
  @media (prefers-color-scheme: dark) {
428
- :host(.bc-auto) {${Se}
428
+ :host(.bc-auto) {${Be}
429
429
  }
430
430
  }
431
431
 
@@ -655,21 +655,21 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
655
655
  .loadfail button[data-act="retry"] { text-decoration: underline; text-underline-offset: 2px; }
656
656
  .loadfail button svg { font-size: 13px; margin: 0; }
657
657
  `;
658
- function Ft(t) {
658
+ function Xt(t) {
659
659
  const e = document.createElement("div");
660
660
  e.setAttribute("data-bugcatch", "widget");
661
- let n = Ht() || Xt(t.config.theme);
662
- e.className = Be(n);
661
+ let n = Ht() || qt(t.config.theme);
662
+ e.className = Ee(n);
663
663
  const i = e.attachShadow({ mode: "open" }), r = document.createElement("style");
664
- r.textContent = qt(t.config.accent || null), i.appendChild(r);
665
- const o = Ce[t.config.widgetPosition] ? t.config.widgetPosition : "bottom-right", a = document.createElement("div");
666
- a.className = `dock ${o.includes("right") ? "at-right" : "at-left"}` + (o.startsWith("top") ? " at-top" : ""), a.style.cssText = Ce[o];
664
+ r.textContent = Ft(t.config.accent || null), i.appendChild(r);
665
+ const o = Se[t.config.widgetPosition] ? t.config.widgetPosition : "bottom-right", a = document.createElement("div");
666
+ a.className = `dock ${o.includes("right") ? "at-right" : "at-left"}` + (o.startsWith("top") ? " at-top" : ""), a.style.cssText = Se[o];
667
667
  const s = {
668
668
  current: () => n,
669
- label: () => P.find((g) => g.value === n).label,
669
+ label: () => P.find((w) => w.value === n).label,
670
670
  cycle() {
671
- const g = P[(P.findIndex((b) => b.value === n) + 1) % P.length];
672
- return n = g.value, e.className = Be(n), zt(n), g;
671
+ const w = P[(P.findIndex((C) => C.value === n) + 1) % P.length];
672
+ return n = w.value, e.className = Ee(n), zt(n), w;
673
673
  }
674
674
  }, c = document.createElement("button");
675
675
  c.className = "launcher", c.type = "button", c.innerHTML = `<span class="ico" aria-hidden="true"><span class="when-closed"><span class="orb"></span></span><span class="when-open">${Mt}</span></span><span>Report a bug</span>`, c.setAttribute("aria-haspopup", "dialog"), c.setAttribute("aria-expanded", "false");
@@ -679,94 +679,106 @@ function Ft(t) {
679
679
  l.close();
680
680
  return;
681
681
  }
682
- l = h();
682
+ l = f();
683
683
  });
684
- function h() {
685
- I(), p();
686
- let g = null, b = !1;
684
+ let h = "report";
685
+ function f() {
686
+ let w = h;
687
+ h = "report", E(), k();
688
+ let C = null, m = !1;
687
689
  const B = () => {
688
- b = !0, c.removeAttribute("aria-busy"), l = null;
689
- }, y = {
690
- close: () => g ? g.close() : B(),
691
- destroy: () => g ? g.destroy() : B()
690
+ m = !0, c.removeAttribute("aria-busy"), l = null;
691
+ }, A = {
692
+ close: () => C ? C.close() : B(),
693
+ destroy: () => C ? C.destroy() : B(),
694
+ // Asked again while it is on its way, or once it is open.
695
+ setMode: (I) => {
696
+ var O;
697
+ C ? (O = C.setMode) == null || O.call(C, I) : w = I;
698
+ }
692
699
  };
693
- return c.setAttribute("aria-busy", "true"), Ie(t.config.chunkBase).then(({ openPanel: C }) => {
694
- b || (c.removeAttribute("aria-busy"), a.classList.add("over"), c.setAttribute("aria-expanded", "true"), g = C({
700
+ return c.setAttribute("aria-busy", "true"), Ie(t.config.chunkBase).then(({ openPanel: I }) => {
701
+ m || (c.removeAttribute("aria-busy"), a.classList.add("over"), c.setAttribute("aria-expanded", "true"), C = I({
695
702
  root: i,
696
703
  host: e,
697
704
  dock: a,
698
705
  client: t,
699
- preloadCall: u,
706
+ preloadCall: b,
700
707
  themeControls: s,
708
+ mode: w,
701
709
  onClose: () => {
702
710
  l = null, a.classList.remove("over"), c.setAttribute("aria-expanded", "false");
703
711
  }
704
712
  }));
705
713
  }, () => {
706
- b || (B(), $());
707
- }), y;
714
+ m || (B(), S());
715
+ }), A;
708
716
  }
709
- const f = () => {
717
+ const u = () => {
710
718
  Ie(t.config.chunkBase).catch(() => {
711
719
  });
712
720
  };
713
- for (const g of ["pointerenter", "touchstart", "focus"])
714
- c.addEventListener(g, f, { once: !0, passive: !0 });
715
- const d = Ee(f);
716
- function u() {
717
- q(t.config.chunkBase).catch(() => {
721
+ for (const w of ["pointerenter", "touchstart", "focus"])
722
+ c.addEventListener(w, u, { once: !0, passive: !0 });
723
+ const d = $e(u);
724
+ function b() {
725
+ X(t.config.chunkBase).catch(() => {
718
726
  });
719
727
  }
720
- let m = null;
721
- function $() {
722
- I(), m = document.createElement("div"), m.className = "msg err loadfail", m.setAttribute("role", "alert"), m.innerHTML = `${ze}<span>The report form didn't load. Check your connection and try again.</span><button type="button" data-act="retry">Try again</button><button type="button" data-act="dismiss" aria-label="Dismiss">${qe}</button>`, m.querySelector('[data-act="retry"]').addEventListener("click", () => {
723
- c.focus(), l || (l = h());
724
- }), m.querySelector('[data-act="dismiss"]').addEventListener("click", () => {
725
- c.focus(), I();
726
- }), a.prepend(m);
728
+ let y = null;
729
+ function S() {
730
+ E(), y = document.createElement("div"), y.className = "msg err loadfail", y.setAttribute("role", "alert"), y.innerHTML = `${ze}<span>The report form didn't load. Check your connection and try again.</span><button type="button" data-act="retry">Try again</button><button type="button" data-act="dismiss" aria-label="Dismiss">${Fe}</button>`, y.querySelector('[data-act="retry"]').addEventListener("click", () => {
731
+ c.focus(), l || (l = f());
732
+ }), y.querySelector('[data-act="dismiss"]').addEventListener("click", () => {
733
+ c.focus(), E();
734
+ }), a.prepend(y);
727
735
  }
728
- function I() {
729
- m == null || m.remove(), m = null;
736
+ function E() {
737
+ y == null || y.remove(), y = null;
730
738
  }
731
- let v = null;
732
- function T(g) {
733
- p(), v = Dt(g, {
739
+ let $ = null;
740
+ function g(w) {
741
+ k(), $ = Pt(w, {
734
742
  where: "launcher",
735
- onDismiss: (b) => {
736
- t.dismissAnnouncement(b), c.focus(), p();
743
+ onDismiss: (C) => {
744
+ t.dismissAnnouncement(C), c.focus(), k();
737
745
  }
738
- }), m ? m.after(v) : a.prepend(v);
746
+ }), y ? y.after($) : a.prepend($);
739
747
  }
740
- function p() {
741
- v == null || v.remove(), v = null;
748
+ function k() {
749
+ $ == null || $.remove(), $ = null;
742
750
  }
743
- const k = t.config.announcements === !1 ? () => {
744
- } : Ee(() => {
745
- t.announcements().then((g) => {
746
- const b = g.find((B) => B.placement === "launcher");
747
- b && !l && e.isConnected && T(b);
751
+ const v = t.config.announcements === !1 ? () => {
752
+ } : $e(() => {
753
+ t.announcements().then((w) => {
754
+ const C = w.find((m) => m.placement === "launcher");
755
+ C && !l && e.isConnected && g(C);
748
756
  }).catch(() => {
749
757
  });
750
758
  });
751
759
  return a.append(c), i.appendChild(a), document.body.appendChild(e), t.widgetControls = {
752
- open: () => {
753
- l || c.click();
760
+ open: (w) => {
761
+ if (l) {
762
+ w && l.setMode(w);
763
+ return;
764
+ }
765
+ h = w || "report", c.click();
754
766
  },
755
767
  close: () => {
756
768
  l == null || l.close();
757
769
  },
758
770
  isOpen: () => !!l
759
771
  }, () => {
760
- d(), k(), l == null || l.destroy(), e.remove(), t.widgetControls = null;
772
+ d(), v(), l == null || l.destroy(), e.remove(), t.widgetControls = null;
761
773
  };
762
774
  }
763
- function Xt(t) {
775
+ function qt(t) {
764
776
  return t === "dark" || t === "light" ? t : "auto";
765
777
  }
766
- function Be(t) {
778
+ function Ee(t) {
767
779
  return t === "dark" ? "bc-dark" : t === "light" ? "bc-light" : "bc-auto";
768
780
  }
769
- function Ee(t) {
781
+ function $e(t) {
770
782
  let e = () => {
771
783
  };
772
784
  const n = () => {
@@ -781,7 +793,7 @@ function Ee(t) {
781
793
  return document.readyState === "complete" ? n() : (window.addEventListener("load", n, { once: !0 }), e = () => window.removeEventListener("load", n)), () => e();
782
794
  }
783
795
  const Wt = "Too many requests are being sent from here at the moment. Please try again in a minute.";
784
- function N(t) {
796
+ function K(t) {
785
797
  return t || Wt;
786
798
  }
787
799
  const Jt = typeof window < "u" && window.fetch ? window.fetch.bind(window) : null, Yt = typeof XMLHttpRequest < "u" ? XMLHttpRequest.prototype.open : null, Vt = typeof XMLHttpRequest < "u" ? XMLHttpRequest.prototype.send : null, Zt = [
@@ -805,27 +817,27 @@ const Jt = typeof window < "u" && window.fetch ? window.fetch.bind(window) : nul
805
817
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
806
818
  "application/vnd.ms-excel",
807
819
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
808
- ], $e = [
820
+ ], Te = [
809
821
  "image/png",
810
822
  "image/jpeg",
811
823
  "image/webp",
812
824
  "video/webm",
813
825
  "video/mp4"
814
- ], fi = () => {
826
+ ], bi = () => {
815
827
  var t;
816
828
  return !!((t = navigator == null ? void 0 : navigator.mediaDevices) != null && t.getUserMedia && typeof MediaRecorder < "u");
817
- }, pi = () => {
829
+ }, xi = () => {
818
830
  var t;
819
831
  return !!((t = navigator == null ? void 0 : navigator.mediaDevices) != null && t.getDisplayMedia && typeof MediaRecorder < "u");
820
- }, gi = () => {
832
+ }, ki = () => {
821
833
  var t;
822
834
  return !!((t = navigator == null ? void 0 : navigator.mediaDevices) != null && t.getDisplayMedia);
823
835
  };
824
- function ae(t, e = Zt) {
836
+ function le(t, e = Zt) {
825
837
  const n = String(t || "").split(";")[0].trim().toLowerCase();
826
838
  return e.includes(n) ? n : null;
827
839
  }
828
- async function mi() {
840
+ async function vi() {
829
841
  const t = await navigator.mediaDevices.getDisplayMedia({
830
842
  video: { frameRate: 1 },
831
843
  audio: !1
@@ -842,57 +854,57 @@ async function mi() {
842
854
  t.getTracks().forEach((e) => e.stop());
843
855
  }
844
856
  }
845
- async function wi({ maxMs: t = 12e4, onTick: e, onAutoStop: n } = {}) {
857
+ async function Ci({ maxMs: t = 12e4, onTick: e, onAutoStop: n } = {}) {
846
858
  const i = await navigator.mediaDevices.getDisplayMedia({
847
859
  video: { frameRate: 15 },
848
860
  audio: !1
849
- }), r = ["video/webm;codecs=vp9", "video/webm;codecs=vp8", "video/webm"].find((u) => MediaRecorder.isTypeSupported(u)) || "video/webm", o = new MediaRecorder(i, { mimeType: r, videoBitsPerSecond: 25e5 }), a = [];
850
- o.ondataavailable = (u) => {
851
- u.data.size && a.push(u.data);
861
+ }), r = ["video/webm;codecs=vp9", "video/webm;codecs=vp8", "video/webm"].find((d) => MediaRecorder.isTypeSupported(d)) || "video/webm", o = new MediaRecorder(i, { mimeType: r, videoBitsPerSecond: 25e5 }), a = [];
862
+ o.ondataavailable = (d) => {
863
+ d.data.size && a.push(d.data);
852
864
  }, o.start(1e3);
853
865
  const s = Date.now(), c = setInterval(() => e == null ? void 0 : e(Math.floor((Date.now() - s) / 1e3)), 500), l = () => {
854
- clearInterval(c), clearTimeout(d), i.getTracks().forEach((u) => u.stop());
855
- }, h = new Promise((u) => {
866
+ clearInterval(c), clearTimeout(u), i.getTracks().forEach((d) => d.stop());
867
+ }, h = new Promise((d) => {
856
868
  o.onstop = () => {
857
- l(), u(new Blob(a, { type: r }));
869
+ l(), d(new Blob(a, { type: r }));
858
870
  };
859
871
  }), f = () => {
860
872
  o.state !== "inactive" && o.stop(), n == null || n();
861
873
  };
862
874
  i.getVideoTracks()[0].addEventListener("ended", f);
863
- const d = setTimeout(f, t);
875
+ const u = setTimeout(f, t);
864
876
  return {
865
877
  mime: r,
866
878
  maxMs: t,
867
879
  async stop() {
868
- return clearTimeout(d), o.state !== "inactive" && o.stop(), { blob: await h, mime: r, kind: "VIDEO" };
880
+ return clearTimeout(u), o.state !== "inactive" && o.stop(), { blob: await h, mime: r, kind: "VIDEO" };
869
881
  },
870
882
  cancel() {
871
883
  l(), o.state !== "inactive" && o.stop();
872
884
  }
873
885
  };
874
886
  }
875
- async function yi({ maxMs: t = 12e4, onTick: e, onAutoStop: n } = {}) {
876
- const i = await navigator.mediaDevices.getUserMedia({ audio: !0 }), r = ["audio/webm;codecs=opus", "audio/webm", "audio/mp4", "audio/ogg"].find((u) => MediaRecorder.isTypeSupported(u)) || "", o = new MediaRecorder(i, r ? { mimeType: r } : void 0), a = [];
877
- o.ondataavailable = (u) => {
878
- u.data.size && a.push(u.data);
887
+ async function Ii({ maxMs: t = 12e4, onTick: e, onAutoStop: n } = {}) {
888
+ const i = await navigator.mediaDevices.getUserMedia({ audio: !0 }), r = ["audio/webm;codecs=opus", "audio/webm", "audio/mp4", "audio/ogg"].find((d) => MediaRecorder.isTypeSupported(d)) || "", o = new MediaRecorder(i, r ? { mimeType: r } : void 0), a = [];
889
+ o.ondataavailable = (d) => {
890
+ d.data.size && a.push(d.data);
879
891
  }, o.start(1e3);
880
892
  const s = Date.now(), c = setInterval(() => e == null ? void 0 : e(Math.floor((Date.now() - s) / 1e3)), 500), l = () => {
881
- clearInterval(c), clearTimeout(d), i.getTracks().forEach((u) => u.stop());
882
- }, h = new Promise((u) => {
893
+ clearInterval(c), clearTimeout(u), i.getTracks().forEach((d) => d.stop());
894
+ }, h = new Promise((d) => {
883
895
  o.onstop = () => {
884
- l(), u(new Blob(a, { type: o.mimeType || r }));
896
+ l(), d(new Blob(a, { type: o.mimeType || r }));
885
897
  };
886
- }), d = setTimeout(() => {
898
+ }), u = setTimeout(() => {
887
899
  o.state !== "inactive" && o.stop(), n == null || n();
888
900
  }, t);
889
901
  return {
890
902
  mime: o.mimeType || r,
891
903
  maxMs: t,
892
904
  async stop() {
893
- clearTimeout(d), o.state !== "inactive" && o.stop();
894
- const u = await h;
895
- return { blob: u, mime: u.type || o.mimeType || r, kind: "AUDIO" };
905
+ clearTimeout(u), o.state !== "inactive" && o.stop();
906
+ const d = await h;
907
+ return { blob: d, mime: d.type || o.mimeType || r, kind: "AUDIO" };
896
908
  },
897
909
  cancel() {
898
910
  l(), o.state !== "inactive" && o.stop();
@@ -901,7 +913,7 @@ async function yi({ maxMs: t = 12e4, onTick: e, onAutoStop: n } = {}) {
901
913
  }
902
914
  async function Gt({ apiBase: t, apiKey: e, blob: n, mime: i, onProgress: r }) {
903
915
  var l;
904
- const o = ae(i || n.type);
916
+ const o = le(i || n.type);
905
917
  if (!o)
906
918
  throw new Error(`[BugCatch] ${i || n.type || "that file"} can't be attached.`);
907
919
  const a = await Jt(`${t}/ingest/presign`, {
@@ -915,7 +927,7 @@ async function Gt({ apiBase: t, apiKey: e, blob: n, mime: i, onProgress: r }) {
915
927
  h = ((l = await a.json()) == null ? void 0 : l.message) || "";
916
928
  } catch {
917
929
  }
918
- throw new Error(`[BugCatch] ${N(typeof h == "string" ? h : "")}`);
930
+ throw new Error(`[BugCatch] ${K(typeof h == "string" ? h : "")}`);
919
931
  }
920
932
  if (!a.ok) throw new Error(`[BugCatch] could not start the upload (HTTP ${a.status}).`);
921
933
  const { key: s, uploadUrl: c } = await a.json();
@@ -933,80 +945,80 @@ function Qt(t, e, n, i) {
933
945
  )), a.onabort = () => o(new Error("[BugCatch] upload cancelled.")), Vt.call(a, e);
934
946
  });
935
947
  }
936
- function bi(t) {
948
+ function Si(t) {
937
949
  return t < 1024 ? `${t} B` : t < 1024 * 1024 ? `${(t / 1024).toFixed(0)} KB` : `${(t / 1024 / 1024).toFixed(1)} MB`;
938
950
  }
939
- function xi(t) {
951
+ function Bi(t) {
940
952
  const e = Math.floor(t / 60), n = t % 60;
941
953
  return `${e}:${String(n).padStart(2, "0")}`;
942
954
  }
943
- const Y = "bugcatch.watch", Te = [2e3, 5e3, 15e3, 3e4, 6e4], en = 5e3;
944
- let _ = null;
955
+ const V = "bugcatch.watch", Ae = [2e3, 5e3, 15e3, 3e4, 6e4], en = 5e3;
956
+ let H = null;
945
957
  function tn(t) {
946
- _ = t || null;
958
+ H = t || null;
947
959
  }
948
- const fe = () => _ ? `${Y}:${_}` : Y;
949
- function ee() {
950
- return _ ? `?projectId=${encodeURIComponent(_)}` : "";
960
+ const ge = () => H ? `${V}:${H}` : V;
961
+ function te() {
962
+ return H ? `?projectId=${encodeURIComponent(H)}` : "";
951
963
  }
952
- function E() {
964
+ function T() {
953
965
  try {
954
966
  const t = window.localStorage;
955
- return (t == null ? void 0 : t.getItem(fe())) || (t == null ? void 0 : t.getItem(Y)) || null;
967
+ return (t == null ? void 0 : t.getItem(ge())) || (t == null ? void 0 : t.getItem(V)) || null;
956
968
  } catch {
957
969
  return null;
958
970
  }
959
971
  }
960
- function se(t) {
972
+ function de(t) {
961
973
  var e;
962
974
  if (t)
963
975
  try {
964
- (e = window.localStorage) == null || e.setItem(fe(), t);
976
+ (e = window.localStorage) == null || e.setItem(ge(), t);
965
977
  } catch {
966
978
  }
967
979
  }
968
- function K() {
980
+ function N() {
969
981
  var t, e;
970
982
  try {
971
- (t = window.localStorage) == null || t.removeItem(fe()), (e = window.localStorage) == null || e.removeItem(Y);
983
+ (t = window.localStorage) == null || t.removeItem(ge()), (e = window.localStorage) == null || e.removeItem(V);
972
984
  } catch {
973
985
  }
974
986
  Ze();
975
987
  }
976
- const V = "bugcatch.unread";
988
+ const Z = "bugcatch.unread";
977
989
  function nn(t) {
978
990
  return [(t == null ? void 0 : t.bugId) || "report", (t == null ? void 0 : t.kind) || "status", (t == null ? void 0 : t.at) || ""].join("|");
979
991
  }
980
- function H() {
992
+ function z() {
981
993
  var t;
982
994
  try {
983
- const e = (t = window.localStorage) == null ? void 0 : t.getItem(V), n = e ? JSON.parse(e) : [];
995
+ const e = (t = window.localStorage) == null ? void 0 : t.getItem(Z), n = e ? JSON.parse(e) : [];
984
996
  return Array.isArray(n) ? n.filter((i) => i && typeof i.id == "string") : [];
985
997
  } catch {
986
998
  return [];
987
999
  }
988
1000
  }
989
- function te(t) {
1001
+ function ne(t) {
990
1002
  var e, n;
991
1003
  try {
992
- t.length ? (e = window.localStorage) == null || e.setItem(V, JSON.stringify(t)) : (n = window.localStorage) == null || n.removeItem(V);
1004
+ t.length ? (e = window.localStorage) == null || e.setItem(Z, JSON.stringify(t)) : (n = window.localStorage) == null || n.removeItem(Z);
993
1005
  } catch {
994
1006
  }
995
1007
  }
996
1008
  function on(t) {
997
- const e = { ...t, id: nn(t) }, n = H().filter((i) => i.id !== e.id);
998
- return n.push(e), te(n.slice(-20)), e;
1009
+ const e = { ...t, id: nn(t) }, n = z().filter((i) => i.id !== e.id);
1010
+ return n.push(e), ne(n.slice(-20)), e;
999
1011
  }
1000
1012
  function rn(t) {
1001
- const e = H().filter((n) => n.id !== t);
1002
- return te(e), e;
1013
+ const e = z().filter((n) => n.id !== t);
1014
+ return ne(e), e;
1003
1015
  }
1004
1016
  function an(t) {
1005
- const e = H().filter((n) => n.bugId !== t);
1006
- return te(e), e;
1017
+ const e = z().filter((n) => n.bugId !== t);
1018
+ return ne(e), e;
1007
1019
  }
1008
1020
  function Ze() {
1009
- return te([]), [];
1021
+ return ne([]), [];
1010
1022
  }
1011
1023
  function sn(t, e) {
1012
1024
  let n = t, i = n.indexOf(`
@@ -1030,30 +1042,30 @@ function sn(t, e) {
1030
1042
  return n;
1031
1043
  }
1032
1044
  async function cn({ apiBase: t }) {
1033
- const e = E();
1045
+ const e = T();
1034
1046
  if (!e) return { reporter: null, reports: [] };
1035
- const n = await fetch(`${t}/ingest/watch/reports${ee()}`, {
1047
+ const n = await fetch(`${t}/ingest/watch/reports${te()}`, {
1036
1048
  headers: { Authorization: `Bearer ${e}` }
1037
1049
  });
1038
1050
  if (n.status === 401)
1039
- return K(), { reporter: null, reports: [] };
1051
+ return N(), { reporter: null, reports: [] };
1040
1052
  if (!n.ok) throw new Error(`[BugCatch] could not load your reports (HTTP ${n.status})`);
1041
1053
  return n.json();
1042
1054
  }
1043
1055
  async function ln({ apiBase: t, bugId: e }) {
1044
- const n = E();
1056
+ const n = T();
1045
1057
  if (!n) return null;
1046
- const i = await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}${ee()}`, {
1058
+ const i = await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}${te()}`, {
1047
1059
  headers: { Authorization: `Bearer ${n}` }
1048
1060
  });
1049
1061
  if (i.status === 401)
1050
- return K(), null;
1062
+ return N(), null;
1051
1063
  if (i.status === 404) return null;
1052
1064
  if (!i.ok) throw new Error(`[BugCatch] could not load that report (HTTP ${i.status})`);
1053
1065
  return i.json();
1054
1066
  }
1055
- async function un({ apiBase: t, bugId: e, body: n, attachments: i }) {
1056
- const r = E();
1067
+ async function dn({ apiBase: t, bugId: e, body: n, attachments: i }) {
1068
+ const r = T();
1057
1069
  if (!r) throw new Error("[BugCatch] nothing filed from this browser yet.");
1058
1070
  const o = await fetch(
1059
1071
  `${t}/ingest/watch/reports/${encodeURIComponent(e)}/messages`,
@@ -1067,7 +1079,7 @@ async function un({ apiBase: t, bugId: e, body: n, attachments: i }) {
1067
1079
  }
1068
1080
  );
1069
1081
  if (o.status === 401)
1070
- throw K(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
1082
+ throw N(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
1071
1083
  if (!o.ok) {
1072
1084
  let a = "";
1073
1085
  try {
@@ -1075,11 +1087,11 @@ async function un({ apiBase: t, bugId: e, body: n, attachments: i }) {
1075
1087
  a = Array.isArray(s.message) ? s.message.join(", ") : s.message || "";
1076
1088
  } catch {
1077
1089
  }
1078
- throw o.status === 429 ? new Error(N(a)) : new Error(a || `[BugCatch] could not send that (HTTP ${o.status}).`);
1090
+ throw o.status === 429 ? new Error(K(a)) : new Error(a || `[BugCatch] could not send that (HTTP ${o.status}).`);
1079
1091
  }
1080
1092
  return o.json();
1081
1093
  }
1082
- async function dn({ apiBase: t, apiKey: e, projectId: n }) {
1094
+ async function un({ apiBase: t, apiKey: e, projectId: n }) {
1083
1095
  const i = { agent: !1, live: !1 };
1084
1096
  try {
1085
1097
  const r = await fetch(
@@ -1117,14 +1129,14 @@ async function hn({ apiBase: t, apiKey: e, token: n, payload: i, watchToken: r }
1117
1129
  } catch {
1118
1130
  }
1119
1131
  const s = new Error(
1120
- o.status === 429 ? N(a) : a || `[BugCatch] the call could not be started (HTTP ${o.status}).`
1132
+ o.status === 429 ? K(a) : a || `[BugCatch] the call could not be started (HTTP ${o.status}).`
1121
1133
  );
1122
1134
  throw s.status = o.status, s;
1123
1135
  }
1124
1136
  return o.json();
1125
1137
  }
1126
- async function Ae({ apiBase: t, bugId: e }) {
1127
- const n = E();
1138
+ async function je({ apiBase: t, bugId: e }) {
1139
+ const n = T();
1128
1140
  if (!n) return !1;
1129
1141
  try {
1130
1142
  const i = await fetch(
@@ -1139,14 +1151,14 @@ async function Ae({ apiBase: t, bugId: e }) {
1139
1151
  }
1140
1152
  }
1141
1153
  async function fn({ apiBase: t, bugId: e }) {
1142
- const n = E();
1154
+ const n = T();
1143
1155
  if (!n) throw new Error("[BugCatch] nothing filed from this browser yet.");
1144
1156
  const i = await fetch(
1145
1157
  `${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call`,
1146
1158
  { method: "POST", headers: { Authorization: `Bearer ${n}` } }
1147
1159
  );
1148
1160
  if (i.status === 401)
1149
- throw K(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
1161
+ throw N(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
1150
1162
  if (!i.ok) {
1151
1163
  let r = "";
1152
1164
  try {
@@ -1159,7 +1171,7 @@ async function fn({ apiBase: t, bugId: e }) {
1159
1171
  return i.json();
1160
1172
  }
1161
1173
  async function pn({ apiBase: t, bugId: e, callId: n }) {
1162
- const i = E();
1174
+ const i = T();
1163
1175
  if (i)
1164
1176
  try {
1165
1177
  await fetch(
@@ -1170,14 +1182,14 @@ async function pn({ apiBase: t, bugId: e, callId: n }) {
1170
1182
  }
1171
1183
  }
1172
1184
  async function gn({ apiBase: t, bugId: e, callId: n }) {
1173
- const i = E();
1185
+ const i = T();
1174
1186
  if (!i) throw new Error("[BugCatch] nothing filed from this browser yet.");
1175
1187
  const r = await fetch(
1176
1188
  `${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/answer`,
1177
1189
  { method: "POST", headers: { Authorization: `Bearer ${i}` } }
1178
1190
  );
1179
1191
  if (r.status === 401)
1180
- throw K(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
1192
+ throw N(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
1181
1193
  if (r.status === 409)
1182
1194
  throw new Error("[BugCatch] that call is no longer ringing.");
1183
1195
  if (!r.ok) {
@@ -1191,8 +1203,8 @@ async function gn({ apiBase: t, bugId: e, callId: n }) {
1191
1203
  }
1192
1204
  return r.json();
1193
1205
  }
1194
- async function je({ apiBase: t, bugId: e, callId: n }) {
1195
- const i = E();
1206
+ async function Oe({ apiBase: t, bugId: e, callId: n }) {
1207
+ const i = T();
1196
1208
  if (i)
1197
1209
  try {
1198
1210
  await fetch(
@@ -1205,26 +1217,26 @@ async function je({ apiBase: t, bugId: e, callId: n }) {
1205
1217
  function mn({ apiBase: t, onUpdate: e }) {
1206
1218
  let n = !0, i = 0, r = null;
1207
1219
  async function o() {
1208
- const a = E();
1220
+ const a = T();
1209
1221
  if (!a) throw new Error("nothing filed from this browser yet");
1210
1222
  r = new AbortController();
1211
- const s = await fetch(`${t}/ingest/watch/stream${ee()}`, {
1223
+ const s = await fetch(`${t}/ingest/watch/stream${te()}`, {
1212
1224
  headers: { Authorization: `Bearer ${a}`, Accept: "text/event-stream" },
1213
1225
  signal: r.signal
1214
1226
  });
1215
1227
  if (s.status === 401)
1216
- throw n = !1, K(), new Error("subscription no longer valid");
1228
+ throw n = !1, N(), new Error("subscription no longer valid");
1217
1229
  if (!s.ok || !s.body) throw new Error(`stream failed (${s.status})`);
1218
1230
  const c = Date.now(), l = s.body.getReader(), h = new TextDecoder();
1219
1231
  let f = "";
1220
1232
  try {
1221
1233
  for (; ; ) {
1222
- const { value: d, done: u } = await l.read();
1223
- if (u) break;
1224
- f += h.decode(d, { stream: !0 }), f = sn(f, (m) => {
1225
- if (m.type !== "ping")
1234
+ const { value: u, done: d } = await l.read();
1235
+ if (d) break;
1236
+ f += h.decode(u, { stream: !0 }), f = sn(f, (b) => {
1237
+ if (b.type !== "ping")
1226
1238
  try {
1227
- e(m);
1239
+ e(b);
1228
1240
  } catch {
1229
1241
  }
1230
1242
  });
@@ -1241,7 +1253,7 @@ function mn({ apiBase: t, onUpdate: e }) {
1241
1253
  if ((s == null ? void 0 : s.name) === "AbortError") return;
1242
1254
  }
1243
1255
  if (!n) return;
1244
- const a = Te[Math.min(i, Te.length - 1)];
1256
+ const a = Ae[Math.min(i, Ae.length - 1)];
1245
1257
  i += 1, await new Promise((s) => setTimeout(s, a));
1246
1258
  }
1247
1259
  })(), () => {
@@ -1267,7 +1279,7 @@ const wn = {
1267
1279
  ring: "rgba(255,255,255,.09)",
1268
1280
  brand: "#a59cff"
1269
1281
  };
1270
- function Oe(t) {
1282
+ function Me(t) {
1271
1283
  return t != null && t.summary ? t.summary : `Your report ${wn[t == null ? void 0 : t.status] || "was updated"}`;
1272
1284
  }
1273
1285
  function bn(t) {
@@ -1303,7 +1315,7 @@ function vn({
1303
1315
  } = {}) {
1304
1316
  const [o, a] = String(e).split("-"), s = o === "top", c = a === "left", l = /* @__PURE__ */ new Map();
1305
1317
  let h = null, f = null;
1306
- function d() {
1318
+ function u() {
1307
1319
  return h != null && h.isConnected || (h = document.createElement("div"), h.setAttribute("data-bugcatch", "updates"), h.style.cssText = [
1308
1320
  "position:fixed",
1309
1321
  `${s ? "top" : "bottom"}:${20 + kn()}px`,
@@ -1321,30 +1333,30 @@ function vn({
1321
1333
  "pointer-events:none"
1322
1334
  ].join(";"), document.body.appendChild(h)), h;
1323
1335
  }
1324
- function u(p) {
1325
- if (!p._bcShown) {
1326
- p.remove();
1336
+ function d(g) {
1337
+ if (!g._bcShown) {
1338
+ g.remove();
1327
1339
  return;
1328
1340
  }
1329
- p.style.opacity = "0", p.style.transform = `translateY(${s ? -8 : 8}px)`, setTimeout(() => p.remove(), 250);
1341
+ g.style.opacity = "0", g.style.transform = `translateY(${s ? -8 : 8}px)`, setTimeout(() => g.remove(), 250);
1330
1342
  }
1331
- const m = t || re, $ = t ? Ye(t) : Je;
1332
- function I(p, k) {
1333
- const g = document.createElement("button");
1334
- return g.type = "button", g.textContent = p, g.style.cssText = [
1343
+ const b = t || ce, y = t ? Ye(t) : Je;
1344
+ function S(g, k) {
1345
+ const v = document.createElement("button");
1346
+ return v.type = "button", v.textContent = g, v.style.cssText = [
1335
1347
  "padding:6px 12px",
1336
1348
  "border:0",
1337
1349
  `box-shadow:${k ? "none" : `inset 0 0 0 1px ${j.ring}`}`,
1338
1350
  "border-radius:999px",
1339
- `background:${k ? m : "rgba(255,255,255,.06)"}`,
1340
- `color:${k ? $ : j.fg}`,
1351
+ `background:${k ? b : "rgba(255,255,255,.06)"}`,
1352
+ `color:${k ? y : j.fg}`,
1341
1353
  "font:560 12px/1.4 inherit",
1342
1354
  "cursor:pointer",
1343
1355
  "white-space:nowrap"
1344
- ].join(";"), g;
1356
+ ].join(";"), v;
1345
1357
  }
1346
- function v(p) {
1347
- var L;
1358
+ function E(g) {
1359
+ var O;
1348
1360
  const k = document.createElement("div");
1349
1361
  k.setAttribute("role", "status"), k.style.cssText = [
1350
1362
  "box-sizing:border-box",
@@ -1360,26 +1372,26 @@ function vn({
1360
1372
  "transition:opacity .2s ease,transform .2s ease",
1361
1373
  "pointer-events:auto"
1362
1374
  ].join(";");
1363
- const g = document.createElement("div");
1364
- g.style.cssText = "display:flex;align-items:baseline;gap:8px;font-weight:600;margin-bottom:2px";
1365
- const b = document.createElement("span");
1366
- b.setAttribute("aria-hidden", "true"), b.style.cssText = `flex:none;width:7px;height:7px;border-radius:50%;transform:translateY(-1px);background:${yn[p == null ? void 0 : p.kind] || t || j.brand}`;
1367
- const B = document.createElement("span");
1368
- B.textContent = Oe(p), g.append(b, B);
1369
- const y = document.createElement("div");
1370
- y.style.cssText = (p == null ? void 0 : p.kind) === "reply" ? `color:${j.muted};padding-left:15px;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden` : `color:${j.muted};padding-left:15px`, y.textContent = bn(p);
1371
- const C = document.createElement("div");
1372
- C.style.cssText = "display:flex;align-items:center;gap:8px;margin-top:10px;padding-left:15px;flex-wrap:wrap";
1375
+ const v = document.createElement("div");
1376
+ v.style.cssText = "display:flex;align-items:baseline;gap:8px;font-weight:600;margin-bottom:2px";
1377
+ const w = document.createElement("span");
1378
+ w.setAttribute("aria-hidden", "true"), w.style.cssText = `flex:none;width:7px;height:7px;border-radius:50%;transform:translateY(-1px);background:${yn[g == null ? void 0 : g.kind] || t || j.brand}`;
1379
+ const C = document.createElement("span");
1380
+ C.textContent = Me(g), v.append(w, C);
1381
+ const m = document.createElement("div");
1382
+ m.style.cssText = (g == null ? void 0 : g.kind) === "reply" ? `color:${j.muted};padding-left:15px;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden` : `color:${j.muted};padding-left:15px`, m.textContent = bn(g);
1383
+ const B = document.createElement("div");
1384
+ B.style.cssText = "display:flex;align-items:center;gap:8px;margin-top:10px;padding-left:15px;flex-wrap:wrap";
1373
1385
  const A = document.createElement("span");
1374
- A.style.cssText = `color:${j.faint};font-size:11px;margin-right:auto`, A.textContent = xn(p == null ? void 0 : p.at);
1375
- const S = I("Mark as read", !1);
1376
- if (S.setAttribute("aria-label", `Mark as read: ${Oe(p)}`), S.addEventListener("click", () => n == null ? void 0 : n(p.id)), C.append(A, S), (L = p == null ? void 0 : p.call) != null && L.offered && typeof r == "function") {
1377
- const ye = I("Talk it through", !0);
1378
- ye.addEventListener("click", () => r(p)), C.insertBefore(ye, S);
1386
+ A.style.cssText = `color:${j.faint};font-size:11px;margin-right:auto`, A.textContent = xn(g == null ? void 0 : g.at);
1387
+ const I = S("Mark as read", !1);
1388
+ if (I.setAttribute("aria-label", `Mark as read: ${Me(g)}`), I.addEventListener("click", () => n == null ? void 0 : n(g.id)), B.append(A, I), (O = g == null ? void 0 : g.call) != null && O.offered && typeof r == "function") {
1389
+ const xe = S("Talk it through", !0);
1390
+ xe.addEventListener("click", () => r(g)), B.insertBefore(xe, I);
1379
1391
  }
1380
- return k.append(g, y, C), k;
1392
+ return k.append(v, m, B), k;
1381
1393
  }
1382
- function T(p) {
1394
+ function $(g) {
1383
1395
  const k = document.createElement("div");
1384
1396
  k.style.cssText = [
1385
1397
  "box-sizing:border-box",
@@ -1395,10 +1407,10 @@ function vn({
1395
1407
  `box-shadow:0 0 0 1px ${j.ring},0 12px 30px -10px rgba(0,0,0,.5)`,
1396
1408
  "pointer-events:auto"
1397
1409
  ].join(";");
1398
- const g = document.createElement("span");
1399
- g.style.cssText = "margin-right:auto", g.textContent = `${p} more update${p === 1 ? "" : "s"}`;
1400
- const b = I("Mark all as read", !1);
1401
- return b.style.cssText += ";padding:4px 9px", b.addEventListener("click", () => i == null ? void 0 : i()), k.append(g, b), k;
1410
+ const v = document.createElement("span");
1411
+ v.style.cssText = "margin-right:auto", v.textContent = `${g} more update${g === 1 ? "" : "s"}`;
1412
+ const w = S("Mark all as read", !1);
1413
+ return w.style.cssText += ";padding:4px 9px", w.addEventListener("click", () => i == null ? void 0 : i()), k.append(v, w), k;
1402
1414
  }
1403
1415
  return {
1404
1416
  /**
@@ -1408,28 +1420,28 @@ function vn({
1408
1420
  * corner the reporter's eye is already trained on — so the stack grows away
1409
1421
  * from the launcher rather than over it.
1410
1422
  */
1411
- render(p) {
1412
- const k = Array.isArray(p) ? p : [];
1423
+ render(g) {
1424
+ const k = Array.isArray(g) ? g : [];
1413
1425
  if (!k.length) {
1414
- for (const S of l.values()) u(S);
1426
+ for (const I of l.values()) d(I);
1415
1427
  l.clear(), f == null || f.remove(), f = null, h == null || h.remove(), h = null;
1416
1428
  return;
1417
1429
  }
1418
- const g = k.slice(-3), b = new Set(g.map((S) => S.id)), B = d();
1419
- for (const [S, L] of l)
1420
- b.has(S) || (u(L), l.delete(S));
1421
- const y = [];
1422
- for (const S of g) {
1423
- if (l.has(S.id)) continue;
1424
- const L = v(S);
1425
- l.set(S.id, L), y.push(L);
1430
+ const v = k.slice(-3), w = new Set(v.map((I) => I.id)), C = u();
1431
+ for (const [I, O] of l)
1432
+ w.has(I) || (d(O), l.delete(I));
1433
+ const m = [];
1434
+ for (const I of v) {
1435
+ if (l.has(I.id)) continue;
1436
+ const O = E(I);
1437
+ l.set(I.id, O), m.push(O);
1426
1438
  }
1427
- const C = s ? [...g].reverse() : g;
1428
- for (const S of C) B.appendChild(l.get(S.id));
1429
- const A = k.length - g.length;
1430
- A > 0 ? (f == null || f.remove(), f = T(A), s ? B.appendChild(f) : B.insertBefore(f, B.firstChild)) : (f == null || f.remove(), f = null), requestAnimationFrame(() => {
1431
- for (const S of y)
1432
- S.isConnected && (S._bcShown = !0, S.style.opacity = "1", S.style.transform = "translateY(0)");
1439
+ const B = s ? [...v].reverse() : v;
1440
+ for (const I of B) C.appendChild(l.get(I.id));
1441
+ const A = k.length - v.length;
1442
+ A > 0 ? (f == null || f.remove(), f = $(A), s ? C.appendChild(f) : C.insertBefore(f, C.firstChild)) : (f == null || f.remove(), f = null), requestAnimationFrame(() => {
1443
+ for (const I of m)
1444
+ I.isConnected && (I._bcShown = !0, I.style.opacity = "1", I.style.transform = "translateY(0)");
1433
1445
  });
1434
1446
  },
1435
1447
  destroy() {
@@ -1437,11 +1449,11 @@ function vn({
1437
1449
  }
1438
1450
  };
1439
1451
  }
1440
- async function In({ apiBase: t, apiKey: e, projectId: n, sessionToken: i }) {
1452
+ async function Cn({ apiBase: t, apiKey: e, projectId: n, sessionToken: i }) {
1441
1453
  try {
1442
1454
  const r = await fetch(
1443
1455
  `${t}/ingest/known-issues?projectId=${encodeURIComponent(n)}`,
1444
- { headers: pe(e, i) }
1456
+ { headers: me(e, i) }
1445
1457
  );
1446
1458
  if (!r.ok) return [];
1447
1459
  const o = await r.json();
@@ -1450,9 +1462,9 @@ async function In({ apiBase: t, apiKey: e, projectId: n, sessionToken: i }) {
1450
1462
  return [];
1451
1463
  }
1452
1464
  }
1453
- async function Cn({ apiBase: t, apiKey: e, projectId: n, q: i, sessionToken: r, signal: o }) {
1465
+ async function In({ apiBase: t, apiKey: e, projectId: n, q: i, sessionToken: r, signal: o }) {
1454
1466
  try {
1455
- const a = `${t}/ingest/known-issues/match?projectId=${encodeURIComponent(n)}&q=${encodeURIComponent(i)}`, s = await fetch(a, { headers: pe(e, r), signal: o });
1467
+ const a = `${t}/ingest/known-issues/match?projectId=${encodeURIComponent(n)}&q=${encodeURIComponent(i)}`, s = await fetch(a, { headers: me(e, r), signal: o });
1456
1468
  if (!s.ok) return [];
1457
1469
  const c = await s.json();
1458
1470
  return Array.isArray(c == null ? void 0 : c.issues) ? c.issues : [];
@@ -1471,11 +1483,11 @@ async function Sn({
1471
1483
  logs: s,
1472
1484
  sessionToken: c
1473
1485
  }) {
1474
- const l = E(), h = await fetch(
1486
+ const l = T(), h = await fetch(
1475
1487
  `${t}/ingest/known-issues/${encodeURIComponent(i)}/join`,
1476
1488
  {
1477
1489
  method: "POST",
1478
- headers: pe(e, c),
1490
+ headers: me(e, c),
1479
1491
  body: JSON.stringify({
1480
1492
  projectId: n,
1481
1493
  reporterEmail: r,
@@ -1488,9 +1500,9 @@ async function Sn({
1488
1500
  );
1489
1501
  if (!h.ok) throw new Error(await Bn(h));
1490
1502
  const f = await h.json();
1491
- return f != null && f.watchToken && se(f.watchToken), f;
1503
+ return f != null && f.watchToken && de(f.watchToken), f;
1492
1504
  }
1493
- function pe(t, e) {
1505
+ function me(t, e) {
1494
1506
  return {
1495
1507
  "Content-Type": "application/json",
1496
1508
  "X-BugCatch-Key": t,
@@ -1504,12 +1516,12 @@ async function Bn(t) {
1504
1516
  e = Array.isArray(n.message) ? n.message.join(", ") : n.message || "";
1505
1517
  } catch {
1506
1518
  }
1507
- return t.status === 429 ? N(e) : e || `Could not add you to this issue (HTTP ${t.status})`;
1519
+ return t.status === 429 ? K(e) : e || `Could not add you to this issue (HTTP ${t.status})`;
1508
1520
  }
1509
1521
  async function En({ apiBase: t, bugId: e, score: n, comment: i }) {
1510
- const r = E();
1522
+ const r = T();
1511
1523
  if (!r) throw new Error("This browser cannot access that report.");
1512
- const o = await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/rating${ee()}`, {
1524
+ const o = await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/rating${te()}`, {
1513
1525
  method: "POST",
1514
1526
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${r}` },
1515
1527
  body: JSON.stringify({ score: n, ...i ? { comment: i } : {} })
@@ -1521,7 +1533,7 @@ async function En({ apiBase: t, bugId: e, score: n, comment: i }) {
1521
1533
  return a;
1522
1534
  }
1523
1535
  async function $n({ apiBase: t, bugId: e, ...n }) {
1524
- const i = E();
1536
+ const i = T();
1525
1537
  if (!i) throw new Error("This browser cannot access that report.");
1526
1538
  const r = await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/verification`, {
1527
1539
  method: "POST",
@@ -1531,19 +1543,19 @@ async function $n({ apiBase: t, bugId: e, ...n }) {
1531
1543
  if (!r.ok) throw new Error(o.message || "Could not record feedback. Please refresh and try again.");
1532
1544
  return o;
1533
1545
  }
1534
- const Tn = "bugcatch.session.", ge = (t) => `${Tn}${t}`, me = /* @__PURE__ */ new Map();
1546
+ const Tn = "bugcatch.session.", we = (t) => `${Tn}${t}`, ye = /* @__PURE__ */ new Map();
1535
1547
  function M(t) {
1536
1548
  var e;
1537
1549
  if (!t) return null;
1538
1550
  try {
1539
- const n = (e = window.localStorage) == null ? void 0 : e.getItem(ge(t));
1551
+ const n = (e = window.localStorage) == null ? void 0 : e.getItem(we(t));
1540
1552
  if (n) {
1541
1553
  const i = JSON.parse(n);
1542
1554
  if (i != null && i.token) return i;
1543
1555
  }
1544
1556
  } catch {
1545
1557
  }
1546
- return me.get(t) || null;
1558
+ return ye.get(t) || null;
1547
1559
  }
1548
1560
  function An(t, e) {
1549
1561
  var i;
@@ -1553,23 +1565,23 @@ function An(t, e) {
1553
1565
  email: e.email || null,
1554
1566
  name: e.name || null
1555
1567
  };
1556
- me.set(t, n);
1568
+ ye.set(t, n);
1557
1569
  try {
1558
- (i = window.localStorage) == null || i.setItem(ge(t), JSON.stringify(n));
1570
+ (i = window.localStorage) == null || i.setItem(we(t), JSON.stringify(n));
1559
1571
  } catch {
1560
1572
  }
1561
1573
  }
1562
- function ce(t) {
1574
+ function ue(t) {
1563
1575
  var e;
1564
1576
  if (t) {
1565
- me.delete(t);
1577
+ ye.delete(t);
1566
1578
  try {
1567
- (e = window.localStorage) == null || e.removeItem(ge(t));
1579
+ (e = window.localStorage) == null || e.removeItem(we(t));
1568
1580
  } catch {
1569
1581
  }
1570
1582
  }
1571
1583
  }
1572
- function ne({ apiKey: t, token: e }) {
1584
+ function ie({ apiKey: t, token: e }) {
1573
1585
  return {
1574
1586
  "Content-Type": "application/json",
1575
1587
  "X-BugCatch-Key": t,
@@ -1586,14 +1598,14 @@ async function Ge(t) {
1586
1598
  e = Array.isArray(n.message) ? n.message.join(", ") : n.message || "";
1587
1599
  } catch {
1588
1600
  }
1589
- return t.status === 429 ? N(e) : e || `Request failed (HTTP ${t.status})`;
1601
+ return t.status === 429 ? K(e) : e || `Request failed (HTTP ${t.status})`;
1590
1602
  }
1591
1603
  async function jn({ apiBase: t, apiKey: e, projectId: n, token: i }) {
1592
1604
  const r = { mode: "off", signedIn: null, signedOutReason: null };
1593
1605
  try {
1594
1606
  const o = await fetch(
1595
1607
  `${t}/ingest/login?projectId=${encodeURIComponent(n)}`,
1596
- { headers: ne({ apiKey: e, token: i }) }
1608
+ { headers: ie({ apiKey: e, token: i }) }
1597
1609
  );
1598
1610
  if (!o.ok) return r;
1599
1611
  const a = await o.json();
@@ -1609,7 +1621,7 @@ async function jn({ apiBase: t, apiKey: e, projectId: n, token: i }) {
1609
1621
  async function On({ apiBase: t, apiKey: e, projectId: n, email: i, name: r }) {
1610
1622
  const o = await fetch(`${t}/ingest/login/start`, {
1611
1623
  method: "POST",
1612
- headers: ne({ apiKey: e }),
1624
+ headers: ie({ apiKey: e }),
1613
1625
  body: JSON.stringify({ projectId: n, email: i, ...r ? { name: r } : {} })
1614
1626
  });
1615
1627
  if (!o.ok) throw new Error(await Ge(o));
@@ -1618,7 +1630,7 @@ async function On({ apiBase: t, apiKey: e, projectId: n, email: i, name: r }) {
1618
1630
  async function Mn({ apiBase: t, apiKey: e, projectId: n, email: i, code: r }) {
1619
1631
  const o = await fetch(`${t}/ingest/login`, {
1620
1632
  method: "POST",
1621
- headers: ne({ apiKey: e }),
1633
+ headers: ie({ apiKey: e }),
1622
1634
  body: JSON.stringify({ projectId: n, email: i, code: r })
1623
1635
  });
1624
1636
  if (!o.ok) throw new Error(await Ge(o));
@@ -1626,11 +1638,11 @@ async function Mn({ apiBase: t, apiKey: e, projectId: n, email: i, code: r }) {
1626
1638
  return An(n, s), s;
1627
1639
  }
1628
1640
  async function Rn({ apiBase: t, apiKey: e, projectId: n, token: i }) {
1629
- if (ce(n), !i) return { signedOut: !0 };
1641
+ if (ue(n), !i) return { signedOut: !0 };
1630
1642
  try {
1631
1643
  await fetch(`${t}/ingest/logout`, {
1632
1644
  method: "POST",
1633
- headers: ne({ apiKey: e, token: i }),
1645
+ headers: ie({ apiKey: e, token: i }),
1634
1646
  body: JSON.stringify({ projectId: n })
1635
1647
  });
1636
1648
  } catch {
@@ -1650,7 +1662,7 @@ if (typeof window < "u" && window.addEventListener)
1650
1662
  function Ln() {
1651
1663
  return Qe;
1652
1664
  }
1653
- const Kn = 2e4, et = 120, le = 200;
1665
+ const Kn = 2e4, et = 120, he = 200;
1654
1666
  function tt(t) {
1655
1667
  if (typeof t != "string" || !t.trim() || t.length > 400) return null;
1656
1668
  try {
@@ -1675,80 +1687,80 @@ function ot(t) {
1675
1687
  function Nn(t, e) {
1676
1688
  return ((t.slice(e.start, e.valueStart) + t.slice(e.valueEnd, e.end)).match(/[a-z]/gi) || []).length;
1677
1689
  }
1678
- const Un = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[A-Za-z0-9][\w-]{5,40}/gi, Me = /[\w-]/;
1679
- function ki(t, e) {
1680
- const n = (t || []).filter((d) => d && d.scan !== !1 && d.pattern), i = [], r = [], o = (e || []).map((d) => typeof d == "string" ? d.slice(0, Kn) : "");
1681
- o.forEach((d, u) => {
1682
- d && n.forEach((m, $) => {
1683
- const I = tt(m.pattern);
1684
- if (!I) return;
1685
- let v, T = 0;
1686
- for (I.lastIndex = 0; (v = I.exec(d)) !== null && !(++T > le); ) {
1687
- if (v[0] === "") {
1688
- I.lastIndex += 1;
1690
+ const Un = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[A-Za-z0-9][\w-]{5,40}/gi, Re = /[\w-]/;
1691
+ function Ei(t, e) {
1692
+ const n = (t || []).filter((u) => u && u.scan !== !1 && u.pattern), i = [], r = [], o = (e || []).map((u) => typeof u == "string" ? u.slice(0, Kn) : "");
1693
+ o.forEach((u, d) => {
1694
+ u && n.forEach((b, y) => {
1695
+ const S = tt(b.pattern);
1696
+ if (!S) return;
1697
+ let E, $ = 0;
1698
+ for (S.lastIndex = 0; (E = S.exec(u)) !== null && !(++$ > he); ) {
1699
+ if (E[0] === "") {
1700
+ S.lastIndex += 1;
1689
1701
  continue;
1690
1702
  }
1691
- const p = ot(v);
1692
- if (!p) continue;
1693
- const k = v.length > 1 && v[1] !== void 0 ? v[1] : v[0], g = v.index + Math.max(0, v[0].indexOf(k)), b = {
1694
- block: u,
1695
- order: $,
1696
- key: m.key,
1697
- label: m.label,
1698
- value: it(m, p.value),
1699
- start: p.start,
1700
- end: p.end,
1701
- valueStart: g,
1702
- valueEnd: g + k.length
1703
+ const g = ot(E);
1704
+ if (!g) continue;
1705
+ const k = E.length > 1 && E[1] !== void 0 ? E[1] : E[0], v = E.index + Math.max(0, E[0].indexOf(k)), w = {
1706
+ block: d,
1707
+ order: y,
1708
+ key: b.key,
1709
+ label: b.label,
1710
+ value: it(b, g.value),
1711
+ start: g.start,
1712
+ end: g.end,
1713
+ valueStart: v,
1714
+ valueEnd: v + k.length
1703
1715
  };
1704
- b.weight = Nn(d, b), i.push(b);
1716
+ w.weight = Nn(u, w), i.push(w);
1705
1717
  }
1706
1718
  });
1707
1719
  });
1708
- const a = i.filter((d) => !i.some((u) => u !== d && u.block === d.block && u.key !== d.key && u.valueStart <= d.valueStart && u.valueEnd >= d.valueEnd && u.weight > d.weight)), s = /* @__PURE__ */ new Map();
1709
- for (const d of a) {
1710
- const u = d.value.toLowerCase();
1711
- s.has(u) || s.set(u, { value: d.value, keys: /* @__PURE__ */ new Map() });
1712
- const m = s.get(u);
1713
- m.keys.has(d.key) || m.keys.set(d.key, { key: d.key, label: d.label, order: d.order });
1720
+ const a = i.filter((u) => !i.some((d) => d !== u && d.block === u.block && d.key !== u.key && d.valueStart <= u.valueStart && d.valueEnd >= u.valueEnd && d.weight > u.weight)), s = /* @__PURE__ */ new Map();
1721
+ for (const u of a) {
1722
+ const d = u.value.toLowerCase();
1723
+ s.has(d) || s.set(d, { value: u.value, keys: /* @__PURE__ */ new Map() });
1724
+ const b = s.get(d);
1725
+ b.keys.has(u.key) || b.keys.set(u.key, { key: u.key, label: u.label, order: u.order });
1714
1726
  }
1715
1727
  const c = [], l = [], h = /* @__PURE__ */ new Map();
1716
- for (const d of s.values()) {
1717
- const u = [...d.keys.values()].sort((I, v) => I.order - v.order);
1718
- if (u.length > 1) {
1719
- l.push({ value: d.value, kinds: u.map(({ key: I, label: v }) => ({ key: I, label: v })) });
1728
+ for (const u of s.values()) {
1729
+ const d = [...u.keys.values()].sort((S, E) => S.order - E.order);
1730
+ if (d.length > 1) {
1731
+ l.push({ value: u.value, kinds: d.map(({ key: S, label: E }) => ({ key: S, label: E })) });
1720
1732
  continue;
1721
1733
  }
1722
- const [{ key: m, label: $ }] = u;
1723
- h.has(m) || h.set(m, []), h.get(m).push({ key: m, label: $, value: d.value });
1734
+ const [{ key: b, label: y }] = d;
1735
+ h.has(b) || h.set(b, []), h.get(b).push({ key: b, label: y, value: u.value });
1724
1736
  }
1725
- for (const d of h.values())
1726
- if (d.length === 1) c.push(d[0]);
1727
- else for (const u of d) l.push({ value: u.value, kinds: [{ key: u.key, label: u.label }] });
1737
+ for (const u of h.values())
1738
+ if (u.length === 1) c.push(u[0]);
1739
+ else for (const d of u) l.push({ value: d.value, kinds: [{ key: d.key, label: d.label }] });
1728
1740
  const f = new Set(s.keys());
1729
- return o.forEach((d, u) => {
1730
- if (!d) return;
1731
- const m = i.filter((T) => T.block === u), $ = new RegExp(Un.source, "gi");
1732
- let I, v = 0;
1733
- for (; (I = $.exec(d)) !== null && ++v <= le; ) {
1734
- const T = I.index, p = T + I[0].length;
1735
- if (m.some((C) => T < C.end && p > C.start)) continue;
1736
- const k = d[T - 1] || "", g = d[p] || "";
1737
- if (Me.test(k) || Me.test(g) || k === "/" || k === "@" || g === "@" || k === "." || g === "." && /\w/.test(d[p + 1] || "") || !/\d/.test(I[0])) continue;
1738
- const b = nt(I[0]), B = b.toLowerCase();
1739
- if (f.has(B)) continue;
1740
- const y = (t || []).filter((C) => C && Pn(C, b)).map(({ key: C, label: A }) => ({ key: C, label: A }));
1741
- y.length && (f.add(B), r.push({ value: b, kinds: y }));
1741
+ return o.forEach((u, d) => {
1742
+ if (!u) return;
1743
+ const b = i.filter(($) => $.block === d), y = new RegExp(Un.source, "gi");
1744
+ let S, E = 0;
1745
+ for (; (S = y.exec(u)) !== null && ++E <= he; ) {
1746
+ const $ = S.index, g = $ + S[0].length;
1747
+ if (b.some((B) => $ < B.end && g > B.start)) continue;
1748
+ const k = u[$ - 1] || "", v = u[g] || "";
1749
+ if (Re.test(k) || Re.test(v) || k === "/" || k === "@" || v === "@" || k === "." || v === "." && /\w/.test(u[g + 1] || "") || !/\d/.test(S[0])) continue;
1750
+ const w = nt(S[0]), C = w.toLowerCase();
1751
+ if (f.has(C)) continue;
1752
+ const m = (t || []).filter((B) => B && Dn(B, w)).map(({ key: B, label: A }) => ({ key: B, label: A }));
1753
+ m.length && (f.add(C), r.push({ value: w, kinds: m }));
1742
1754
  }
1743
1755
  }), { found: c, conflicts: l, loose: r };
1744
1756
  }
1745
- function Pn(t, e) {
1757
+ function Dn(t, e) {
1746
1758
  const n = typeof e == "string" ? e.trim() : "";
1747
1759
  if (!n || n.length > et) return null;
1748
1760
  const i = tt(t && (t.valuePattern || t.pattern));
1749
1761
  if (!i) return null;
1750
1762
  let r, o = 0;
1751
- for (i.lastIndex = 0; (r = i.exec(n)) !== null && !(++o > le); ) {
1763
+ for (i.lastIndex = 0; (r = i.exec(n)) !== null && !(++o > he); ) {
1752
1764
  if (r[0] === "") {
1753
1765
  i.lastIndex += 1;
1754
1766
  continue;
@@ -1761,7 +1773,7 @@ function Pn(t, e) {
1761
1773
  }
1762
1774
  return null;
1763
1775
  }
1764
- async function Dn({ apiBase: t, apiKey: e, projectId: n }) {
1776
+ async function Pn({ apiBase: t, apiKey: e, projectId: n }) {
1765
1777
  const i = { policy: "off", fields: [] };
1766
1778
  try {
1767
1779
  const r = await fetch(
@@ -1775,7 +1787,7 @@ async function Dn({ apiBase: t, apiKey: e, projectId: n }) {
1775
1787
  return i;
1776
1788
  }
1777
1789
  }
1778
- const vi = /Did this answer your question\?/i;
1790
+ const $i = /Did this answer your question\?/i;
1779
1791
  async function _n({ apiBase: t, apiKey: e, projectId: n }) {
1780
1792
  try {
1781
1793
  const i = await fetch(
@@ -1789,8 +1801,8 @@ async function _n({ apiBase: t, apiKey: e, projectId: n }) {
1789
1801
  return [];
1790
1802
  }
1791
1803
  }
1792
- const Hn = 5 * 6e4, rt = "bugcatch:announcements:seen", zn = 40, qn = ["info", "success", "warning", "critical"], at = (t) => `bugcatch:announcements:${t}`;
1793
- async function Fn({
1804
+ const Hn = 5 * 6e4, rt = "bugcatch:announcements:seen", zn = 40, Fn = ["info", "success", "warning", "critical"], at = (t) => `bugcatch:announcements:${t}`;
1805
+ async function Xn({
1794
1806
  apiBase: t,
1795
1807
  apiKey: e,
1796
1808
  projectId: n,
@@ -1811,7 +1823,7 @@ async function Fn({
1811
1823
  return [];
1812
1824
  }
1813
1825
  }
1814
- function Xn(t, { on: e = Yn(), seen: n = ct() } = {}) {
1826
+ function qn(t, { on: e = Yn(), seen: n = ct() } = {}) {
1815
1827
  return (t || []).filter((i) => Vn(i, e) && !(i.dismissible && n.includes(st(i))));
1816
1828
  }
1817
1829
  function Wn(t) {
@@ -1843,7 +1855,7 @@ function Zn(t) {
1843
1855
  revision: Number.isInteger(e.revision) ? e.revision : 0,
1844
1856
  title: e.title,
1845
1857
  body: typeof e.body == "string" ? e.body : "",
1846
- tone: qn.includes(e.tone) ? e.tone : "info",
1858
+ tone: Fn.includes(e.tone) ? e.tone : "info",
1847
1859
  // Both halves, or neither, as the API saves them.
1848
1860
  ctaLabel: i && typeof e.ctaLabel == "string" ? e.ctaLabel : "",
1849
1861
  ctaHref: i && typeof e.ctaLabel == "string" ? i : "",
@@ -1878,53 +1890,108 @@ function Qn(t, e) {
1878
1890
  } catch {
1879
1891
  }
1880
1892
  }
1881
- const Z = 120, ei = 500, G = 30, ti = 1e3, we = {
1893
+ const ei = ["idea", "praise", "confusing", "other"], ti = 5, ni = 4e3;
1894
+ async function ii({ apiBase: t, apiKey: e, projectId: n }) {
1895
+ try {
1896
+ const i = await fetch(`${t}/ingest/feedback?projectId=${encodeURIComponent(n)}`, {
1897
+ headers: { "X-BugCatch-Key": e }
1898
+ });
1899
+ if (!i.ok) return !1;
1900
+ const r = await i.json();
1901
+ return (r == null ? void 0 : r.enabled) === !0;
1902
+ } catch {
1903
+ return !1;
1904
+ }
1905
+ }
1906
+ function oi({ message: t, kind: e, score: n, email: i, name: r } = {}) {
1907
+ const o = typeof t == "string" ? t.trim().slice(0, ni) : "";
1908
+ if (!o) throw new Error("[BugCatch] feedback needs a message.");
1909
+ const a = typeof n == "string" && n.trim() !== "" ? Number(n) : n, s = typeof i == "string" ? i.trim() : "", c = typeof r == "string" ? r.trim() : "";
1910
+ return {
1911
+ message: o,
1912
+ ...ei.includes(e) ? { kind: e } : {},
1913
+ ...Number.isInteger(a) && a >= 1 && a <= ti ? { score: a } : {},
1914
+ ...s ? { email: s.slice(0, 254) } : {},
1915
+ ...c ? { name: c.slice(0, 120) } : {}
1916
+ };
1917
+ }
1918
+ async function ri({ apiBase: t, apiKey: e, token: n, payload: i }) {
1919
+ let r;
1920
+ try {
1921
+ r = await fetch(`${t}/ingest/feedback`, {
1922
+ method: "POST",
1923
+ headers: {
1924
+ "Content-Type": "application/json",
1925
+ "X-BugCatch-Key": e,
1926
+ // Present only where they signed in, so the server can put a proved
1927
+ // name and address on it. A stale one is ignored there, not refused.
1928
+ ...n ? { "X-BugCatch-Session": n } : {}
1929
+ },
1930
+ body: JSON.stringify(i)
1931
+ });
1932
+ } catch (o) {
1933
+ const a = new Error(`[BugCatch] could not reach ${t} — check your connection and try again.`);
1934
+ throw a.cause = o, a;
1935
+ }
1936
+ if (!r.ok) {
1937
+ let o = "";
1938
+ try {
1939
+ const s = await r.json();
1940
+ o = Array.isArray(s.message) ? s.message.join(", ") : s.message || "";
1941
+ } catch {
1942
+ }
1943
+ const a = r.status === 429 ? new Error(`[BugCatch] ${K(o)}`) : new Error(`[BugCatch] ${o || `feedback could not be sent (HTTP ${r.status})`}`);
1944
+ throw a.status = r.status, a;
1945
+ }
1946
+ return r.json();
1947
+ }
1948
+ const G = 120, ai = 500, Q = 30, si = 1e3, be = {
1882
1949
  loanId: ["loanId", "loanNumber"],
1883
1950
  applicationId: ["applicationId"],
1884
1951
  customerNumber: ["customerNumber", "customerId"]
1885
- }, ni = /[\u0000-\u001f\u007f]/;
1886
- function ii(t) {
1952
+ }, ci = /[\u0000-\u001f\u007f]/;
1953
+ function li(t) {
1887
1954
  if (typeof t == "number") return Number.isFinite(t) ? String(t) : null;
1888
1955
  if (typeof t != "string") return null;
1889
1956
  const e = t.trim();
1890
- return !e || e.length > Z || ni.test(e) ? null : e;
1957
+ return !e || e.length > G || ci.test(e) ? null : e;
1891
1958
  }
1892
- function O(t) {
1959
+ function R(t) {
1893
1960
  return t === null ? "null" : Array.isArray(t) ? "an array" : typeof t == "object" ? "an object" : `a ${typeof t}`;
1894
1961
  }
1895
- function ue(t, e, n, i, r) {
1962
+ function fe(t, e, n, i, r) {
1896
1963
  for (const o of n) {
1897
1964
  if (!(o in t) || t[o] === void 0 || t[o] === null || t[o] === "") continue;
1898
- const a = ii(t[o]);
1965
+ const a = li(t[o]);
1899
1966
  if (a) return a;
1900
1967
  const s = t[o];
1901
- r(typeof s == "string" && s.trim().length > Z ? `${i}.${o} is longer than ${Z} characters and was dropped — pass the identifier itself, not a sentence or a URL.` : `${i}.${o} should be a string or number, got ${O(s)} — it was dropped.`);
1968
+ r(typeof s == "string" && s.trim().length > G ? `${i}.${o} is longer than ${G} characters and was dropped — pass the identifier itself, not a sentence or a URL.` : `${i}.${o} should be a string or number, got ${R(s)} — it was dropped.`);
1902
1969
  }
1903
1970
  return null;
1904
1971
  }
1905
1972
  function lt(t) {
1906
1973
  if (t === null || typeof t == "boolean") return { ok: !0, value: t };
1907
1974
  if (typeof t == "number") return Number.isFinite(t) ? { ok: !0, value: t } : { ok: !1 };
1908
- if (typeof t == "string") return { ok: !0, value: t.slice(0, ei) };
1975
+ if (typeof t == "string") return { ok: !0, value: t.slice(0, ai) };
1909
1976
  if (typeof t == "object")
1910
1977
  try {
1911
1978
  const e = JSON.stringify(t);
1912
- if (e && e.length <= ti) return { ok: !0, value: JSON.parse(e) };
1979
+ if (e && e.length <= si) return { ok: !0, value: JSON.parse(e) };
1913
1980
  } catch {
1914
1981
  }
1915
1982
  return { ok: !1 };
1916
1983
  }
1917
- const ut = ["email", "name", "phone"], oi = /* @__PURE__ */ new Set(["id", "userId", ...ut, ...Object.values(we).flat()]);
1918
- function Re(t, e = () => {
1984
+ const dt = ["email", "name", "phone"], di = /* @__PURE__ */ new Set(["id", "userId", ...dt, ...Object.values(be).flat()]);
1985
+ function Le(t, e = () => {
1919
1986
  }) {
1920
1987
  if (t == null) return null;
1921
1988
  if (typeof t != "object" || Array.isArray(t))
1922
- return e(`identify() takes an object like { id, email, name } or null, got ${O(t)} — ignored.`), null;
1989
+ return e(`identify() takes an object like { id, email, name } or null, got ${R(t)} — ignored.`), null;
1923
1990
  const n = {};
1924
1991
  try {
1925
- const i = ue(t, "id", ["id", "userId"], "identify()", e);
1992
+ const i = fe(t, "id", ["id", "userId"], "identify()", e);
1926
1993
  i && (n.id = i);
1927
- for (const o of ut) {
1994
+ for (const o of dt) {
1928
1995
  const a = t[o];
1929
1996
  if (a == null || a === "") continue;
1930
1997
  if (o === "phone" && typeof a == "number" && Number.isFinite(a)) {
@@ -1932,26 +1999,26 @@ function Re(t, e = () => {
1932
1999
  continue;
1933
2000
  }
1934
2001
  if (typeof a != "string") {
1935
- e(`identify().${o} should be a string, got ${O(a)} — it was dropped.`);
2002
+ e(`identify().${o} should be a string, got ${R(a)} — it was dropped.`);
1936
2003
  continue;
1937
2004
  }
1938
- const s = a.trim().slice(0, o === "name" ? 200 : Z);
2005
+ const s = a.trim().slice(0, o === "name" ? 200 : G);
1939
2006
  s && (o === "email" && !s.includes("@") && e(`identify().email "${s}" does not look like an email address — reports cannot be threaded or followed up without one.`), n[o] = s);
1940
2007
  }
1941
- for (const [o, a] of Object.entries(we)) {
1942
- const s = ue(t, o, a, "identify()", e);
2008
+ for (const [o, a] of Object.entries(be)) {
2009
+ const s = fe(t, o, a, "identify()", e);
1943
2010
  s && (n[o] = s);
1944
2011
  }
1945
2012
  let r = 0;
1946
2013
  for (const [o, a] of Object.entries(t)) {
1947
- if (oi.has(o) || a === void 0 || typeof a == "function") continue;
1948
- if (r >= G) {
1949
- e(`identify() was given more than ${G} extra fields; the rest were dropped.`);
2014
+ if (di.has(o) || a === void 0 || typeof a == "function") continue;
2015
+ if (r >= Q) {
2016
+ e(`identify() was given more than ${Q} extra fields; the rest were dropped.`);
1950
2017
  break;
1951
2018
  }
1952
2019
  const s = lt(a);
1953
2020
  if (!s.ok) {
1954
- e(`identify().${o} could not be sent (${O(a)} too large or not serialisable) — dropped.`);
2021
+ e(`identify().${o} could not be sent (${R(a)} too large or not serialisable) — dropped.`);
1955
2022
  continue;
1956
2023
  }
1957
2024
  n[o] = s.value, r += 1;
@@ -1960,16 +2027,16 @@ function Re(t, e = () => {
1960
2027
  }
1961
2028
  return !n.id && !n.email && e("identify() was called without an id or email — reports will not be attributed to anyone, and nothing can be looked up by user."), n;
1962
2029
  }
1963
- function Le(t, e, n = () => {
2030
+ function se(t, e, n = () => {
1964
2031
  }) {
1965
2032
  if (e === null) return {};
1966
2033
  const i = { ...t || {} };
1967
2034
  if (e === void 0) return i;
1968
2035
  if (typeof e != "object" || Array.isArray(e))
1969
- return n(`setContext() takes an object like { loanId, screen } or null, got ${O(e)} — ignored.`), i;
2036
+ return n(`setContext() takes an object like { loanId, screen } or null, got ${R(e)} — ignored.`), i;
1970
2037
  try {
1971
2038
  const r = /* @__PURE__ */ new Map();
1972
- for (const [o, a] of Object.entries(we)) for (const s of a) r.set(s, o);
2039
+ for (const [o, a] of Object.entries(be)) for (const s of a) r.set(s, o);
1973
2040
  for (const [o, a] of Object.entries(e)) {
1974
2041
  const s = r.get(o);
1975
2042
  if (a == null) {
@@ -1977,18 +2044,18 @@ function Le(t, e, n = () => {
1977
2044
  continue;
1978
2045
  }
1979
2046
  if (s) {
1980
- const l = ue({ [o]: a }, s, [o], "setContext()", n);
2047
+ const l = fe({ [o]: a }, s, [o], "setContext()", n);
1981
2048
  l ? i[s] = l : delete i[s];
1982
2049
  continue;
1983
2050
  }
1984
2051
  if (typeof a == "function") continue;
1985
- if (!(o in i) && Object.keys(i).length >= G) {
1986
- n(`setContext() holds at most ${G} keys; "${o}" was dropped.`);
2052
+ if (!(o in i) && Object.keys(i).length >= Q) {
2053
+ n(`setContext() holds at most ${Q} keys; "${o}" was dropped.`);
1987
2054
  continue;
1988
2055
  }
1989
2056
  const c = lt(a);
1990
2057
  if (!c.ok) {
1991
- n(`setContext().${o} could not be sent (${O(a)} too large or not serialisable) — dropped.`);
2058
+ n(`setContext().${o} could not be sent (${R(a)} too large or not serialisable) — dropped.`);
1992
2059
  continue;
1993
2060
  }
1994
2061
  i[o] = c.value;
@@ -1997,7 +2064,7 @@ function Le(t, e, n = () => {
1997
2064
  }
1998
2065
  return i;
1999
2066
  }
2000
- const dt = [
2067
+ const ut = [
2001
2068
  "apiBase",
2002
2069
  "apiKey",
2003
2070
  "projectId",
@@ -2034,8 +2101,9 @@ const dt = [
2034
2101
  "environment",
2035
2102
  "buildId",
2036
2103
  "chunkBase",
2037
- "announcements"
2038
- ], ri = [
2104
+ "announcements",
2105
+ "feedback"
2106
+ ], ui = [
2039
2107
  "beforeSend",
2040
2108
  "onUpdate",
2041
2109
  "onCallState",
@@ -2044,35 +2112,35 @@ const dt = [
2044
2112
  "onAssistantPhase",
2045
2113
  "onError"
2046
2114
  ];
2047
- function ai(t) {
2115
+ function hi(t) {
2048
2116
  const e = t.toLowerCase().replace(/[-_]/g, "");
2049
- return dt.find((n) => n.toLowerCase() === e) || null;
2117
+ return ut.find((n) => n.toLowerCase() === e) || null;
2050
2118
  }
2051
- const Ke = /^(your[_-]|<|xxx|todo|changeme)/i, si = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2052
- function ci(t, { pageHost: e = "" } = {}) {
2119
+ const Ke = /^(your[_-]|<|xxx|todo|changeme)/i, fi = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2120
+ function pi(t, { pageHost: e = "" } = {}) {
2053
2121
  const n = [], i = [];
2054
2122
  if (!t || typeof t != "object")
2055
2123
  return n.push("init() takes an options object: BugCatch.init({ apiBase, apiKey, projectId })."), { errors: n, warnings: i };
2056
2124
  const { apiKey: r, projectId: o, apiBase: a } = t;
2057
- r ? typeof r != "string" ? n.push(`apiKey must be a string, got ${O(r)}.`) : Ke.test(r) ? n.push(`apiKey is still the placeholder "${r}" — paste the key you saved when you created it.`) : si.test(r) ? i.push("apiKey looks like a project id — did you swap apiKey and projectId?") : r.startsWith("bc_") || i.push('apiKey does not look like a BugCatch key (they start with "bc_live_") — reports will be refused with HTTP 401.') : n.push("apiKey is required — create one under Workspace Settings → API Keys."), o ? typeof o != "string" ? n.push(`projectId must be a string, got ${O(o)}.`) : Ke.test(o) ? n.push(`projectId is still the placeholder "${o}".`) : o.startsWith("bc_") ? i.push("projectId looks like an API key — did you swap apiKey and projectId?") : /\s/.test(o) && i.push("projectId contains whitespace — check it was copied cleanly.") : n.push("projectId is required — copy it from Project Settings → Web SDK."), a == null ? !e || /^(localhost|127\.|0\.0\.0\.0|\[::1\])/.test(e) || i.push("apiBase is not set, so reports go to http://localhost:3000 — set apiBase to your BugCatch API URL.") : (typeof a != "string" || !/^https?:\/\//.test(a)) && i.push(`apiBase should be an absolute http(s) URL, got ${JSON.stringify(a)}.`);
2125
+ r ? typeof r != "string" ? n.push(`apiKey must be a string, got ${R(r)}.`) : Ke.test(r) ? n.push(`apiKey is still the placeholder "${r}" — paste the key you saved when you created it.`) : fi.test(r) ? i.push("apiKey looks like a project id — did you swap apiKey and projectId?") : r.startsWith("bc_") || i.push('apiKey does not look like a BugCatch key (they start with "bc_live_") — reports will be refused with HTTP 401.') : n.push("apiKey is required — create one under Workspace Settings → API Keys."), o ? typeof o != "string" ? n.push(`projectId must be a string, got ${R(o)}.`) : Ke.test(o) ? n.push(`projectId is still the placeholder "${o}".`) : o.startsWith("bc_") ? i.push("projectId looks like an API key — did you swap apiKey and projectId?") : /\s/.test(o) && i.push("projectId contains whitespace — check it was copied cleanly.") : n.push("projectId is required — copy it from Project Settings → Web SDK."), a == null ? !e || /^(localhost|127\.|0\.0\.0\.0|\[::1\])/.test(e) || i.push("apiBase is not set, so reports go to http://localhost:3000 — set apiBase to your BugCatch API URL.") : (typeof a != "string" || !/^https?:\/\//.test(a)) && i.push(`apiBase should be an absolute http(s) URL, got ${JSON.stringify(a)}.`);
2058
2126
  for (const s of Object.keys(t)) {
2059
- if (dt.includes(s)) continue;
2060
- const c = ai(s);
2127
+ if (ut.includes(s)) continue;
2128
+ const c = hi(s);
2061
2129
  i.push(c ? `unknown option "${s}" — did you mean "${c}"?` : `unknown option "${s}" is ignored.`);
2062
2130
  }
2063
- for (const s of ri) {
2131
+ for (const s of ui) {
2064
2132
  const c = t[s];
2065
- c != null && typeof c != "function" && i.push(`${s} should be a function, got ${O(c)} — it will not be called.`);
2133
+ c != null && typeof c != "function" && i.push(`${s} should be a function, got ${R(c)} — it will not be called.`);
2066
2134
  }
2067
2135
  return { errors: n, warnings: i };
2068
2136
  }
2069
- function li(t) {
2137
+ function gi(t) {
2070
2138
  return typeof t == "string" ? t.replace(/\/+$/, "") : t;
2071
2139
  }
2072
- const D = {
2140
+ const U = {
2073
2141
  name: "@sphoro/bugcatch-web-sdk",
2074
- version: "0.19.0"
2075
- }, U = {
2142
+ version: "0.21.0"
2143
+ }, D = {
2076
2144
  apiBase: "http://localhost:3000",
2077
2145
  apiKey: null,
2078
2146
  projectId: null,
@@ -2094,6 +2162,10 @@ const D = {
2094
2162
  // ones written for that. false draws nothing; announcements() still answers,
2095
2163
  // for a site that shows them its own way.
2096
2164
  announcements: !0,
2165
+ // Offer "Give feedback" beside "Report a bug" in the panel, where the
2166
+ // project has it switched on (Settings → Project → General). false hides it
2167
+ // on this site; feedback() still sends, for a site with a form of its own.
2168
+ feedback: !0,
2097
2169
  // Screenshot / screen recording / file attach. Capture needs getDisplayMedia,
2098
2170
  // so it is offered only where the browser has it — file attach always works.
2099
2171
  attachments: !0,
@@ -2156,15 +2228,15 @@ const D = {
2156
2228
  // printed either way.
2157
2229
  debug: !1
2158
2230
  };
2159
- function ui(t) {
2160
- const e = E();
2231
+ function mi(t) {
2232
+ const e = T();
2161
2233
  return e ? { ...t, watchToken: e } : t;
2162
2234
  }
2163
- var w, F, ft, R, pt, de, X, W, he, gt, mt, wt, J, yt;
2235
+ var p, q, ft, L, pt, pe, _, W, J, gt, mt, wt, Y, yt;
2164
2236
  class ht {
2165
2237
  constructor() {
2166
- xe(this, w);
2167
- this.config = { ...U }, this.started = !1, this.teardown = [], this.consoleBuffer = z(U.consoleLimit), this.networkBuffer = z(U.networkLimit), this.stopWatching = null, this.notifier = null, this.call = null, this.callStarting = !1, this.ringing = null, this.listeners = /* @__PURE__ */ new Map(), this.context = {}, this.warned = /* @__PURE__ */ new Set(), this.phases = /* @__PURE__ */ new Map();
2238
+ ve(this, p);
2239
+ this.config = { ...D }, this.started = !1, this.teardown = [], this.consoleBuffer = F(D.consoleLimit), this.networkBuffer = F(D.networkLimit), this.stopWatching = null, this.notifier = null, this.call = null, this.callStarting = !1, this.ringing = null, this.listeners = /* @__PURE__ */ new Map(), this.context = {}, this.warned = /* @__PURE__ */ new Set(), this.phases = /* @__PURE__ */ new Map();
2168
2240
  }
2169
2241
  /** A misconfiguration, said once. Always printed — it is what saves a day of guessing. */
2170
2242
  warn(e) {
@@ -2177,14 +2249,14 @@ class ht {
2177
2249
  init(e = {}) {
2178
2250
  if (this.started)
2179
2251
  return console.warn("[BugCatch] init() called twice — ignoring the second call."), this;
2180
- const { errors: n, warnings: i } = ci(e, {
2252
+ const { errors: n, warnings: i } = pi(e, {
2181
2253
  pageHost: typeof location < "u" ? location.hostname : ""
2182
2254
  });
2183
2255
  if (n.length) throw new Error(`[BugCatch] ${n[0]}`);
2184
2256
  for (const o of i) this.warn(o);
2185
2257
  const r = this.config.user;
2186
- return this.config = { ...U, ...e, apiBase: li(e.apiBase ?? U.apiBase) }, this.config.user = e.user !== void 0 ? Re(e.user, (o) => this.warn(o.replace("identify()", "init({ user })"))) : r || null, e.context && this.setContext(e.context), this.consoleBuffer = z(this.config.consoleLimit), this.networkBuffer = z(this.config.networkLimit), this.config.captureConsole && this.teardown.push(At(this.consoleBuffer)), this.config.captureNetwork && this.teardown.push(jt(this.networkBuffer)), this.config.captureErrors && this.teardown.push(Ot(this.consoleBuffer)), tn(this.config.projectId), this.config.widget && this.teardown.push(Ft(this)), this.config.updates && E() && (this.startWatching(), queueMicrotask(() => x(this, w, R).call(this))), this.started = !0, x(this, w, ft).call(this), this.debugLog("initialised", {
2187
- version: D.version,
2258
+ return this.config = { ...D, ...e, apiBase: gi(e.apiBase ?? D.apiBase) }, this.config.user = e.user !== void 0 ? Le(e.user, (o) => this.warn(o.replace("identify()", "init({ user })"))) : r || null, e.context && this.setContext(e.context), this.consoleBuffer = F(this.config.consoleLimit), this.networkBuffer = F(this.config.networkLimit), this.config.captureConsole && this.teardown.push(At(this.consoleBuffer)), this.config.captureNetwork && this.teardown.push(jt(this.networkBuffer)), this.config.captureErrors && this.teardown.push(Ot(this.consoleBuffer)), tn(this.config.projectId), this.config.widget && this.teardown.push(Xt(this)), this.config.updates && T() && (this.startWatching(), queueMicrotask(() => x(this, p, L).call(this))), this.started = !0, x(this, p, ft).call(this), this.debugLog("initialised", {
2259
+ version: U.version,
2188
2260
  apiBase: this.config.apiBase,
2189
2261
  projectId: this.config.projectId,
2190
2262
  user: this.config.user,
@@ -2201,22 +2273,22 @@ class ht {
2201
2273
  apiBase: this.config.apiBase,
2202
2274
  onUpdate: (n) => {
2203
2275
  if (n != null && n.incomingCall) {
2204
- x(this, w, wt).call(this, n);
2276
+ x(this, p, wt).call(this, n);
2205
2277
  return;
2206
2278
  }
2207
2279
  if (n != null && n.callWithdrawn) {
2208
- x(this, w, J).call(this, n.callWithdrawn.callId);
2280
+ x(this, p, Y).call(this, n.callWithdrawn.callId);
2209
2281
  return;
2210
2282
  }
2211
2283
  const i = on(n);
2212
- typeof this.config.onUpdate == "function" && this.config.onUpdate(i), this.emit("update", i), x(this, w, R).call(this);
2284
+ typeof this.config.onUpdate == "function" && this.config.onUpdate(i), this.emit("update", i), x(this, p, L).call(this);
2213
2285
  }
2214
2286
  }), this.teardown.push(() => {
2215
2287
  var n;
2216
2288
  return (n = this.stopWatching) == null ? void 0 : n.call(this);
2217
- }), this.teardown.push(() => x(this, w, J).call(this));
2289
+ }), this.teardown.push(() => x(this, p, Y).call(this));
2218
2290
  const e = (n) => {
2219
- (n.key === V || n.key === null) && x(this, w, R).call(this);
2291
+ (n.key === Z || n.key === null) && x(this, p, L).call(this);
2220
2292
  };
2221
2293
  return window.addEventListener("storage", e), this.teardown.push(() => window.removeEventListener("storage", e)), this;
2222
2294
  }
@@ -2260,7 +2332,7 @@ class ht {
2260
2332
  * Each carries the `id` the mark-read calls take.
2261
2333
  */
2262
2334
  unreadUpdates() {
2263
- return H();
2335
+ return z();
2264
2336
  }
2265
2337
  /**
2266
2338
  * Mark one update read. It stops being shown, here and on the next load.
@@ -2273,7 +2345,7 @@ class ht {
2273
2345
  * knows when its reader has seen one, so it has to say.
2274
2346
  */
2275
2347
  markUpdateRead(e) {
2276
- return rn(e), x(this, w, R).call(this), this;
2348
+ return rn(e), x(this, p, L).call(this), this;
2277
2349
  }
2278
2350
  /**
2279
2351
  * Mark everything about one report read.
@@ -2282,18 +2354,18 @@ class ht {
2282
2354
  * the thread opens; an integration with its own report view should too.
2283
2355
  */
2284
2356
  markReportRead(e) {
2285
- return an(e), x(this, w, R).call(this), this;
2357
+ return an(e), x(this, p, L).call(this), this;
2286
2358
  }
2287
2359
  /** Mark everything read. The "clear all" behind your own notification list. */
2288
2360
  markUpdatesRead() {
2289
- return Ze(), x(this, w, R).call(this), this;
2361
+ return Ze(), x(this, p, L).call(this), this;
2290
2362
  }
2291
2363
  /**
2292
2364
  * Tell the team whether their fix worked. STILL_HAPPENING reopens the report
2293
2365
  * and re-sends this browser's context with it.
2294
2366
  */
2295
2367
  async verifyFix(e, { result: n, resolvedAt: i, note: r }) {
2296
- const o = n === "STILL_HAPPENING" ? await x(this, w, W).call(this, {}) : {};
2368
+ const o = n === "STILL_HAPPENING" ? await x(this, p, W).call(this, {}) : {};
2297
2369
  return $n({ apiBase: this.config.apiBase, bugId: e, result: n, resolvedAt: i, note: r, metadata: o.metadata, logs: o.logs });
2298
2370
  }
2299
2371
  /**
@@ -2318,7 +2390,7 @@ class ht {
2318
2390
  */
2319
2391
  async myReport(e) {
2320
2392
  const n = await ln({ apiBase: this.config.apiBase, bugId: e });
2321
- return x(this, w, pt).call(this, e, n == null ? void 0 : n.assistant), n;
2393
+ return x(this, p, pt).call(this, e, n == null ? void 0 : n.assistant), n;
2322
2394
  }
2323
2395
  /**
2324
2396
  * Write back on a report this browser filed.
@@ -2334,7 +2406,7 @@ class ht {
2334
2406
  * the caller renders what the server kept rather than what it hoped it sent.
2335
2407
  */
2336
2408
  replyToReport(e, { body: n, attachments: i } = {}) {
2337
- return un({ apiBase: this.config.apiBase, bugId: e, body: n, attachments: i });
2409
+ return dn({ apiBase: this.config.apiBase, bugId: e, body: n, attachments: i });
2338
2410
  }
2339
2411
  /**
2340
2412
  * Whether this visitor can report something by talking about it instead.
@@ -2387,7 +2459,7 @@ class ht {
2387
2459
  async callKinds() {
2388
2460
  var n;
2389
2461
  const e = { agent: !1, live: !1 };
2390
- return !this.config.voice || !((n = this.config.user) != null && n.email) ? e : this.kinds !== void 0 ? this.kinds : (this.kinds = await dn({
2462
+ return !this.config.voice || !((n = this.config.user) != null && n.email) ? e : this.kinds !== void 0 ? this.kinds : (this.kinds = await un({
2391
2463
  apiBase: this.config.apiBase,
2392
2464
  apiKey: this.config.apiKey,
2393
2465
  projectId: this.config.projectId
@@ -2408,7 +2480,7 @@ class ht {
2408
2480
  * for either of them to be asking about.
2409
2481
  */
2410
2482
  canCall(e) {
2411
- return this.config.voice ? Ae({ apiBase: this.config.apiBase, bugId: e }) : Promise.resolve(!1);
2483
+ return this.config.voice ? je({ apiBase: this.config.apiBase, bugId: e }) : Promise.resolve(!1);
2412
2484
  }
2413
2485
  /**
2414
2486
  * Ring the team.
@@ -2451,7 +2523,7 @@ class ht {
2451
2523
  try {
2452
2524
  if (!await this.callKind())
2453
2525
  throw new Error((n = this.config.user) != null && n.email ? "[BugCatch] calling is not available on this project." : "[BugCatch] a call needs to know who is calling — call identify() with an email first.");
2454
- return await x(this, w, mt).call(this, e);
2526
+ return await x(this, p, mt).call(this, e);
2455
2527
  } finally {
2456
2528
  this.callStarting = !1;
2457
2529
  }
@@ -2474,7 +2546,7 @@ class ht {
2474
2546
  * For a host application drawing its own button. The widget asks this itself.
2475
2547
  */
2476
2548
  canCallTeam(e) {
2477
- return this.config.voice ? Ae({ apiBase: this.config.apiBase, bugId: e }) : Promise.resolve(!1);
2549
+ return this.config.voice ? je({ apiBase: this.config.apiBase, bugId: e }) : Promise.resolve(!1);
2478
2550
  }
2479
2551
  /**
2480
2552
  * End the call in progress, of either kind. Does nothing when there is not
@@ -2501,7 +2573,7 @@ class ht {
2501
2573
  /** True when this browser has filed something, so a "your reports" entry
2502
2574
  * point can be hidden until it would show anything. */
2503
2575
  hasReports() {
2504
- return !!E();
2576
+ return !!T();
2505
2577
  }
2506
2578
  /**
2507
2579
  * Forget this browser's reports — call on sign-out, or the next person at
@@ -2509,7 +2581,7 @@ class ht {
2509
2581
  */
2510
2582
  forgetReports() {
2511
2583
  var e;
2512
- return (e = this.stopWatching) == null || e.call(this), this.stopWatching = null, this.endCall(), K(), x(this, w, R).call(this), this;
2584
+ return (e = this.stopWatching) == null || e.call(this), this.stopWatching = null, this.endCall(), N(), x(this, p, L).call(this), this;
2513
2585
  }
2514
2586
  /**
2515
2587
  * Attach the signed-in user so reports say who hit the bug.
@@ -2526,7 +2598,7 @@ class ht {
2526
2598
  * Pass null to forget them again on sign-out.
2527
2599
  */
2528
2600
  identify(e) {
2529
- const n = Re(e, (i) => this.warn(i));
2601
+ const n = Le(e, (i) => this.warn(i));
2530
2602
  return e != null && !n ? this : (this.config.user = n, this.debugLog("identify", n), this);
2531
2603
  }
2532
2604
  /**
@@ -2543,7 +2615,7 @@ class ht {
2543
2615
  * outrank the same field on identify(); anything else is readable metadata.
2544
2616
  */
2545
2617
  setContext(e) {
2546
- return this.context = Le(this.context, e, (n) => this.warn(n)), this.debugLog("context", this.context), this;
2618
+ return this.context = se(this.context, e, (n) => this.warn(n)), this.debugLog("context", this.context), this;
2547
2619
  }
2548
2620
  /** What setContext() currently holds (a copy). */
2549
2621
  getContext() {
@@ -2553,11 +2625,16 @@ class ht {
2553
2625
  * Open the report panel, as if the floating button had been pressed — for a
2554
2626
  * "Report a problem" item in your own menu.
2555
2627
  *
2556
- * Needs the built-in widget (`widget: true`, the default). With `widget:
2557
- * false` there is no panel to open: draw your own form and call report().
2628
+ * BugCatch.open(); // the report form
2629
+ * BugCatch.open({ mode: 'feedback' }); // straight to "Give feedback"
2630
+ *
2631
+ * Feedback opens only where this project takes it; otherwise the report form
2632
+ * does. An open panel moves to the mode asked for. Needs the built-in widget
2633
+ * (`widget: true`, the default). With `widget: false` there is no panel to
2634
+ * open: draw your own form and call report() or feedback().
2558
2635
  */
2559
- open() {
2560
- return this.started ? this.widgetControls ? (this.widgetControls.open(), this) : (this.warn("open() needs the built-in widget; it was turned off with widget: false."), this) : (this.warn("open() was called before init() — nothing to open yet."), this);
2636
+ open({ mode: e } = {}) {
2637
+ return this.started ? this.widgetControls ? (e !== void 0 && e !== "report" && e !== "feedback" && (this.warn(`open({ mode: "${e}" }) is not 'report' or 'feedback' — opened the report form.`), e = "report"), this.widgetControls.open(e), this) : (this.warn("open() needs the built-in widget; it was turned off with widget: false."), this) : (this.warn("open() was called before init() — nothing to open yet."), this);
2561
2638
  }
2562
2639
  /** Close the report panel if it is open. */
2563
2640
  close() {
@@ -2598,17 +2675,17 @@ class ht {
2598
2675
  context: s = null,
2599
2676
  issue: c = null
2600
2677
  } = {}) {
2601
- var I, v, T, p, k, g, b, B;
2678
+ var S, E, $, g, k, v, w, C;
2602
2679
  if (!this.started) throw new Error("[BugCatch] call init() first.");
2603
2680
  if (typeof e != "string" || !e.trim()) throw new Error("[BugCatch] a title is required.");
2604
2681
  ["LOW", "MEDIUM", "HIGH", "CRITICAL"].includes(String(i).toUpperCase()) || (this.warn(`priority "${i}" is not one of LOW, MEDIUM, HIGH, CRITICAL — sent as MEDIUM.`), i = "MEDIUM");
2605
- const l = (o || []).filter((y) => (y == null ? void 0 : y.storageKey) && ae(y.mime, $e)).map((y) => ({
2606
- type: y.type === "VIDEO" ? "VIDEO" : "SCREENSHOT",
2607
- storageKey: y.storageKey,
2608
- mime: ae(y.mime, $e)
2609
- })), h = (Array.isArray(a) ? a : []).filter((y) => y && typeof y.key == "string" && y.key && (typeof y.value == "string" || typeof y.value == "number")).map((y) => ({ key: y.key.slice(0, 64), value: String(y.value).trim().slice(0, 120) })).filter((y) => y.value);
2682
+ const l = (o || []).filter((m) => (m == null ? void 0 : m.storageKey) && le(m.mime, Te)).map((m) => ({
2683
+ type: m.type === "VIDEO" ? "VIDEO" : "SCREENSHOT",
2684
+ storageKey: m.storageKey,
2685
+ mime: le(m.mime, Te)
2686
+ })), h = (Array.isArray(a) ? a : []).filter((m) => m && typeof m.key == "string" && m.key && (typeof m.value == "string" || typeof m.value == "number")).map((m) => ({ key: m.key.slice(0, 64), value: String(m.value).trim().slice(0, 120) })).filter((m) => m.value);
2610
2687
  Array.isArray(a) && h.length < a.length && this.warn("report({ references }) takes [{ key, value }] with string values; malformed entries were dropped.");
2611
- let f = await x(this, w, W).call(this, {
2688
+ let f = await x(this, p, W).call(this, {
2612
2689
  title: e.trim(),
2613
2690
  description: typeof n == "string" ? n : String(n ?? ""),
2614
2691
  priority: String(i).toUpperCase(),
@@ -2618,20 +2695,20 @@ class ht {
2618
2695
  context: s,
2619
2696
  issue: typeof c == "string" && c ? c.slice(0, 32) : null
2620
2697
  });
2621
- const d = x(this, w, he).call(this, f);
2622
- if (d === !1) return { cancelled: !0 };
2623
- f = d, this.debugLog("sending report", {
2698
+ const u = x(this, p, J).call(this, f, { type: "report" });
2699
+ if (u === !1) return { cancelled: !0 };
2700
+ f = u, this.debugLog("sending report", {
2624
2701
  title: f.title,
2625
- user: (I = f.metadata) == null ? void 0 : I.user,
2626
- context: (v = f.metadata) == null ? void 0 : v.context,
2702
+ user: (S = f.metadata) == null ? void 0 : S.user,
2703
+ context: (E = f.metadata) == null ? void 0 : E.context,
2627
2704
  references: f.references,
2628
- console: (k = (p = (T = f.logs) == null ? void 0 : T.console) == null ? void 0 : p.entries) == null ? void 0 : k.length,
2629
- network: (B = (b = (g = f.logs) == null ? void 0 : g.network) == null ? void 0 : b.entries) == null ? void 0 : B.length
2705
+ console: (k = (g = ($ = f.logs) == null ? void 0 : $.console) == null ? void 0 : g.entries) == null ? void 0 : k.length,
2706
+ network: (C = (w = (v = f.logs) == null ? void 0 : v.network) == null ? void 0 : w.entries) == null ? void 0 : C.length
2630
2707
  });
2631
- const u = M(this.config.projectId);
2632
- let m;
2708
+ const d = M(this.config.projectId);
2709
+ let b;
2633
2710
  try {
2634
- m = await fetch(`${this.config.apiBase}/ingest/bugs`, {
2711
+ b = await fetch(`${this.config.apiBase}/ingest/bugs`, {
2635
2712
  method: "POST",
2636
2713
  headers: {
2637
2714
  "Content-Type": "application/json",
@@ -2640,27 +2717,27 @@ class ht {
2640
2717
  // address from here rather than from the payload when it is — on a
2641
2718
  // project that requires sign-in, letting the page name a different
2642
2719
  // reporter would undo the requirement.
2643
- ...u != null && u.token ? { "X-BugCatch-Session": u.token } : {}
2720
+ ...d != null && d.token ? { "X-BugCatch-Session": d.token } : {}
2644
2721
  },
2645
- body: JSON.stringify(ui(f))
2722
+ body: JSON.stringify(mi(f))
2646
2723
  });
2647
- } catch (y) {
2648
- const C = new Error(`[BugCatch] could not reach ${this.config.apiBase} — check apiBase, and that this site's origin is allowed by the API.`);
2649
- throw C.cause = y, x(this, w, X).call(this, "report", C), C;
2724
+ } catch (m) {
2725
+ const B = new Error(`[BugCatch] could not reach ${this.config.apiBase} — check apiBase, and that this site's origin is allowed by the API.`);
2726
+ throw B.cause = m, x(this, p, _).call(this, "report", B), B;
2650
2727
  }
2651
- if (m.status === 401 && u && ce(this.config.projectId), !m.ok) {
2652
- let y = "";
2728
+ if (b.status === 401 && d && ue(this.config.projectId), !b.ok) {
2729
+ let m = "";
2653
2730
  try {
2654
- const A = await m.json();
2655
- y = Array.isArray(A.message) ? A.message.join(", ") : A.message || "";
2731
+ const A = await b.json();
2732
+ m = Array.isArray(A.message) ? A.message.join(", ") : A.message || "";
2656
2733
  } catch {
2657
2734
  }
2658
- m.status === 401 && !u && (y || (y = "the apiKey was not accepted")), m.status === 403 && (y || (y = "the apiKey is not allowed to report to this projectId"));
2659
- const C = m.status === 429 ? new Error(`[BugCatch] ${N(y)}`) : new Error(`[BugCatch] report failed (HTTP ${m.status})${y ? ": " + y : ""}`);
2660
- throw C.status = m.status, x(this, w, X).call(this, "report", C), C;
2735
+ b.status === 401 && !d && (m || (m = "the apiKey was not accepted")), b.status === 403 && (m || (m = "the apiKey is not allowed to report to this projectId"));
2736
+ const B = b.status === 429 ? new Error(`[BugCatch] ${K(m)}`) : new Error(`[BugCatch] report failed (HTTP ${b.status})${m ? ": " + m : ""}`);
2737
+ throw B.status = b.status, x(this, p, _).call(this, "report", B), B;
2661
2738
  }
2662
- const $ = await m.json();
2663
- return x(this, w, de).call(this, $, { title: f.title ?? e.trim(), via: "form" }), $.watchToken && (se($.watchToken), this.config.updates && this.startWatching()), $;
2739
+ const y = await b.json();
2740
+ return x(this, p, pe).call(this, y, { title: f.title ?? e.trim(), via: "form" }), y.watchToken && (de(y.watchToken), this.config.updates && this.startWatching()), y;
2664
2741
  }
2665
2742
  /**
2666
2743
  * What this project asks of the person reporting, and who this browser is
@@ -2702,7 +2779,7 @@ class ht {
2702
2779
  * whether that form should have an identifier box on it.
2703
2780
  */
2704
2781
  referenceFields() {
2705
- return this.refFields ? this.refFields : (this.refFields = Dn({
2782
+ return this.refFields ? this.refFields : (this.refFields = Pn({
2706
2783
  apiBase: this.config.apiBase,
2707
2784
  apiKey: this.config.apiKey,
2708
2785
  projectId: this.config.projectId
@@ -2745,12 +2822,12 @@ class ht {
2745
2822
  * `widget: false` or `announcements: false`. Empty on every failure.
2746
2823
  */
2747
2824
  async announcements() {
2748
- const e = await Fn({
2825
+ const e = await Xn({
2749
2826
  apiBase: this.config.apiBase,
2750
2827
  apiKey: this.config.apiKey,
2751
2828
  projectId: this.config.projectId
2752
2829
  });
2753
- return Xn(e);
2830
+ return qn(e);
2754
2831
  }
2755
2832
  /**
2756
2833
  * Stop showing an announcement in this browser, until the team uses "Show it
@@ -2760,6 +2837,82 @@ class ht {
2760
2837
  dismissAnnouncement(e) {
2761
2838
  Wn(e);
2762
2839
  }
2840
+ /**
2841
+ * Whether this project takes feedback from the widget — the answer that
2842
+ * decides whether "Give feedback" is drawn.
2843
+ *
2844
+ * if (await BugCatch.feedbackEnabled()) showMyFeedbackButton();
2845
+ *
2846
+ * Switched on and off on the project's settings page, not here. Asked once
2847
+ * per page and kept; false on any failure.
2848
+ */
2849
+ feedbackEnabled() {
2850
+ return this.feedbackState ? this.feedbackState : (this.feedbackState = ii({
2851
+ apiBase: this.config.apiBase,
2852
+ apiKey: this.config.apiKey,
2853
+ projectId: this.config.projectId
2854
+ }), this.feedbackState);
2855
+ }
2856
+ /**
2857
+ * Send feedback — an idea, praise, something that confused them — to this
2858
+ * project's team. Not a bug: it is not triaged, assigned or answered in the
2859
+ * widget; it lands on the dashboard's Feedback page.
2860
+ *
2861
+ * await BugCatch.feedback({
2862
+ * message: 'Export to CSV would save me an hour a week',
2863
+ * kind: 'idea', // 'idea' | 'praise' | 'confusing' | 'other' (optional)
2864
+ * score: 4, // 1 (terrible) – 5 (great), how it feels so far (optional)
2865
+ * email: 'jo@acme.com', // only if they want a reply; identify()'s is used otherwise
2866
+ * });
2867
+ * // → { id }
2868
+ *
2869
+ * Sent with the page and browser details, who identify() says they are and
2870
+ * the setContext() context — never the console or network logs, which say
2871
+ * nothing about an opinion. Goes through beforeSend, whose second argument is
2872
+ * `{ type: 'feedback' }`. Rejects with a message fit to show the person.
2873
+ */
2874
+ async feedback({ message: e, kind: n, score: i, email: r, name: o, context: a = null } = {}) {
2875
+ var f, u, d, b;
2876
+ if (!this.started) throw new Error("[BugCatch] call init() first.");
2877
+ const s = oi({
2878
+ message: e,
2879
+ kind: n,
2880
+ score: i,
2881
+ // What they typed wins: it is the address they asked to be answered at.
2882
+ email: r ?? ((f = this.config.user) == null ? void 0 : f.email),
2883
+ name: o ?? ((u = this.config.user) == null ? void 0 : u.name)
2884
+ });
2885
+ n != null && !s.kind && this.warn(`feedback({ kind: "${n}" }) is not one of idea, praise, confusing, other — sent without one.`);
2886
+ const c = a ? se(this.context, a, (y) => this.warn(y.replace("setContext()", "feedback({ context })"))) : this.context;
2887
+ let l = {
2888
+ projectId: this.config.projectId,
2889
+ ...s,
2890
+ url: window.location.href,
2891
+ metadata: {
2892
+ ...await ae(),
2893
+ release: this.config.release,
2894
+ environment: this.config.environment,
2895
+ buildId: this.config.buildId,
2896
+ user: this.config.user || void 0,
2897
+ ...Object.keys(c).length ? { context: c } : {},
2898
+ sdk: U
2899
+ }
2900
+ };
2901
+ const h = x(this, p, J).call(this, l, { type: "feedback" });
2902
+ if (h === !1) return { cancelled: !0 };
2903
+ l = h, this.debugLog("sending feedback", { kind: l.kind, score: l.score, user: (d = l.metadata) == null ? void 0 : d.user });
2904
+ try {
2905
+ const y = await ri({
2906
+ apiBase: this.config.apiBase,
2907
+ apiKey: this.config.apiKey,
2908
+ token: (b = M(this.config.projectId)) == null ? void 0 : b.token,
2909
+ payload: l
2910
+ }), S = { id: (y == null ? void 0 : y.id) ?? null, kind: l.kind ?? null, score: l.score ?? null };
2911
+ return this.debugLog("feedback accepted", S), this.emit("feedback", S), y;
2912
+ } catch (y) {
2913
+ throw x(this, p, _).call(this, "feedback", y), y;
2914
+ }
2915
+ }
2763
2916
  /**
2764
2917
  * Who this browser is signed in as on this project, from storage alone.
2765
2918
  *
@@ -2840,7 +2993,7 @@ class ht {
2840
2993
  */
2841
2994
  knownIssues() {
2842
2995
  var e;
2843
- return In({
2996
+ return Cn({
2844
2997
  apiBase: this.config.apiBase,
2845
2998
  apiKey: this.config.apiKey,
2846
2999
  projectId: this.config.projectId,
@@ -2855,7 +3008,7 @@ class ht {
2855
3008
  */
2856
3009
  matchKnownIssues(e, { signal: n } = {}) {
2857
3010
  var i;
2858
- return Cn({
3011
+ return In({
2859
3012
  apiBase: this.config.apiBase,
2860
3013
  apiKey: this.config.apiKey,
2861
3014
  projectId: this.config.projectId,
@@ -2879,7 +3032,7 @@ class ht {
2879
3032
  */
2880
3033
  async meToo(e, { email: n, name: i } = {}) {
2881
3034
  var a, s;
2882
- const r = M(this.config.projectId), o = await ve();
3035
+ const r = M(this.config.projectId), o = await ae();
2883
3036
  return Sn({
2884
3037
  apiBase: this.config.apiBase,
2885
3038
  apiKey: this.config.apiKey,
@@ -2891,7 +3044,7 @@ class ht {
2891
3044
  ...o,
2892
3045
  user: this.config.user || void 0,
2893
3046
  ...Object.keys(this.context).length ? { context: this.context } : {},
2894
- sdk: D
3047
+ sdk: U
2895
3048
  },
2896
3049
  logs: {
2897
3050
  console: { entries: this.consoleBuffer.all() },
@@ -2923,8 +3076,8 @@ class ht {
2923
3076
  }), this.teardown = [], this.notifier = null, this.started = !1;
2924
3077
  }
2925
3078
  }
2926
- w = new WeakSet(), /** Call a host callback without letting it break the SDK. */
2927
- F = function(e, n) {
3079
+ p = new WeakSet(), /** Call a host callback without letting it break the SDK. */
3080
+ q = function(e, n) {
2928
3081
  const i = this.config[e];
2929
3082
  if (typeof i == "function")
2930
3083
  try {
@@ -2960,7 +3113,7 @@ ft = function() {
2960
3113
  headers: { "Content-Type": "application/json", "X-BugCatch-Key": this.config.apiKey },
2961
3114
  body: JSON.stringify({
2962
3115
  projectId: this.config.projectId,
2963
- version: D.version,
3116
+ version: U.version,
2964
3117
  identify: !!this.config.user,
2965
3118
  context: !!(this.context && Object.keys(this.context).length),
2966
3119
  widget: !!this.config.widget,
@@ -2978,8 +3131,8 @@ ft = function() {
2978
3131
  * here, so the cards on screen and a host app's own badge cannot disagree
2979
3132
  * about what is outstanding.
2980
3133
  */
2981
- R = function() {
2982
- const e = H();
3134
+ L = function() {
3135
+ const e = z();
2983
3136
  if (this.emit("unread", { count: e.length, updates: e }), !!this.config.updateToast) {
2984
3137
  if (!this.notifier) {
2985
3138
  if (!e.length) return;
@@ -3015,18 +3168,18 @@ pt = function(e, n) {
3015
3168
  if (!e || typeof i != "string" || this.phases.get(e) === i) return;
3016
3169
  this.phases.set(e, i);
3017
3170
  const r = { bugId: e, phase: i, title: n.title ?? null, detail: n.detail ?? null };
3018
- this.debugLog("assistant", r), x(this, w, F).call(this, "onAssistantPhase", r), this.emit("assistant", r);
3171
+ this.debugLog("assistant", r), x(this, p, q).call(this, "onAssistantPhase", r), this.emit("assistant", r);
3019
3172
  }, /** A report was accepted: tell the host app, however it was filed. */
3020
- de = function(e, { title: n, via: i }) {
3173
+ pe = function(e, { title: n, via: i }) {
3021
3174
  if (!(e != null && e.id)) return;
3022
3175
  const r = { bugId: e.id, title: n ?? null, via: i, result: e };
3023
- this.debugLog("report accepted", r), x(this, w, F).call(this, "onReportSubmitted", r), this.emit("report", r);
3176
+ this.debugLog("report accepted", r), x(this, p, q).call(this, "onReportSubmitted", r), this.emit("report", r);
3024
3177
  }, /** Something done on the page's behalf failed. */
3025
- X = function(e, n) {
3026
- x(this, w, F).call(this, "onError", { action: e, error: n }), this.emit("error", { action: e, error: n });
3178
+ _ = function(e, n) {
3179
+ x(this, p, q).call(this, "onError", { action: e, error: n }), this.emit("error", { action: e, error: n });
3027
3180
  }, W = async function({ title: e, description: n = "", priority: i = "MEDIUM", metadata: r = {}, media: o = [], references: a = [], context: s = null, issue: c = null }) {
3028
3181
  var h, f;
3029
- const l = s ? Le(this.context, s, (d) => this.warn(d.replace("setContext()", "report({ context })"))) : this.context;
3182
+ const l = s ? se(this.context, s, (u) => this.warn(u.replace("setContext()", "report({ context })"))) : this.context;
3030
3183
  return {
3031
3184
  projectId: this.config.projectId,
3032
3185
  ...e ? { title: e } : {},
@@ -3038,7 +3191,7 @@ X = function(e, n) {
3038
3191
  // than a mailbox, and so the resolution email can open with their name.
3039
3192
  reporterName: (f = this.config.user) == null ? void 0 : f.name,
3040
3193
  metadata: {
3041
- ...await ve(),
3194
+ ...await ae(),
3042
3195
  release: this.config.release,
3043
3196
  environment: this.config.environment,
3044
3197
  buildId: this.config.buildId,
@@ -3050,7 +3203,7 @@ X = function(e, n) {
3050
3203
  // The screen the report came from — setContext(). Its identifiers
3051
3204
  // outrank the same kind on `user`.
3052
3205
  ...Object.keys(l).length ? { context: l } : {},
3053
- sdk: D
3206
+ sdk: U
3054
3207
  },
3055
3208
  logs: {
3056
3209
  console: { entries: this.consoleBuffer.all() },
@@ -3089,17 +3242,17 @@ X = function(e, n) {
3089
3242
  *
3090
3243
  * Returns the payload to send, or false when the host cancelled.
3091
3244
  */
3092
- he = function(e) {
3245
+ J = function(e, n = { type: "report" }) {
3093
3246
  if (typeof this.config.beforeSend != "function") return e;
3094
- let n;
3247
+ let i;
3095
3248
  try {
3096
- n = this.config.beforeSend(e);
3097
- } catch (i) {
3098
- return this.warn(`beforeSend threw, so nothing was sent: ${(i == null ? void 0 : i.message) || i}`), !1;
3249
+ i = this.config.beforeSend(e, n);
3250
+ } catch (r) {
3251
+ return this.warn(`beforeSend threw, so nothing was sent: ${(r == null ? void 0 : r.message) || r}`), !1;
3099
3252
  }
3100
- return n === !1 ? !1 : n && typeof n == "object" ? n : e;
3253
+ return i === !1 ? !1 : i && typeof i == "object" ? i : e;
3101
3254
  }, gt = async function() {
3102
- const e = M(this.config.projectId), n = x(this, w, he).call(this, await x(this, w, W).call(this, {}));
3255
+ const e = M(this.config.projectId), n = x(this, p, J).call(this, await x(this, p, W).call(this, {}));
3103
3256
  if (n === !1)
3104
3257
  return this.debugLog("call cancelled by beforeSend"), { cancelled: !0 };
3105
3258
  let i;
@@ -3111,14 +3264,14 @@ he = function(e) {
3111
3264
  payload: n,
3112
3265
  // See report(): the token this browser holds, so the one that comes
3113
3266
  // back still covers what it covered.
3114
- watchToken: E()
3267
+ watchToken: T()
3115
3268
  });
3116
3269
  } catch (r) {
3117
- throw r.status === 401 && e && ce(this.config.projectId), x(this, w, X).call(this, "call", r), r;
3270
+ throw r.status === 401 && e && ue(this.config.projectId), x(this, p, _).call(this, "call", r), r;
3118
3271
  }
3119
- return x(this, w, de).call(this, i, { title: null, via: "call" }), i.watchToken && (se(i.watchToken), this.config.updates && this.startWatching()), i;
3272
+ return x(this, p, pe).call(this, i, { title: null, via: "call" }), i.watchToken && (de(i.watchToken), this.config.updates && this.startWatching()), i;
3120
3273
  }, mt = async function(e) {
3121
- const { joinLiveCall: n, liveCallSupported: i, openMicrophone: r } = await q(this.config.chunkBase);
3274
+ const { joinLiveCall: n, liveCallSupported: i, openMicrophone: r } = await X(this.config.chunkBase);
3122
3275
  if (!i())
3123
3276
  throw new Error("[BugCatch] this browser cannot make live calls.");
3124
3277
  const o = await r();
@@ -3126,7 +3279,7 @@ he = function(e) {
3126
3279
  try {
3127
3280
  if (e)
3128
3281
  a = await fn({ apiBase: this.config.apiBase, bugId: e });
3129
- else if (s = await x(this, w, gt).call(this), e = s.id, a = s.live_call, !(a != null && a.realtime_url)) {
3282
+ else if (s = await x(this, p, gt).call(this), e = s.id, a = s.live_call, !(a != null && a.realtime_url)) {
3130
3283
  const l = new Error(`[BugCatch] the report was filed, but the team could not be rung${s.call_error ? `: ${s.call_error}` : "."}`);
3131
3284
  throw l.filed = s, l.reason = s.call_error || null, l;
3132
3285
  }
@@ -3168,10 +3321,10 @@ wt = function(e) {
3168
3321
  var r;
3169
3322
  const n = e.incomingCall;
3170
3323
  if (!this.config.voice || ((r = this.ringing) == null ? void 0 : r.callId) === n.callId || this.call || this.callStarting) return;
3171
- x(this, w, J).call(this);
3324
+ x(this, p, Y).call(this);
3172
3325
  const i = { callId: n.callId, dismiss: () => {
3173
3326
  } };
3174
- this.ringing = i, q(this.config.chunkBase).then(({ liveCallSupported: o, showIncomingCall: a }) => {
3327
+ this.ringing = i, X(this.config.chunkBase).then(({ liveCallSupported: o, showIncomingCall: a }) => {
3175
3328
  if (this.ringing !== i || (this.ringing = null, !o()) || this.call || this.callStarting) return;
3176
3329
  const s = a({
3177
3330
  call: n,
@@ -3181,10 +3334,10 @@ wt = function(e) {
3181
3334
  // out loud — tracked since load, which the card's own code cannot be.
3182
3335
  touched: Ln,
3183
3336
  onAnswer: () => {
3184
- x(this, w, yt).call(this, e.bugId, n);
3337
+ x(this, p, yt).call(this, e.bugId, n);
3185
3338
  },
3186
3339
  onDecline: () => {
3187
- this.ringing = null, je({
3340
+ this.ringing = null, Oe({
3188
3341
  apiBase: this.config.apiBase,
3189
3342
  bugId: e.bugId,
3190
3343
  callId: n.callId
@@ -3208,7 +3361,7 @@ wt = function(e) {
3208
3361
  this.ringing === i && (this.ringing = null);
3209
3362
  });
3210
3363
  }, /** Take the card away, whatever it is showing. */
3211
- J = function(e) {
3364
+ Y = function(e) {
3212
3365
  if (this.ringing && !(e && this.ringing.callId !== e)) {
3213
3366
  try {
3214
3367
  this.ringing.dismiss();
@@ -3221,10 +3374,10 @@ J = function(e) {
3221
3374
  this.callStarting = !0;
3222
3375
  let i, r;
3223
3376
  try {
3224
- const a = await q(this.config.chunkBase);
3377
+ const a = await X(this.config.chunkBase);
3225
3378
  r = a.joinLiveCall, i = await a.openMicrophone();
3226
3379
  } catch (a) {
3227
- this.callStarting = !1, je({ apiBase: this.config.apiBase, bugId: e, callId: n.callId }), this.emit("incoming-call", { bugId: e, callId: n.callId, state: "failed", error: a });
3380
+ this.callStarting = !1, Oe({ apiBase: this.config.apiBase, bugId: e, callId: n.callId }), this.emit("incoming-call", { bugId: e, callId: n.callId, state: "failed", error: a });
3228
3381
  return;
3229
3382
  }
3230
3383
  let o;
@@ -3260,33 +3413,35 @@ J = function(e) {
3260
3413
  };
3261
3414
  const bt = new ht();
3262
3415
  bt.Client = ht;
3263
- bt.version = D.version;
3416
+ bt.version = U.version;
3264
3417
  export {
3265
3418
  bt as B,
3419
+ ei as F,
3266
3420
  Je as I,
3267
- re as P,
3268
- $e as R,
3269
- vi as S,
3421
+ ni as M,
3422
+ ce as P,
3423
+ Te as R,
3424
+ $i as S,
3270
3425
  Zt as U,
3271
3426
  Kt as a,
3272
- gi as b,
3273
- qe as c,
3274
- pi as d,
3275
- mi as e,
3276
- wi as f,
3277
- xi as g,
3278
- bi as h,
3427
+ ki as b,
3428
+ Fe as c,
3429
+ xi as d,
3430
+ vi as e,
3431
+ Ci as f,
3432
+ Bi as g,
3433
+ Si as h,
3279
3434
  ze as i,
3280
3435
  Nt as j,
3281
- Dt as k,
3282
- fi as l,
3436
+ Pt as k,
3437
+ bi as l,
3283
3438
  Lt as m,
3284
- ae as n,
3285
- yi as o,
3286
- hi as p,
3439
+ le as n,
3440
+ Ii as o,
3441
+ yi as p,
3287
3442
  Ye as q,
3288
- ki as r,
3443
+ Ei as r,
3289
3444
  Rt as s,
3290
- Pn as v
3445
+ Dn as v
3291
3446
  };
3292
3447
  //# sourceMappingURL=bugcatch-core.es.js.map