@fixback/sdk 0.1.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,891 @@
1
+ function me(e) {
2
+ return `${e.replace(/\/+$/, "")}/api/ingest/boot`;
3
+ }
4
+ function ge(e) {
5
+ if (typeof e != "object" || e === null) return !1;
6
+ const t = e;
7
+ return typeof t.originAllowed == "boolean" && typeof t.canSubmit == "boolean" && typeof t.gate == "string" && (t.tier === null || typeof t.tier == "string");
8
+ }
9
+ async function xe(e, t, o = fetch) {
10
+ let n;
11
+ try {
12
+ n = await o(me(e), {
13
+ method: "POST",
14
+ headers: { "content-type": "application/json" },
15
+ body: JSON.stringify(t)
16
+ });
17
+ } catch {
18
+ return null;
19
+ }
20
+ if (!n.ok) return null;
21
+ let i;
22
+ try {
23
+ i = await n.json();
24
+ } catch {
25
+ return null;
26
+ }
27
+ return ge(i) ? i : null;
28
+ }
29
+ var J = "fixback.anonymousId";
30
+ function Z() {
31
+ const e = globalThis.crypto;
32
+ return e && typeof e.randomUUID == "function" ? e.randomUUID() : `fb-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
33
+ }
34
+ function ye() {
35
+ try {
36
+ const e = globalThis.localStorage, t = e.getItem(J);
37
+ if (t) return t;
38
+ const o = Z();
39
+ return e.setItem(J, o), o;
40
+ } catch {
41
+ return Z();
42
+ }
43
+ }
44
+ var ke = `
45
+ :host {
46
+ /* Vendored Signal tokens (packages/ui/src/tokens.css). */
47
+ --fb-color-accent: #2f6fed;
48
+ --fb-color-accent-hover: #245fd0;
49
+ --fb-color-on-emphasis: #ffffff;
50
+ --fb-color-text: #0f1720;
51
+ --fb-font-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto,
52
+ Helvetica, Arial, sans-serif;
53
+
54
+ display: block;
55
+ color: var(--fb-color-text);
56
+ font-family: var(--fb-font-sans);
57
+ font-size: 13px;
58
+ line-height: 1.4;
59
+ -webkit-font-smoothing: antialiased;
60
+ }
61
+
62
+ .fb-launcher {
63
+ display: inline-flex;
64
+ align-items: center;
65
+ gap: 8px;
66
+ box-sizing: border-box;
67
+ height: 40px;
68
+ margin: 0;
69
+ padding: 0 16px;
70
+ border: 0;
71
+ border-radius: 999px;
72
+ background: var(--fb-color-accent);
73
+ color: var(--fb-color-on-emphasis);
74
+ font-family: inherit;
75
+ font-size: 13px;
76
+ font-weight: 600;
77
+ letter-spacing: 0.01em;
78
+ cursor: pointer;
79
+ box-shadow:
80
+ 0 6px 18px rgba(15, 23, 32, 0.16),
81
+ 0 1px 2px rgba(15, 23, 32, 0.12);
82
+ transition:
83
+ background-color 120ms ease,
84
+ transform 120ms ease;
85
+ }
86
+
87
+ .fb-launcher:hover {
88
+ background: var(--fb-color-accent-hover);
89
+ }
90
+
91
+ .fb-launcher:active {
92
+ transform: translateY(1px);
93
+ }
94
+
95
+ .fb-launcher:focus-visible {
96
+ outline: 2px solid var(--fb-color-accent);
97
+ outline-offset: 2px;
98
+ }
99
+
100
+ .fb-launcher__icon {
101
+ display: block;
102
+ flex: none;
103
+ width: 16px;
104
+ height: 16px;
105
+ }
106
+
107
+ .fb-launcher__label {
108
+ white-space: nowrap;
109
+ }
110
+
111
+ @media (prefers-reduced-motion: reduce) {
112
+ .fb-launcher {
113
+ transition: none;
114
+ }
115
+ }
116
+ `, Q = "data-fixback-root", U = "fixback:launch", we = '<svg class="fb-launcher__icon" viewBox="0 0 16 16" aria-hidden="true" focusable="false"><path fill="currentColor" d="M3.25 2h9.5A1.25 1.25 0 0 1 14 3.25v6.5A1.25 1.25 0 0 1 12.75 11H7.6l-3.19 2.55A.6.6 0 0 1 3.4 13.1V11h-.15A1.25 1.25 0 0 1 2 9.75v-6.5A1.25 1.25 0 0 1 3.25 2Z"/></svg>';
117
+ function Ee(e) {
118
+ const t = e.ownerDocument, o = t.querySelector(`[${Q}]`);
119
+ o && o.remove();
120
+ const n = t.createElement("div");
121
+ n.setAttribute(Q, ""), n.style.cssText = "position:fixed;right:20px;bottom:20px;z-index:2147483000;margin:0;padding:0;border:0;";
122
+ const i = n.attachShadow({ mode: "open" }), l = t.createElement("style");
123
+ l.textContent = ke, i.appendChild(l);
124
+ const a = t.createElement("button");
125
+ return a.type = "button", a.className = "fb-launcher", a.setAttribute("aria-haspopup", "dialog"), a.setAttribute("aria-label", "Give feedback"), a.innerHTML = `${we}<span class="fb-launcher__label">Feedback</span>`, a.addEventListener("click", () => {
126
+ n.dispatchEvent(new CustomEvent(U, {
127
+ bubbles: !0,
128
+ composed: !0
129
+ }));
130
+ }), i.appendChild(a), e.appendChild(n), { host: n };
131
+ }
132
+ function Se(e) {
133
+ e.host.remove();
134
+ }
135
+ var ne = ["data-fixback-root", "data-fixback-overlay"], Ce = ne.map((e) => `[${e}]`).join(",");
136
+ function Te(e) {
137
+ let t = e instanceof Node ? e : null;
138
+ for (; t; ) {
139
+ if (t instanceof Element) {
140
+ for (const n of ne) if (t.hasAttribute(n)) return !0;
141
+ }
142
+ const o = t.getRootNode();
143
+ if (o instanceof ShadowRoot && o !== t) {
144
+ t = o.host;
145
+ continue;
146
+ }
147
+ t = t.parentNode;
148
+ }
149
+ return !1;
150
+ }
151
+ function Ie(e) {
152
+ for (const t of Array.from(e.querySelectorAll(Ce))) t.remove();
153
+ }
154
+ function ee(e) {
155
+ const t = globalThis.CSS;
156
+ return t != null && t.escape ? t.escape(e) : e.replace(/[^\w-]/g, (o) => `\\${o}`);
157
+ }
158
+ function Le(e) {
159
+ let t = 1, o = e.previousElementSibling;
160
+ for (; o; )
161
+ o.tagName === e.tagName && (t += 1), o = o.previousElementSibling;
162
+ return t;
163
+ }
164
+ function Ae(e) {
165
+ if (e.id) return `#${ee(e.id)}`;
166
+ const t = [];
167
+ let o = e;
168
+ for (; o && o.tagName.toLowerCase() !== "html"; ) {
169
+ if (o.id) {
170
+ t.unshift(`#${ee(o.id)}`);
171
+ break;
172
+ }
173
+ const n = o.tagName.toLowerCase(), i = o.parentElement;
174
+ if (i) {
175
+ const l = Array.from(i.children).filter((a) => a.tagName === o.tagName);
176
+ t.unshift(l.length > 1 ? `${n}:nth-of-type(${Le(o)})` : n);
177
+ } else t.unshift(n);
178
+ o = i;
179
+ }
180
+ return t.join(" > ");
181
+ }
182
+ function Ne(e) {
183
+ const t = e.tagName.toLowerCase();
184
+ if (e.id) return `${t}#${e.id}`;
185
+ const o = e.classList[0];
186
+ return o ? `${t}.${o}` : t;
187
+ }
188
+ function _e(e) {
189
+ const t = [];
190
+ let o = e;
191
+ for (; o; )
192
+ t.unshift(Ne(o)), o = o.parentElement;
193
+ return t.join(" > ");
194
+ }
195
+ function Oe(e) {
196
+ const t = e.getBoundingClientRect();
197
+ return {
198
+ x: Math.round(t.x),
199
+ y: Math.round(t.y),
200
+ width: Math.round(t.width),
201
+ height: Math.round(t.height)
202
+ };
203
+ }
204
+ function Re(e) {
205
+ return {
206
+ selector: Ae(e),
207
+ domPath: _e(e),
208
+ tag: e.tagName.toLowerCase(),
209
+ rect: Oe(e)
210
+ };
211
+ }
212
+ function Me(e) {
213
+ var t, o;
214
+ const n = (t = e.doc) !== null && t !== void 0 ? t : document, i = (o = e.ignore) !== null && o !== void 0 ? o : Te;
215
+ let l = null, a = !1;
216
+ function c(u) {
217
+ var f;
218
+ const y = (f = (typeof u.composedPath == "function" ? u.composedPath() : [])[0]) !== null && f !== void 0 ? f : u.target;
219
+ return y instanceof Element ? i(y) ? null : y : null;
220
+ }
221
+ function b(u) {
222
+ var f;
223
+ a || (l = c(u), (f = e.onHover) === null || f === void 0 || f.call(e, l));
224
+ }
225
+ function p(u) {
226
+ var f;
227
+ if (a) return;
228
+ const y = (f = c(u)) !== null && f !== void 0 ? f : l;
229
+ y && (u.preventDefault(), u.stopPropagation(), s(), e.onPick(y));
230
+ }
231
+ function g(u) {
232
+ if (!a && u.key === "Escape") {
233
+ var f;
234
+ u.preventDefault(), s(), (f = e.onCancel) === null || f === void 0 || f.call(e);
235
+ }
236
+ }
237
+ function s() {
238
+ a || (a = !0, n.removeEventListener("mouseover", b, !0), n.removeEventListener("click", p, !0), n.removeEventListener("keydown", g, !0), l = null);
239
+ }
240
+ return n.addEventListener("mouseover", b, !0), n.addEventListener("click", p, !0), n.addEventListener("keydown", g, !0), { stop: s };
241
+ }
242
+ function Be(e, t) {
243
+ var o;
244
+ const n = {}, i = e.innerWidth;
245
+ typeof i == "number" && i > 0 && (n.viewportWidth = Math.round(i));
246
+ const l = e.innerHeight;
247
+ typeof l == "number" && l > 0 && (n.viewportHeight = Math.round(l));
248
+ const a = (o = e.navigator) === null || o === void 0 ? void 0 : o.userAgent;
249
+ return typeof a == "string" && a.length > 0 && (n.browser = a), t.length > 0 && (n.sdkVersion = t), n;
250
+ }
251
+ function ze(e) {
252
+ var t;
253
+ const o = {};
254
+ e.kind && (o.kind = e.kind);
255
+ const n = (t = e.comment) === null || t === void 0 ? void 0 : t.trim();
256
+ return n && (o.comment = n), e.url && (o.url = e.url), e.environment && Object.keys(e.environment).length > 0 && (o.environment = e.environment), e.element && (o.annotation = e.element), o;
257
+ }
258
+ var Pe = `
259
+ :host {
260
+ --fb-color-accent: #2f6fed;
261
+ --fb-color-accent-hover: #245fd0;
262
+ --fb-color-on-emphasis: #ffffff;
263
+ --fb-color-ink: #0f1720;
264
+ --fb-color-text: #1a2530;
265
+ --fb-color-muted: #5a6875;
266
+ --fb-color-faint: #9aa7b2;
267
+ --fb-color-border: #e0e6ec;
268
+ --fb-color-border-soft: #e6ebf0;
269
+ --fb-color-surface: #ffffff;
270
+ --fb-color-bug: #e5484d;
271
+ --fb-color-bug-bg: #fdecec;
272
+ --fb-color-impr: #2f6fed;
273
+ --fb-color-impr-bg: #eaf1fe;
274
+ --fb-color-idea: #8b5cf6;
275
+ --fb-color-idea-bg: #f2ecfe;
276
+ --fb-color-success: #2f9e5b;
277
+ --fb-font-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto,
278
+ Helvetica, Arial, sans-serif;
279
+ --fb-font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas,
280
+ monospace;
281
+
282
+ display: block;
283
+ color: var(--fb-color-text);
284
+ font-family: var(--fb-font-sans);
285
+ font-size: 13px;
286
+ line-height: 1.45;
287
+ -webkit-font-smoothing: antialiased;
288
+ }
289
+
290
+ * { box-sizing: border-box; }
291
+
292
+ .fb-ov-panel {
293
+ width: 300px;
294
+ max-width: calc(100vw - 40px);
295
+ background: var(--fb-color-surface);
296
+ border: 1px solid var(--fb-color-border);
297
+ border-radius: 13px;
298
+ box-shadow: 0 18px 44px rgba(20, 40, 70, 0.2);
299
+ overflow: hidden;
300
+ }
301
+
302
+ .fb-ov-head {
303
+ display: flex;
304
+ align-items: center;
305
+ gap: 9px;
306
+ padding: 12px 14px;
307
+ border-bottom: 1px solid var(--fb-color-border-soft);
308
+ }
309
+ .fb-ov-mark-sq {
310
+ width: 13px;
311
+ height: 13px;
312
+ border-radius: 4px;
313
+ background: var(--fb-color-accent);
314
+ flex: none;
315
+ }
316
+ .fb-ov-brand { font-size: 14px; font-weight: 600; color: var(--fb-color-ink); }
317
+ .fb-ov-close {
318
+ margin-left: auto;
319
+ border: 0;
320
+ background: none;
321
+ color: var(--fb-color-faint);
322
+ font-size: 16px;
323
+ line-height: 1;
324
+ padding: 2px 4px;
325
+ cursor: pointer;
326
+ border-radius: 6px;
327
+ }
328
+ .fb-ov-close:hover { color: var(--fb-color-muted); background: #f4f7fa; }
329
+
330
+ .fb-ov-tabs { display: flex; gap: 6px; padding: 12px 14px 6px; }
331
+ .fb-ov-tab {
332
+ flex: 1;
333
+ text-align: center;
334
+ font-size: 11px;
335
+ font-weight: 600;
336
+ padding: 6px;
337
+ border-radius: 7px;
338
+ border: 1px solid var(--fb-color-border);
339
+ background: var(--fb-color-surface);
340
+ color: var(--fb-color-muted);
341
+ cursor: pointer;
342
+ font-family: inherit;
343
+ }
344
+ .fb-ov-tab:hover { border-color: #cfd8e2; }
345
+ .fb-ov-tab.is-active[data-kind="bug"] {
346
+ background: var(--fb-color-bug-bg); color: var(--fb-color-bug); border-color: transparent;
347
+ }
348
+ .fb-ov-tab.is-active[data-kind="improvement"] {
349
+ background: var(--fb-color-impr-bg); color: var(--fb-color-impr); border-color: transparent;
350
+ }
351
+ .fb-ov-tab.is-active[data-kind="idea"] {
352
+ background: var(--fb-color-idea-bg); color: var(--fb-color-idea); border-color: transparent;
353
+ }
354
+
355
+ .fb-ov-mark {
356
+ margin: 10px 14px;
357
+ min-height: 52px;
358
+ border-radius: 9px;
359
+ border: 1px solid var(--fb-color-border-soft);
360
+ background: repeating-linear-gradient(135deg, #f4f7fa, #f4f7fa 7px, #eaeff4 7px, #eaeff4 14px);
361
+ display: flex;
362
+ flex-direction: column;
363
+ align-items: flex-start;
364
+ justify-content: center;
365
+ gap: 6px;
366
+ padding: 10px 12px;
367
+ }
368
+ .fb-ov-selector {
369
+ display: none;
370
+ max-width: 100%;
371
+ font-family: var(--fb-font-mono);
372
+ font-size: 10px;
373
+ color: var(--fb-color-on-emphasis);
374
+ background: var(--fb-color-accent);
375
+ padding: 3px 8px;
376
+ border-radius: 5px;
377
+ overflow: hidden;
378
+ text-overflow: ellipsis;
379
+ white-space: nowrap;
380
+ }
381
+ .fb-ov-mark.has-element .fb-ov-selector { display: inline-block; }
382
+ .fb-ov-mark-caption { font-size: 10px; color: var(--fb-color-faint); font-family: var(--fb-font-mono); }
383
+
384
+ .fb-ov-comment {
385
+ display: block;
386
+ width: calc(100% - 28px);
387
+ margin: 0 14px 10px;
388
+ min-height: 62px;
389
+ resize: vertical;
390
+ font-family: inherit;
391
+ font-size: 13px;
392
+ color: var(--fb-color-text);
393
+ border: 1px solid var(--fb-color-border-soft);
394
+ border-radius: 9px;
395
+ padding: 10px 11px;
396
+ }
397
+ .fb-ov-comment::placeholder { color: var(--fb-color-faint); }
398
+ .fb-ov-comment:focus-visible { outline: 2px solid var(--fb-color-accent); outline-offset: 1px; }
399
+
400
+ .fb-ov-status { padding: 0 14px; font-size: 11px; min-height: 0; }
401
+ .fb-ov-status.is-error { color: var(--fb-color-bug); }
402
+
403
+ .fb-ov-tools { display: flex; align-items: center; gap: 8px; padding: 8px 14px 14px; }
404
+ .fb-ov-pickbtn {
405
+ display: inline-flex;
406
+ align-items: center;
407
+ gap: 6px;
408
+ font-family: inherit;
409
+ font-size: 12px;
410
+ color: var(--fb-color-muted);
411
+ background: var(--fb-color-surface);
412
+ border: 1px solid var(--fb-color-border);
413
+ border-radius: 8px;
414
+ padding: 8px 11px;
415
+ cursor: pointer;
416
+ }
417
+ .fb-ov-pickbtn:hover { border-color: #cfd8e2; }
418
+ .fb-ov-pickbtn.is-active {
419
+ color: var(--fb-color-accent);
420
+ border-color: var(--fb-color-accent);
421
+ background: var(--fb-color-impr-bg);
422
+ }
423
+ .fb-ov-pickbtn__glyph { font-size: 14px; line-height: 1; }
424
+
425
+ .fb-ov-send {
426
+ margin-left: auto;
427
+ font-family: inherit;
428
+ font-size: 13px;
429
+ font-weight: 600;
430
+ color: var(--fb-color-on-emphasis);
431
+ background: var(--fb-color-accent);
432
+ border: 0;
433
+ border-radius: 8px;
434
+ padding: 9px 18px;
435
+ cursor: pointer;
436
+ }
437
+ .fb-ov-send:hover { background: var(--fb-color-accent-hover); }
438
+ .fb-ov-send:disabled { opacity: 0.6; cursor: default; }
439
+
440
+ .fb-ov-done { display: none; padding: 24px 18px; text-align: center; }
441
+ .fb-ov-panel.is-sent .fb-ov-form { display: none; }
442
+ .fb-ov-panel.is-sent .fb-ov-done { display: block; }
443
+ .fb-ov-done__check {
444
+ width: 40px; height: 40px; margin: 0 auto 12px;
445
+ border-radius: 50%;
446
+ background: #e7f6ee; color: var(--fb-color-success);
447
+ display: flex; align-items: center; justify-content: center;
448
+ font-size: 20px; font-weight: 700;
449
+ }
450
+ .fb-ov-done__title { font-size: 15px; font-weight: 600; color: var(--fb-color-ink); }
451
+ .fb-ov-done__sub { font-size: 12px; color: var(--fb-color-muted); margin-top: 4px; }
452
+
453
+ .fb-ov-pick { position: fixed; inset: 0; pointer-events: none; z-index: 2147483002; display: none; }
454
+ .fb-ov-panel.is-picking + .fb-ov-pick { display: block; }
455
+ .fb-ov-panel.is-picking { visibility: hidden; }
456
+ .fb-ov-highlight {
457
+ position: absolute;
458
+ border: 2px dashed var(--fb-color-accent);
459
+ border-radius: 6px;
460
+ box-shadow: 0 0 0 3px rgba(47, 111, 237, 0.14);
461
+ transition: all 60ms ease;
462
+ }
463
+ .fb-ov-hint {
464
+ position: absolute;
465
+ top: 16px;
466
+ left: 50%;
467
+ transform: translateX(-50%);
468
+ font-family: var(--fb-font-mono);
469
+ font-size: 11px;
470
+ color: var(--fb-color-on-emphasis);
471
+ background: var(--fb-color-ink);
472
+ padding: 6px 12px;
473
+ border-radius: 7px;
474
+ box-shadow: 0 8px 20px rgba(20, 40, 70, 0.25);
475
+ }
476
+
477
+ @media (prefers-reduced-motion: reduce) {
478
+ .fb-ov-highlight { transition: none; }
479
+ }
480
+ `;
481
+ var $e = 32, He = /* @__PURE__ */ new Set([
482
+ "button",
483
+ "submit",
484
+ "reset",
485
+ "checkbox",
486
+ "radio",
487
+ "range",
488
+ "color",
489
+ "file",
490
+ "image",
491
+ "hidden"
492
+ ]);
493
+ function V(e) {
494
+ const t = Math.min(Math.max(e, 1), $e);
495
+ return "•".repeat(t);
496
+ }
497
+ function Ve(e) {
498
+ for (const n of Array.from(e.querySelectorAll("input"))) {
499
+ var t;
500
+ const i = ((t = n.getAttribute("type")) !== null && t !== void 0 ? t : "text").toLowerCase();
501
+ if (He.has(i)) continue;
502
+ const l = n.value;
503
+ if (!l) continue;
504
+ const a = V(l.length);
505
+ n.value = a, n.setAttribute("value", a);
506
+ }
507
+ for (const n of Array.from(e.querySelectorAll("textarea"))) {
508
+ const i = n.value || n.textContent || "";
509
+ if (!i) continue;
510
+ const l = V(i.length);
511
+ n.value = l, n.textContent = l;
512
+ }
513
+ for (const n of Array.from(e.querySelectorAll("[contenteditable]"))) {
514
+ var o;
515
+ if (n.getAttribute("contenteditable") === "false") continue;
516
+ const i = (o = n.textContent) !== null && o !== void 0 ? o : "";
517
+ i.trim() && (n.textContent = V(i.length));
518
+ }
519
+ }
520
+ function te(e, t, o) {
521
+ const n = e == null ? void 0 : e[`inner${o}`], i = t.documentElement[`client${o}`];
522
+ return Math.max(1, Math.round((typeof n == "number" && n > 0 ? n : i) || 0) || 1);
523
+ }
524
+ function Ue(e, t, o) {
525
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${o}"><foreignObject x="0" y="0" width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml">${new XMLSerializer().serializeToString(e)}</div></foreignObject></svg>`;
526
+ }
527
+ var je = 4e3, Fe = (e, { width: t, height: o, type: n }) => new Promise((i) => {
528
+ let l = !1;
529
+ const a = (c) => {
530
+ l || (l = !0, i(c));
531
+ };
532
+ try {
533
+ const c = new Image(), b = setTimeout(() => a(null), je);
534
+ c.onload = () => {
535
+ try {
536
+ const p = document.createElement("canvas");
537
+ p.width = t, p.height = o;
538
+ const g = p.getContext("2d");
539
+ if (!g) {
540
+ clearTimeout(b), a(null);
541
+ return;
542
+ }
543
+ g.drawImage(c, 0, 0), p.toBlob((s) => {
544
+ clearTimeout(b), a(s);
545
+ }, n);
546
+ } catch {
547
+ clearTimeout(b), a(null);
548
+ }
549
+ }, c.onerror = () => {
550
+ clearTimeout(b), a(null);
551
+ }, c.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(e)}`;
552
+ } catch {
553
+ a(null);
554
+ }
555
+ });
556
+ async function De(e = {}) {
557
+ try {
558
+ var t, o, n, i, l, a;
559
+ const c = (t = e.doc) !== null && t !== void 0 ? t : document, b = (o = (n = e.win) !== null && n !== void 0 ? n : c.defaultView) !== null && o !== void 0 ? o : void 0, p = (i = e.target) !== null && i !== void 0 ? i : c.documentElement, g = (l = e.type) !== null && l !== void 0 ? l : "image/png", s = te(b, c, "Width"), u = te(b, c, "Height"), f = p.cloneNode(!0);
560
+ Ie(f), Ve(f);
561
+ const y = Ue(f, s, u), h = await ((a = e.rasterize) !== null && a !== void 0 ? a : Fe)(y, {
562
+ width: s,
563
+ height: u,
564
+ type: g
565
+ });
566
+ return h ? {
567
+ blob: h,
568
+ width: s,
569
+ height: u,
570
+ type: g
571
+ } : null;
572
+ } catch {
573
+ return null;
574
+ }
575
+ }
576
+ var Ke = "screenshot";
577
+ function qe(e) {
578
+ return `${e.replace(/\/+$/, "")}/api/ingest/feedback`;
579
+ }
580
+ function Xe(e) {
581
+ if (!e) return {};
582
+ const t = {};
583
+ return e.signedIdentity && (t.signedIdentity = e.signedIdentity), e.reporterId && (t.reporterId = e.reporterId), e.anonymousId && (t.anonymousId = e.anonymousId), t;
584
+ }
585
+ async function Ye(e, t, o = fetch) {
586
+ var n;
587
+ const i = {
588
+ key: t.key,
589
+ ...Xe(t.identity),
590
+ ...t.content
591
+ }, l = new FormData();
592
+ if (l.append("payload", JSON.stringify(i)), !((n = t.screenshot) === null || n === void 0) && n.blob) {
593
+ var a;
594
+ l.append(Ke, t.screenshot.blob, (a = t.screenshot.filename) !== null && a !== void 0 ? a : "screenshot.png");
595
+ }
596
+ let c;
597
+ try {
598
+ c = await o(qe(e), {
599
+ method: "POST",
600
+ body: l
601
+ });
602
+ } catch {
603
+ return {
604
+ ok: !1,
605
+ reason: "unreachable"
606
+ };
607
+ }
608
+ if (!c.ok) return {
609
+ ok: !1,
610
+ reason: "refused",
611
+ status: c.status
612
+ };
613
+ try {
614
+ return {
615
+ ok: !0,
616
+ feedback: await c.json()
617
+ };
618
+ } catch {
619
+ return {
620
+ ok: !0,
621
+ feedback: null
622
+ };
623
+ }
624
+ }
625
+ var re = "0.1.0", Ge = "data-fixback-overlay", We = [
626
+ {
627
+ value: "bug",
628
+ label: "Bug"
629
+ },
630
+ {
631
+ value: "improvement",
632
+ label: "Improve"
633
+ },
634
+ {
635
+ value: "idea",
636
+ label: "Idea"
637
+ }
638
+ ], Je = 1800;
639
+ function d(e, t, o = {}, n = []) {
640
+ const i = e.createElement(t);
641
+ for (const [l, a] of Object.entries(o)) a !== void 0 && i.setAttribute(l, a);
642
+ for (const l of n) i.appendChild(typeof l == "string" ? e.createTextNode(l) : l);
643
+ return i;
644
+ }
645
+ var Ze = {
646
+ "image/png": "png",
647
+ "image/jpeg": "jpg",
648
+ "image/webp": "webp",
649
+ "image/gif": "gif"
650
+ };
651
+ function Qe(e) {
652
+ var t;
653
+ return (t = Ze[e]) !== null && t !== void 0 ? t : "png";
654
+ }
655
+ function et(e) {
656
+ var t, o, n, i, l, a, c, b, p, g;
657
+ const s = (t = e.doc) !== null && t !== void 0 ? t : document, u = (o = (n = e.win) !== null && n !== void 0 ? n : s.defaultView) !== null && o !== void 0 ? o : window, f = (i = e.sdkVersion) !== null && i !== void 0 ? i : re, y = {
658
+ captureView: (l = (a = e.deps) === null || a === void 0 ? void 0 : a.captureView) !== null && l !== void 0 ? l : De,
659
+ submitReport: (c = (b = e.deps) === null || b === void 0 ? void 0 : b.submitReport) !== null && c !== void 0 ? c : Ye,
660
+ startElementPicker: (p = (g = e.deps) === null || g === void 0 ? void 0 : g.startElementPicker) !== null && p !== void 0 ? p : Me
661
+ };
662
+ let h = null, r = null, E = null, T = null, I = !1;
663
+ const x = {
664
+ kind: "bug",
665
+ selectedElement: null,
666
+ phase: "compose"
667
+ };
668
+ function L(v, m) {
669
+ r && (r.status.textContent = v, r.status.classList.toggle("is-error", m));
670
+ }
671
+ function j(v) {
672
+ if (x.kind = v, !!r)
673
+ for (const [m, w] of r.tabs) {
674
+ const k = m === v;
675
+ w.classList.toggle("is-active", k), w.setAttribute("aria-pressed", String(k));
676
+ }
677
+ }
678
+ function F() {
679
+ r && (x.selectedElement ? (r.mark.classList.add("has-element"), r.selector.textContent = x.selectedElement.selector, r.caption.textContent = "Element selected · masked screenshot on Send", r.pickBtn.textContent = "", r.pickBtn.append(oe(s), s.createTextNode("Change element"))) : (r.mark.classList.remove("has-element"), r.selector.textContent = "", r.caption.textContent = "Masked screenshot attached on Send", r.pickBtn.textContent = "", r.pickBtn.append(oe(s), s.createTextNode("Pick element"))));
680
+ }
681
+ function ie(v) {
682
+ if (!r) return;
683
+ if (!v) {
684
+ r.highlight.style.display = "none";
685
+ return;
686
+ }
687
+ const m = v.getBoundingClientRect();
688
+ r.highlight.style.display = "block", r.highlight.style.left = `${m.left}px`, r.highlight.style.top = `${m.top}px`, r.highlight.style.width = `${m.width}px`, r.highlight.style.height = `${m.height}px`;
689
+ }
690
+ function N() {
691
+ E == null || E.stop(), E = null;
692
+ }
693
+ function S() {
694
+ r && (r.panel.classList.remove("is-picking"), r.pickBtn.classList.remove("is-active"), r.highlight.style.display = "none"), N();
695
+ }
696
+ function ae() {
697
+ r && (N(), r.panel.classList.add("is-picking"), r.pickBtn.classList.add("is-active"), E = y.startElementPicker({
698
+ doc: s,
699
+ onHover: ie,
700
+ onPick: (v) => {
701
+ x.selectedElement = Re(v), S(), F();
702
+ },
703
+ onCancel: S
704
+ }));
705
+ }
706
+ function _() {
707
+ T !== null && (clearTimeout(T), T = null);
708
+ }
709
+ async function se() {
710
+ if (!(!r || x.phase === "sending")) {
711
+ x.phase = "sending", r.sendBtn.disabled = !0, r.sendBtn.textContent = "Sending…", L("", !1);
712
+ try {
713
+ var v, m;
714
+ const w = ze({
715
+ kind: x.kind,
716
+ comment: r.comment.value,
717
+ element: (v = x.selectedElement) !== null && v !== void 0 ? v : void 0,
718
+ url: (m = u.location) === null || m === void 0 ? void 0 : m.href,
719
+ environment: Be(u, f)
720
+ }), k = await y.captureView({
721
+ doc: s,
722
+ win: u
723
+ }), M = k ? {
724
+ blob: k.blob,
725
+ filename: `screenshot.${Qe(k.type)}`
726
+ } : null, C = await y.submitReport(e.apiUrl, {
727
+ key: e.key,
728
+ identity: e.identity,
729
+ content: w,
730
+ screenshot: M
731
+ });
732
+ C.ok ? (x.phase = "sent", r.panel.classList.add("is-sent"), T = setTimeout(R, Je)) : (O(), L(C.reason === "unreachable" ? "Couldn't reach Fixback — try again." : "Fixback couldn't accept this report.", !0));
733
+ } catch {
734
+ O(), L("Something went wrong — try again.", !0);
735
+ }
736
+ }
737
+ }
738
+ function O() {
739
+ x.phase = "compose", r && (r.sendBtn.disabled = !1, r.sendBtn.textContent = "Send");
740
+ }
741
+ function le() {
742
+ var v;
743
+ h = d(s, "div", { [Ge]: "" }), h.style.cssText = "position:fixed;right:20px;bottom:84px;z-index:2147483001;margin:0;padding:0;border:0;display:none;";
744
+ const m = h.attachShadow({ mode: "open" }), w = s.createElement("style");
745
+ w.textContent = Pe, m.appendChild(w);
746
+ const k = d(s, "button", {
747
+ type: "button",
748
+ class: "fb-ov-close",
749
+ "aria-label": "Close"
750
+ }, ["✕"]), M = d(s, "div", { class: "fb-ov-head" }, [
751
+ d(s, "span", { class: "fb-ov-mark-sq" }),
752
+ d(s, "span", { class: "fb-ov-brand" }, ["Fixback"]),
753
+ k
754
+ ]), C = /* @__PURE__ */ new Map(), D = d(s, "div", { class: "fb-ov-tabs" });
755
+ for (const { value: $, label: he } of We) {
756
+ const H = d(s, "button", {
757
+ type: "button",
758
+ class: "fb-ov-tab",
759
+ "data-kind": $
760
+ }, [he]);
761
+ H.addEventListener("click", () => j($)), C.set($, H), D.appendChild(H);
762
+ }
763
+ const K = d(s, "span", { class: "fb-ov-selector" }), q = d(s, "span", { class: "fb-ov-mark-caption" }), X = d(s, "div", { class: "fb-ov-mark" }, [K, q]), Y = d(s, "textarea", {
764
+ class: "fb-ov-comment",
765
+ placeholder: "Describe what you saw or want…",
766
+ "aria-label": "Comment"
767
+ }), G = d(s, "div", {
768
+ class: "fb-ov-status",
769
+ role: "status",
770
+ "aria-live": "polite"
771
+ }), B = d(s, "button", {
772
+ type: "button",
773
+ class: "fb-ov-pickbtn"
774
+ });
775
+ B.addEventListener("click", () => {
776
+ x.phase !== "sending" && (r != null && r.panel.classList.contains("is-picking") ? S() : ae());
777
+ });
778
+ const z = d(s, "button", {
779
+ type: "button",
780
+ class: "fb-ov-send"
781
+ }, ["Send"]);
782
+ z.addEventListener("click", () => {
783
+ se();
784
+ });
785
+ const ue = d(s, "div", { class: "fb-ov-tools" }, [B, z]), be = d(s, "div", { class: "fb-ov-form" }, [
786
+ D,
787
+ X,
788
+ Y,
789
+ G,
790
+ ue
791
+ ]), pe = d(s, "div", { class: "fb-ov-done" }, [
792
+ d(s, "div", { class: "fb-ov-done__check" }, ["✓"]),
793
+ d(s, "div", { class: "fb-ov-done__title" }, ["Report sent"]),
794
+ d(s, "div", { class: "fb-ov-done__sub" }, ["Thanks — the team can see it now."])
795
+ ]), W = d(s, "div", {
796
+ class: "fb-ov-panel",
797
+ role: "dialog",
798
+ "aria-label": "Fixback feedback"
799
+ }, [
800
+ M,
801
+ be,
802
+ pe
803
+ ]), P = d(s, "div", { class: "fb-ov-highlight" });
804
+ P.style.display = "none";
805
+ const ve = d(s, "div", { class: "fb-ov-pick" }, [d(s, "div", { class: "fb-ov-hint" }, ["Click the element you mean · Esc to cancel"]), P]);
806
+ m.appendChild(W), m.appendChild(ve), k.addEventListener("click", R), ((v = e.target) !== null && v !== void 0 ? v : s.body).appendChild(h), r = {
807
+ panel: W,
808
+ tabs: C,
809
+ mark: X,
810
+ selector: K,
811
+ caption: q,
812
+ comment: Y,
813
+ status: G,
814
+ pickBtn: B,
815
+ sendBtn: z,
816
+ highlight: P
817
+ };
818
+ }
819
+ function ce() {
820
+ (!h || !r) && le();
821
+ }
822
+ function de() {
823
+ if (ce(), !(!h || !r)) {
824
+ _(), S(), x.phase = "compose", x.selectedElement = null, r.panel.classList.remove("is-sent"), r.comment.value = "", O(), L("", !1), j("bug"), F(), h.style.display = "block", I = !0;
825
+ try {
826
+ r.comment.focus();
827
+ } catch {
828
+ }
829
+ }
830
+ }
831
+ function R() {
832
+ _(), S(), h && (h.style.display = "none"), I = !1;
833
+ }
834
+ function fe() {
835
+ _(), N(), h == null || h.remove(), h = null, r = null, I = !1;
836
+ }
837
+ return {
838
+ open: de,
839
+ close: R,
840
+ destroy: fe,
841
+ get isOpen() {
842
+ return I;
843
+ }
844
+ };
845
+ }
846
+ function oe(e) {
847
+ return d(e, "span", {
848
+ class: "fb-ov-pickbtn__glyph",
849
+ "aria-hidden": "true"
850
+ }, ["⌖"]);
851
+ }
852
+ var tt = "https://api.fixback.dev", A = { destroy() {
853
+ } };
854
+ async function ot(e) {
855
+ try {
856
+ var t, o, n;
857
+ if (typeof document == "undefined") return A;
858
+ const i = e == null ? void 0 : e.key;
859
+ if (typeof i != "string" || i.length === 0) return A;
860
+ const l = (t = e.apiUrl) !== null && t !== void 0 ? t : tt, a = (o = e.anonymousId) !== null && o !== void 0 ? o : ye(), c = await xe(l, {
861
+ key: i,
862
+ signedIdentity: e.signedIdentity,
863
+ reporterId: e.reporterId,
864
+ anonymousId: a
865
+ });
866
+ if (!(c != null && c.canSubmit)) return A;
867
+ const b = (n = e.target) !== null && n !== void 0 ? n : document.body, p = Ee(b), g = et({
868
+ apiUrl: l,
869
+ key: i,
870
+ identity: {
871
+ signedIdentity: e.signedIdentity,
872
+ reporterId: e.reporterId,
873
+ anonymousId: a
874
+ },
875
+ sdkVersion: re,
876
+ target: b
877
+ }), s = () => g.open();
878
+ return p.host.addEventListener(U, s), { destroy: () => {
879
+ p.host.removeEventListener(U, s), g.destroy(), Se(p);
880
+ } };
881
+ } catch {
882
+ return A;
883
+ }
884
+ }
885
+ export {
886
+ tt as DEFAULT_API_URL,
887
+ U as LAUNCH_EVENT,
888
+ ot as init
889
+ };
890
+
891
+ //# sourceMappingURL=index.mjs.map