@getpinax/widget 0.0.0-stage → 1.0.0-beta.2

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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +513 -2
  3. package/dist/a11y/scan.d.ts +25 -0
  4. package/dist/api.d.ts +83 -0
  5. package/dist/capture/breadcrumbs.d.ts +49 -0
  6. package/dist/capture/console.d.ts +17 -0
  7. package/dist/capture/env.d.ts +25 -0
  8. package/dist/capture/network.d.ts +23 -0
  9. package/dist/capture/ring.d.ts +14 -0
  10. package/dist/capture/signature.d.ts +7 -0
  11. package/dist/capture/text.d.ts +23 -0
  12. package/dist/capture/ua.d.ts +13 -0
  13. package/dist/chunks/editor-0Kr31Uly.mjs +1368 -0
  14. package/dist/chunks/privacy-B_b1_Y1n.mjs +39 -0
  15. package/dist/chunks/recorder-tu4yugLw.mjs +2874 -0
  16. package/dist/chunks/scan-CFQwrtAQ.mjs +46137 -0
  17. package/dist/chunks/text-D9SaDBT0.mjs +36 -0
  18. package/dist/chunks/widget-BpTBdX2R.mjs +1272 -0
  19. package/dist/editor/annotator.d.ts +20 -0
  20. package/dist/editor/capture.d.ts +28 -0
  21. package/dist/editor/encode.d.ts +7 -0
  22. package/dist/editor/index.d.ts +5 -0
  23. package/dist/editor/mask.d.ts +29 -0
  24. package/dist/editor/pii.d.ts +22 -0
  25. package/dist/editor/shapes.d.ts +31 -0
  26. package/dist/editor-loader.d.ts +9 -0
  27. package/dist/editor-loader.embed.d.ts +6 -0
  28. package/dist/fixcheck.d.ts +42 -0
  29. package/dist/index.d.ts +85 -0
  30. package/dist/known.d.ts +27 -0
  31. package/dist/mount.d.ts +8 -0
  32. package/dist/navigation.d.ts +1 -0
  33. package/dist/paths.d.ts +4 -0
  34. package/dist/pinax-axe.js +46167 -0
  35. package/dist/pinax-editor.js +1417 -0
  36. package/dist/pinax-recorder.js +2915 -0
  37. package/dist/pinax.js +135 -0
  38. package/dist/pinax.mjs +1270 -0
  39. package/dist/preview.d.ts +48 -0
  40. package/dist/preview.mjs +67 -0
  41. package/dist/privacy.d.ts +24 -0
  42. package/dist/queue.d.ts +10 -0
  43. package/dist/replay/buffer.d.ts +40 -0
  44. package/dist/replay/recorder.d.ts +25 -0
  45. package/dist/replay/sanitize.d.ts +19 -0
  46. package/dist/report.d.ts +128 -0
  47. package/dist/segment.d.ts +31 -0
  48. package/dist/settings.d.ts +40 -0
  49. package/dist/types.d.ts +247 -0
  50. package/dist/ui/color.d.ts +7 -0
  51. package/dist/ui/dom.d.ts +14 -0
  52. package/dist/ui/styles.d.ts +3 -0
  53. package/dist/ui/widget.d.ts +241 -0
  54. package/package.json +74 -4
@@ -0,0 +1,1272 @@
1
+ import { a as e, i as t, n, t as r } from "./text-D9SaDBT0.mjs";
2
+ import { o as i } from "./privacy-B_b1_Y1n.mjs";
3
+ // src/report.ts
4
+ var a = [
5
+ "see",
6
+ "keyboard",
7
+ "screen-reader",
8
+ "media",
9
+ "other"
10
+ ], o = {
11
+ message: 5e3,
12
+ email: 320,
13
+ entries: 50,
14
+ annotations: 200,
15
+ screenshotChars: 6e6,
16
+ screenshotBytes: 4718592,
17
+ breadcrumbs: 20,
18
+ followUpQuestion: 300,
19
+ followUpAnswer: 2e3,
20
+ replayChars: 45e5,
21
+ fields: 10,
22
+ fieldId: 40,
23
+ fieldText: 200,
24
+ bodyBytes: 11534336
25
+ }, s = 65536, c = /^[A-Za-z0-9+/=]+$/, l = /^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9-]*\.)+[A-Za-z]{2,}$/, u = /^data:image\/(png|jpeg|webp);base64,[A-Za-z0-9+/=]+$/;
26
+ function d(e) {
27
+ return e.length <= o.email && l.test(e);
28
+ }
29
+ function f(e) {
30
+ let t = e.slice(e.indexOf(",") + 1), n = t.endsWith("==") ? 2 : +!!t.endsWith("=");
31
+ return Math.floor(t.length * 3 / 4) - n;
32
+ }
33
+ function p(e) {
34
+ return e.length <= o.screenshotChars && u.test(e) && f(e) <= o.screenshotBytes;
35
+ }
36
+ function m(e) {
37
+ return e.message.trim().length > 0 || e.type === "GENERAL" && e.rating !== void 0 || e.type === "ACCESSIBILITY" && e.barrier !== void 0 || e.screenshot !== void 0;
38
+ }
39
+ var h = (e, t) => Number.isFinite(e) ? Math.round(Math.min(1, Math.max(t, e)) * 1e4) / 1e4 : 0;
40
+ function g(i) {
41
+ let a = t(e(i), r);
42
+ return a.length <= 2e3 ? a : n(a.split("?")[0], 2e3);
43
+ }
44
+ function _(e) {
45
+ if (!e) return;
46
+ let t = {};
47
+ return e.id != null && String(e.id) && (t.id = n(String(e.id), 200)), e.name && (t.name = n(String(e.name), 200)), Object.keys(t).length ? t : void 0;
48
+ }
49
+ function v(e, t) {
50
+ let r = {
51
+ type: e.type,
52
+ message: n(e.message.trim(), o.message),
53
+ page: {
54
+ url: g(t.page.url),
55
+ title: t.page.title ? n(t.page.title, 500) : void 0
56
+ },
57
+ environment: t.environment
58
+ };
59
+ e.type === "GENERAL" && e.rating !== void 0 && Number.isInteger(e.rating) && e.rating >= 1 && e.rating <= 5 && (r.rating = e.rating);
60
+ let s = e.email?.trim().toLowerCase();
61
+ s && d(s) && (r.email = s);
62
+ let c = _(e.user);
63
+ c && (r.user = c), t.console.length && (r.console = t.console.slice(-o.entries).map((e) => {
64
+ let t = {
65
+ ...e,
66
+ message: i(e.message)
67
+ };
68
+ return e.stack && (t.stack = i(e.stack)), t;
69
+ })), t.network.length && (r.network = t.network.slice(-o.entries)), t.breadcrumbs?.length && (r.breadcrumbs = t.breadcrumbs.slice(-o.breadcrumbs).map((e) => {
70
+ let t = {
71
+ kind: e.kind,
72
+ at: n(e.at, 40),
73
+ path: n(e.path, 500)
74
+ };
75
+ return e.target && (t.target = n(i(e.target), 200)), t;
76
+ }));
77
+ let l = e.followUp?.question.trim(), u = e.followUp?.answer.trim();
78
+ l && u && (r.followUp = {
79
+ question: n(l, o.followUpQuestion),
80
+ answer: n(u, o.followUpAnswer)
81
+ });
82
+ let f = (e.fields ?? []).filter((e) => typeof e.id == "string" && e.id.length <= o.fieldId && (typeof e.value == "boolean" || typeof e.value == "string" && e.value.trim())).slice(0, o.fields).map((e) => ({
83
+ id: e.id,
84
+ value: typeof e.value == "boolean" ? e.value : n(e.value.trim(), o.fieldText)
85
+ }));
86
+ return f.length && (r.fields = f), e.type === "ACCESSIBILITY" && (e.barrier && a.includes(e.barrier) && (r.barrier = e.barrier), e.a11yScan && (r.a11yScan = e.a11yScan)), e.consent && (r.consent = {
87
+ diagnostics: e.consent.diagnostics === !0,
88
+ replay: e.consent.replay === !0
89
+ }), e.includeLogs === !0 && (r.includeLogs = !0), e.hp && (r.hp = n(e.hp, 500)), e.elapsedMs !== void 0 && Number.isFinite(e.elapsedMs) && e.elapsedMs >= 0 && (r.elapsedMs = Math.min(Math.round(e.elapsedMs), 864e5)), e.screenshot && p(e.screenshot) && (r.screenshot = e.screenshot, e.annotations?.length && (r.annotations = e.annotations.slice(0, o.annotations).map((e) => {
90
+ let t = e.type === "arrow" ? -1 : 0, r = {
91
+ type: e.type,
92
+ x: h(e.x, 0),
93
+ y: h(e.y, 0),
94
+ w: h(e.w, t),
95
+ h: h(e.h, t)
96
+ };
97
+ return e.type === "text" && e.text && (r.text = n(e.text, 500)), r;
98
+ }))), r;
99
+ }
100
+ function y(e) {
101
+ return new TextEncoder().encode(JSON.stringify(e)).length;
102
+ }
103
+ function b(e, t) {
104
+ return !t || t.length > o.replayChars || !c.test(t) || y(e) + t.length + 12 > o.bodyBytes - s ? !1 : (e.replay = t, !0);
105
+ }
106
+ // src/settings.ts
107
+ var x = {
108
+ color: "#B8F35C",
109
+ text: "Feedback",
110
+ position: "bottom-right",
111
+ types: {
112
+ problem: !0,
113
+ idea: !0,
114
+ general: !0,
115
+ accessibility: !1
116
+ },
117
+ rating: !0,
118
+ hidePaths: [],
119
+ smallOnMobile: !1,
120
+ hideButton: !1,
121
+ segment: !1,
122
+ wording: {
123
+ chooserTitle: "",
124
+ problemTitle: "",
125
+ ideaTitle: "",
126
+ generalTitle: "",
127
+ accessibilityTitle: "",
128
+ messagePlaceholder: "",
129
+ confirmation: ""
130
+ },
131
+ fields: [],
132
+ capture: {
133
+ console: !0,
134
+ network: !0
135
+ },
136
+ knownIssues: {
137
+ enabled: !0,
138
+ notify: !0
139
+ },
140
+ consent: { required: !1 },
141
+ privacyUrl: "",
142
+ identifyPrefill: !0
143
+ }, S = {
144
+ fields: 10,
145
+ label: 80,
146
+ options: 20,
147
+ option: 80,
148
+ text: 200
149
+ }, C = [
150
+ "bottom-right",
151
+ "bottom-left",
152
+ "right-edge"
153
+ ], w = Object.keys(x.wording), T = (e, t) => typeof e == "string" ? e.trim().slice(0, t) : "", E = (e, t) => typeof e == "boolean" ? e : t, D = [
154
+ "select",
155
+ "text",
156
+ "checkbox"
157
+ ];
158
+ function O(e) {
159
+ if (!Array.isArray(e)) return [];
160
+ let t = [], n = /* @__PURE__ */ new Set();
161
+ for (let r of e) {
162
+ if (!r || typeof r != "object") continue;
163
+ let e = r, i = typeof e.id == "string" ? e.id.slice(0, 40) : "", a = e.type, o = T(e.label, S.label);
164
+ if (!i || n.has(i) || !D.includes(a) || !o) continue;
165
+ let s = a === "select" && Array.isArray(e.options) ? [...new Set(e.options.map((e) => T(e, S.option)).filter(Boolean))].slice(0, S.options) : [];
166
+ if (a === "select" && !s.length) continue;
167
+ let c = e.types ?? {};
168
+ if (n.add(i), t.push({
169
+ id: i,
170
+ type: a,
171
+ label: o,
172
+ required: e.required === !0,
173
+ options: s,
174
+ types: {
175
+ problem: E(c.problem, !0),
176
+ idea: E(c.idea, !0),
177
+ general: E(c.general, !0)
178
+ }
179
+ }), t.length >= S.fields) break;
180
+ }
181
+ return t;
182
+ }
183
+ function k(e) {
184
+ let t = e ?? {}, n = x, r = t.types ?? {}, i = {
185
+ problem: E(r.problem, !0),
186
+ idea: E(r.idea, !0),
187
+ general: E(r.general, !0),
188
+ accessibility: E(r.accessibility, !1)
189
+ }, a = i.problem || i.idea || i.general || i.accessibility, o = t.wording ?? {}, s = { ...n.wording };
190
+ for (let e of w) s[e] = T(o[e], 120);
191
+ return {
192
+ color: typeof t.color == "string" ? t.color : n.color,
193
+ text: T(t.text, 40) || n.text,
194
+ position: C.includes(t.position) ? t.position : n.position,
195
+ types: a ? i : { ...n.types },
196
+ rating: E(t.rating, n.rating),
197
+ hidePaths: Array.isArray(t.hidePaths) ? t.hidePaths.filter((e) => typeof e == "string") : [],
198
+ smallOnMobile: E(t.smallOnMobile, n.smallOnMobile),
199
+ hideButton: E(t.hideButton, n.hideButton),
200
+ segment: E(t.segment, n.segment),
201
+ wording: s,
202
+ fields: O(t.fields),
203
+ capture: {
204
+ console: E(t.capture?.console, !0),
205
+ network: E(t.capture?.network, !0)
206
+ },
207
+ knownIssues: {
208
+ enabled: E(t.knownIssues?.enabled, !0),
209
+ notify: E(t.knownIssues?.notify, !0)
210
+ },
211
+ consent: { required: t.consent?.required === !0 },
212
+ privacyUrl: A(t.privacyUrl),
213
+ identifyPrefill: E(t.identifyPrefill, !0)
214
+ };
215
+ }
216
+ function A(e) {
217
+ let t = typeof e == "string" ? e.trim() : "";
218
+ try {
219
+ return t.length <= 500 && new URL(t).protocol === "https:" ? t : "";
220
+ } catch {
221
+ return "";
222
+ }
223
+ }
224
+ var j = /^#[0-9a-fA-F]{6}$/, M = (e) => typeof e == "string" && j.test(e) ? e : null;
225
+ function N(e) {
226
+ let t = e && typeof e == "object" ? e : {}, n = typeof t.logoUrl == "string" && /^https?:\/\//i.test(t.logoUrl) ? t.logoUrl.slice(0, 2e3) : null;
227
+ return {
228
+ poweredBy: t.poweredBy === !0,
229
+ logoUrl: n,
230
+ primary: M(t.primary),
231
+ accent: M(t.accent)
232
+ };
233
+ }
234
+ var P = (e) => typeof e == "number" && Number.isFinite(e) ? Math.min(1, Math.max(0, e)) : 0;
235
+ function F(e, t) {
236
+ let n = e && typeof e == "object" ? e : {}, r = typeof t == "number" ? P(t) : 1, i = Array.isArray(n.fixChecks) ? n.fixChecks : [];
237
+ return {
238
+ followUp: n.followUp === !0,
239
+ autoBlur: n.autoBlur === !0,
240
+ replay: n.replay === !0,
241
+ replaySampleRate: Math.min(n.replaySampleRate === void 0 ? 1 : P(n.replaySampleRate), r),
242
+ replayMask: n.replayMask === "inputs" ? "inputs" : "all",
243
+ fixChecks: i.filter((e) => !!e && typeof e.id == "string" && typeof e.path == "string" && typeof e.signature == "string"),
244
+ watches: I(n.watches),
245
+ fixCheckSampleRate: Math.min(P(n.fixCheckSampleRate), r)
246
+ };
247
+ }
248
+ function I(e) {
249
+ return (Array.isArray(e) ? e : []).filter((e) => !!e && typeof e.id == "string" && typeof e.signature == "string").slice(0, 50);
250
+ }
251
+ function L(e, t) {
252
+ if (!Array.isArray(e) || t?.enabled === !1) return [];
253
+ let n = [];
254
+ for (let t of e) {
255
+ if (!t || typeof t != "object") continue;
256
+ let e = t, r = typeof e.id == "string" ? e.id.slice(0, 64) : "", i = T(e.title, 120);
257
+ if (r && i && (n.push({
258
+ id: r,
259
+ title: i,
260
+ paths: (Array.isArray(e.paths) ? e.paths : []).filter((e) => typeof e == "string" && e[0] === "/").slice(0, 10),
261
+ signature: typeof e.signature == "string" && e.signature ? e.signature : null
262
+ }), n.length >= 20)) break;
263
+ }
264
+ return n;
265
+ }
266
+ // src/ui/color.ts
267
+ function R(e) {
268
+ let t = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e.trim());
269
+ if (!t) return null;
270
+ let n = t[1];
271
+ n.length === 3 && (n = [...n].map((e) => e + e).join(""));
272
+ let [r, i, a] = [
273
+ 0,
274
+ 2,
275
+ 4
276
+ ].map((e) => {
277
+ let t = Number.parseInt(n.slice(e, e + 2), 16) / 255;
278
+ return t <= .03928 ? t / 12.92 : ((t + .055) / 1.055) ** 2.4;
279
+ });
280
+ return .2126 * r + .7152 * i + .0722 * a;
281
+ }
282
+ function z(e, t) {
283
+ let [n, r] = e > t ? [e, t] : [t, e];
284
+ return (n + .05) / (r + .05);
285
+ }
286
+ function B(e) {
287
+ let t = R(e);
288
+ return t === null ? "#FFFFFF" : z(t, R("#0B1300")) >= z(t, 1) ? "#0B1300" : "#FFFFFF";
289
+ }
290
+ function V(e, t = "#B8F35C") {
291
+ return typeof e == "string" && R(e) !== null ? e.trim() : t;
292
+ }
293
+ // src/ui/dom.ts
294
+ function H(e, t = {}, ...n) {
295
+ let r = document.createElement(e);
296
+ for (let [e, n] of Object.entries(t)) n != null && n !== !1 && r.setAttribute(e, n === !0 ? "" : String(n));
297
+ for (let e of n) e != null && e !== !1 && r.append(e);
298
+ return r;
299
+ }
300
+ var U = "http://www.w3.org/2000/svg";
301
+ function W(e, t = 16) {
302
+ let n = document.createElementNS(U, "svg");
303
+ n.setAttribute("width", String(t)), n.setAttribute("height", String(t)), n.setAttribute("viewBox", "0 0 24 24"), n.setAttribute("fill", "none"), n.setAttribute("stroke", "currentColor"), n.setAttribute("stroke-width", "2.2"), n.setAttribute("stroke-linecap", "round"), n.setAttribute("stroke-linejoin", "round"), n.setAttribute("aria-hidden", "true");
304
+ let r = document.createElementNS(U, "path");
305
+ return r.setAttribute("d", e), n.append(r), n;
306
+ }
307
+ var G = {
308
+ close: "M18 6L6 18M6 6l12 12",
309
+ back: "M15 18l-6-6 6-6",
310
+ pen: "M12 20h9M16.5 3.5a2.1 2.1 0 013 3L7 19l-4 1 1-4z",
311
+ camera: "M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2zM12 17a4 4 0 100-8 4 4 0 000 8z",
312
+ trash: "M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6"
313
+ }, K = "\n $ .panel, $.pos-bottom-right .panel, $.pos-bottom-left .panel, $.pos-right-edge .panel { left: 0; right: 0; bottom: 0; width: 100%; max-width: none; max-height: 88vh; border-radius: 16px 16px 0 0; padding: 18px 16px calc(16px + env(safe-area-inset-bottom)); }\n $.open .launcher { display: none; }\n $ .field textarea, $ .field input, $ .field select { font-size: 16px; }\n $ .launcher { padding: 11px 16px; font-size: 14px; }\n $.pos-bottom-right .launcher { right: 16px; bottom: 16px; }\n $.pos-bottom-left .launcher { left: 16px; bottom: 16px; }\n $.small .launcher { padding: 8px 12px; font-size: 13px; box-shadow: 0 8px 20px -6px rgba(0,0,0,0.35); }\n $.small.pos-bottom-right .launcher { right: 12px; bottom: 12px; }\n $.small.pos-bottom-left .launcher { left: 12px; bottom: 12px; }\n $.small.pos-right-edge .launcher { padding: 8px 10px; }\n";
314
+ function q(e, t) {
315
+ let n = K.replace(/\$/g, t);
316
+ return e ? `${e}${n}}` : n;
317
+ }
318
+ var J = `
319
+ :host { all: initial; }
320
+ * { box-sizing: border-box; }
321
+ .pnx { font-family: Manrope, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; color: #111827; font-size: 14px; line-height: 1.4; -webkit-font-smoothing: antialiased; }
322
+ button { font: inherit; color: inherit; cursor: pointer; }
323
+ button:disabled { cursor: default; }
324
+ :focus-visible { outline: 3px solid #2E46BF; outline-offset: 2px; }
325
+ .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
326
+
327
+ .launcher { position: fixed; z-index: 2; border: 0; padding: 13px 20px; border-radius: 999px; font-weight: 700; font-size: 15px; line-height: 1.2; box-shadow: 0 12px 30px -8px rgba(0,0,0,0.35); background: var(--pnx-brand); color: var(--pnx-ink); transition: transform .15s ease; max-width: calc(100vw - 32px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
328
+ .launcher:hover { transform: translateY(-1px); }
329
+ .pos-bottom-right .launcher { right: 24px; bottom: 24px; }
330
+ .pos-bottom-left .launcher { left: 24px; bottom: 24px; }
331
+ .pos-right-edge .launcher { right: 0; top: 45%; border-radius: 10px 0 0 10px; }
332
+ .pos-right-edge .launcher:hover { transform: translateX(-2px); }
333
+ .pos-right-edge.open .launcher { visibility: hidden; }
334
+ .launcher[hidden] { display: none; }
335
+
336
+ .panel { position: fixed; z-index: 3; bottom: 84px; width: 300px; max-width: calc(100vw - 32px); max-height: calc(100vh - 108px); overflow: auto; padding: 18px; border-radius: 16px; background: #FFFFFF; color: #111827; box-shadow: 0 30px 60px -18px rgba(0,0,0,0.45), 0 0 0 1px rgba(17,24,39,0.06); display: flex; flex-direction: column; gap: 12px; }
337
+ .panel[hidden] { display: none; }
338
+ .pos-bottom-right .panel { right: 24px; }
339
+ .pos-bottom-left .panel { left: 24px; }
340
+ .pos-right-edge .panel { right: 24px; bottom: 24px; max-height: calc(100vh - 48px); }
341
+ .no-button .panel { bottom: 24px; max-height: calc(100vh - 48px); }
342
+
343
+ .head { display: flex; align-items: center; gap: 8px; }
344
+ .title { margin: 0; flex: 1; font-size: 15px; font-weight: 700; }
345
+ .icon-btn { flex: none; width: 32px; height: 32px; margin: -6px; border: 0; border-radius: 8px; background: transparent; color: #5B6474; display: inline-flex; align-items: center; justify-content: center; }
346
+ .icon-btn:hover { background: #F2F4F8; color: #111827; }
347
+ .head .icon-btn:first-child { margin-right: 0; }
348
+
349
+ .choices { display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 0; list-style: none; }
350
+ .choice { width: 100%; display: flex; align-items: center; gap: 10px; padding: 11px 12px; border: 0; border-radius: 10px; background: #F2F4F8; font-size: 14px; font-weight: 600; text-align: left; }
351
+ .choice:hover { background: #FFF1EC; box-shadow: inset 0 0 0 2px var(--dot); }
352
+ .dot { flex: none; width: 10px; height: 10px; border-radius: 50%; background: var(--dot); }
353
+ .choice small { display: block; font-size: 12px; font-weight: 500; color: #5B6474; }
354
+
355
+ .shot { position: relative; border-radius: 10px; background: #F4EDE2; overflow: hidden; min-height: 72px; display: flex; align-items: center; justify-content: center; }
356
+ .shot img { display: block; width: 100%; height: auto; max-height: 160px; object-fit: contain; background: #F2F4F8; }
357
+ .shot .tag { position: absolute; right: 8px; top: 8px; padding: 3px 7px; border-radius: 6px; background: #111827; color: #FFFFFF; font-size: 11px; font-weight: 700; }
358
+ .shot .wait { font-size: 13px; color: #5B6474; padding: 20px; }
359
+ .shot-actions { display: flex; gap: 8px; flex-wrap: wrap; }
360
+ .chip { display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 7px 11px; border: 0; border-radius: 8px; background: #F2F4F8; color: #111827; font-size: 13px; font-weight: 700; }
361
+ .chip:hover { background: #E3E8F0; }
362
+ .chip.primary { background: #111827; color: #FFFFFF; }
363
+ .chip.primary:hover { background: #1F2937; }
364
+
365
+ .field { display: flex; flex-direction: column; gap: 6px; }
366
+ .field label, .legend { font-size: 12px; font-weight: 600; color: #5B6474; }
367
+ .field textarea, .field input { width: 100%; border: 0; border-radius: 10px; padding: 11px 12px; background: #F2F4F8; color: #111827; font: inherit; font-size: 14px; line-height: 1.5; box-shadow: inset 0 0 0 1px transparent; }
368
+ .field textarea { min-height: 84px; resize: vertical; }
369
+ .field textarea::placeholder, .field input::placeholder { color: #5B6474; opacity: 1; }
370
+ .field textarea:focus, .field input:focus { outline: none; box-shadow: inset 0 0 0 2px #2E46BF; background: #FFFFFF; }
371
+ .field .hint { font-size: 12px; color: #5B6474; }
372
+ .field select { width: 100%; border: 0; border-radius: 10px; padding: 11px 12px; background: #F2F4F8; color: #111827; font: inherit; font-size: 14px; line-height: 1.5; }
373
+ .field select:focus { outline: none; box-shadow: inset 0 0 0 2px #2E46BF; background: #FFFFFF; }
374
+ .field [aria-invalid="true"] { box-shadow: inset 0 0 0 2px #B42318; }
375
+ .field .optional { font-weight: 500; }
376
+ .field.check { flex-direction: row; align-items: flex-start; gap: 10px; }
377
+ .field.check input { flex: none; width: 20px; height: 20px; margin: 0; padding: 0; accent-color: #2E46BF; box-shadow: none; }
378
+ .field.check label { font-size: 13px; color: #111827; font-weight: 600; line-height: 1.45; }
379
+ .field.check input[aria-invalid="true"] { outline: 2px solid #B42318; outline-offset: 2px; }
380
+ .a11y-note { margin: 0; font-size: 13px; line-height: 1.45; color: #374151; }
381
+ fieldset.barriers { border: 0; margin: 0; padding: 0; min-width: 0; gap: 2px; }
382
+ fieldset.barriers legend { padding: 0; margin-bottom: 4px; }
383
+ .radio { display: flex; align-items: center; gap: 10px; min-height: 36px; padding: 0 8px; border-radius: 8px; }
384
+ .radio:hover { background: #F2F4F8; }
385
+ .field .radio input, .field .radio input:focus { flex: none; width: 20px; height: 20px; margin: 0; padding: 0; border-radius: 50%; background: none; accent-color: #0F766E; box-shadow: none; }
386
+ .radio input:focus-visible { outline: 2px solid #2E46BF; outline-offset: 2px; }
387
+ .radio label { flex: 1; font-size: 14px; color: #111827; font-weight: 500; line-height: 1.35; padding: 8px 0; cursor: pointer; }
388
+ .brand { display: flex; align-items: center; min-height: 28px; }
389
+ .brand .logo { display: block; max-height: 32px; max-width: 160px; width: auto; height: auto; object-fit: contain; }
390
+ .accented .panel { border-top: 4px solid var(--pnx-accent); }
391
+ .accented .choice:hover { box-shadow: inset 0 0 0 2px var(--pnx-accent); }
392
+ .accented .tick { background: var(--pnx-accent); color: var(--pnx-accent-ink); }
393
+
394
+ .stars { display: flex; gap: 4px; border: 0; margin: 0; padding: 0; }
395
+ .star { width: 40px; height: 40px; border: 0; border-radius: 10px; font-size: 24px; line-height: 1; background: #F2F4F8; color: #6B7280; }
396
+ .star.on { background: #FFF6DF; color: #B9800F; }
397
+
398
+ .error { margin: 0; font-size: 13px; color: #B42318; font-weight: 600; }
399
+ .error:empty { display: none; }
400
+ .send { width: 100%; padding: 12px; border: 0; border-radius: 10px; font-size: 14px; font-weight: 800; background: var(--type); color: var(--type-ink); }
401
+ .send:disabled { opacity: .7; }
402
+ .powered { font-size: 11px; color: #5B6474; text-align: center; }
403
+ .powered a { color: inherit; text-decoration: none; }
404
+ .powered a:hover { text-decoration: underline; }
405
+
406
+ .done { text-align: center; padding: 18px 0 6px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
407
+ .tick { width: 46px; height: 46px; border-radius: 50%; background: #B8F35C; color: #0B1300; font-size: 22px; font-weight: 800; display: flex; align-items: center; justify-content: center; }
408
+ .done p { margin: 0; font-size: 13px; color: #5B6474; }
409
+ .link { border: 0; background: transparent; color: #5B6474; font-size: 13px; font-weight: 700; padding: 6px 8px; border-radius: 6px; }
410
+ .link:hover { color: #111827; }
411
+
412
+ .note { display: flex; align-items: baseline; gap: 8px; padding: 10px 12px; border-radius: 10px; background: #F2F4F8; color: #5B6474; font-size: 13px; line-height: 1.45; overflow-wrap: anywhere; }
413
+ .note .dot { transform: translateY(-1px); }
414
+ .field label.question { font-size: 14px; font-weight: 700; color: #111827; line-height: 1.4; }
415
+ .field textarea.answer { min-height: 64px; }
416
+ .skip { width: 100%; padding: 8px; text-align: center; }
417
+ .skip:disabled, .send:disabled + .skip { opacity: .7; }
418
+
419
+ .known { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }
420
+ .known > li { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding: 12px; border-radius: 10px; background: #F2F4F8; }
421
+ .known-title { margin: 0; font-size: 14px; font-weight: 700; color: #111827; overflow-wrap: anywhere; }
422
+ .known-thanks { margin: 0; font-size: 13px; font-weight: 600; color: #374151; }
423
+ .known .field { align-self: stretch; }
424
+ .known .field input { background: #FFFFFF; box-shadow: inset 0 0 0 1px #6B7280; }
425
+ .known .field input:focus { box-shadow: inset 0 0 0 2px #2E46BF; }
426
+ .known .field [aria-invalid="true"] { box-shadow: inset 0 0 0 2px #B42318; }
427
+ .subtitle { margin: 4px 0 0; font-size: 13px; font-weight: 700; color: #5B6474; }
428
+ .privacy { display: flex; flex-direction: column; gap: 10px; }
429
+ .notice { margin: 0; font-size: 12px; line-height: 1.45; color: #5B6474; overflow-wrap: anywhere; }
430
+ .notice a { color: #2E46BF; font-weight: 700; text-decoration: underline; }
431
+ .notice a:hover { color: #111827; }
432
+ .hint.auto-blur { display: flex; align-items: center; gap: 6px; }
433
+ .hint.auto-blur i { flex: none; width: 16px; height: 10px; border-radius: 3px; background: repeating-linear-gradient(90deg, #D8DEE9 0 4px, #C7CFDC 4px 8px); box-shadow: 0 0 0 1px #C7CFDC; }
434
+
435
+ ${q("@media (max-width: 520px) {", ".pnx")}
436
+ @media (prefers-reduced-motion: reduce) { * { transition: none !important; } }
437
+ @media (forced-colors: active) { .launcher, .choice, .send, .chip, .star { border: 1px solid ButtonText; } .known > li { border: 1px solid CanvasText; } }
438
+ `, Y = [
439
+ {
440
+ type: "PROBLEM",
441
+ key: "problem",
442
+ label: "Report a problem",
443
+ desc: "Point at what is broken",
444
+ dot: "#FF5C35",
445
+ send: "#CC3F1B",
446
+ ink: "#FFFFFF"
447
+ },
448
+ {
449
+ type: "IDEA",
450
+ key: "idea",
451
+ label: "Share an idea",
452
+ desc: "Suggest something better",
453
+ dot: "#7C9CFF",
454
+ send: "#7C9CFF",
455
+ ink: "#0B1122"
456
+ },
457
+ {
458
+ type: "GENERAL",
459
+ key: "general",
460
+ label: "General feedback",
461
+ desc: "A rating and a few words",
462
+ dot: "#3DBF6E",
463
+ send: "#3DBF6E",
464
+ ink: "#0B1300"
465
+ },
466
+ {
467
+ type: "ACCESSIBILITY",
468
+ key: "accessibility",
469
+ label: "Report an accessibility barrier",
470
+ desc: "Something you can't see, reach or use",
471
+ dot: "#2FB8AC",
472
+ send: "#0F766E",
473
+ ink: "#FFFFFF"
474
+ }
475
+ ], X = [
476
+ ["see", "Hard to see or read"],
477
+ ["keyboard", "Can't use it with a keyboard"],
478
+ ["screen-reader", "Doesn't work with my screen reader"],
479
+ ["media", "Video or audio"],
480
+ ["other", "Something else"]
481
+ ], Z = 4e3, Q = "What would you like to do?", $ = "Thanks! We've got it.", ee = {
482
+ problem: "problemTitle",
483
+ idea: "ideaTitle",
484
+ general: "generalTitle",
485
+ accessibility: "accessibilityTitle"
486
+ }, te = class {
487
+ constructor(e, t, n, r = {}) {
488
+ this.root = e, this.config = t, this.handlers = n, this.kind = null, this.shot = { kind: "none" }, this.message = "", this.email = "", this.emailEdited = !1, this.answers = {}, this.sendColour = null, this.sending = !1, this.openedAt = 0, this.hp = "", this.uid = Math.random().toString(36).slice(2, 8), this.pathHidden = !1, this.returnFocus = null, this.known = [], this.knownHidden = /* @__PURE__ */ new Set(), this.meToo = {}, this.includeLogs = !1, this.privacy = null, this.noticeText = null, this.shown = {
489
+ logs: !0,
490
+ askLogs: !1,
491
+ replay: !1
492
+ }, this.view = "choose", this.queued = !1, this.asked = null, this.answer = "";
493
+ let i = t.settings, a = t.branding?.primary ? V(t.branding.primary, "") : "", o = t.branding?.accent ? V(t.branding.accent, "") : "", s = a || V(i.color);
494
+ this.sendColour = a || null;
495
+ let c = (e) => e.key === "accessibility" ? i.types?.accessibility === !0 : i.types?.[e.key] !== !1;
496
+ this.kinds = Y.filter(c), this.kinds.length || (this.kinds = Y.slice(0, 3));
497
+ let l = H("style");
498
+ l.textContent = r.css ? J + r.css : J, this.launcher = H("button", {
499
+ type: "button",
500
+ class: "launcher",
501
+ "aria-haspopup": "dialog",
502
+ "aria-expanded": "false",
503
+ "aria-controls": `pnx-panel-${this.uid}`
504
+ }, (i.text || "Feedback").slice(0, 40)), this.launcher.addEventListener("click", () => this.isOpen() ? this.close() : this.open()), this.panel = H("div", {
505
+ class: "panel",
506
+ id: `pnx-panel-${this.uid}`,
507
+ role: "dialog",
508
+ "aria-modal": "false",
509
+ "aria-labelledby": `pnx-title-${this.uid}`,
510
+ hidden: !0
511
+ }), this.panel.addEventListener("keydown", (e) => {
512
+ e.key === "Escape" && (e.stopPropagation(), this.close());
513
+ }), this.panel.addEventListener("pointerdown", () => this.holdOpen()), this.panel.addEventListener("focusin", () => this.holdOpen()), this.live = H("div", {
514
+ class: "sr",
515
+ role: "status",
516
+ "aria-live": "polite"
517
+ });
518
+ let u = [
519
+ "bottom-right",
520
+ "bottom-left",
521
+ "right-edge"
522
+ ].includes(i.position) ? i.position : "bottom-right";
523
+ this.wrap = H("div", { class: `pnx pos-${u}${r.className ? ` ${r.className}` : ""}` }), i.smallOnMobile && this.wrap.classList.add("small"), this.updateButton(), this.wrap.style.setProperty("--pnx-brand", s), this.wrap.style.setProperty("--pnx-ink", B(s)), o && (this.wrap.classList.add("accented"), this.wrap.style.setProperty("--pnx-accent", o), this.wrap.style.setProperty("--pnx-accent-ink", B(o))), this.wrap.append(this.launcher, this.panel, this.live), e.append(l, this.wrap);
524
+ }
525
+ isOpen() {
526
+ return !this.panel.hidden;
527
+ }
528
+ hasButton() {
529
+ return !this.launcher.hidden;
530
+ }
531
+ setPathHidden(e) {
532
+ this.pathHidden = e, this.updateButton();
533
+ }
534
+ updateButton() {
535
+ let e = this.config.settings.hideButton || this.pathHidden;
536
+ this.launcher.hidden = e, this.wrap.classList.toggle("no-button", e);
537
+ }
538
+ open(e = !0) {
539
+ if (this.isOpen()) {
540
+ e && this.focusFirst();
541
+ return;
542
+ }
543
+ let t = document.activeElement;
544
+ this.returnFocus = t instanceof HTMLElement && t !== this.root.host ? t : null, this.openedAt || (this.openedAt = Date.now()), (this.view === "choose" || this.kinds.length === 1 && this.view === "form" && !this.message.trim()) && this.offerKnown(), this.panel.hidden = !1, this.wrap.classList.add("open"), this.launcher.setAttribute("aria-expanded", "true"), !this.kind && this.kinds.length === 1 && !this.knownShown().length && this.pick(this.kinds[0], !1), this.render(), e && this.focusFirst();
545
+ try {
546
+ this.handlers.opened?.();
547
+ } catch {}
548
+ }
549
+ close(e = !0) {
550
+ clearTimeout(this.closeTimer), this.isOpen() && (this.panel.hidden = !0, this.wrap.classList.remove("open"), this.launcher.setAttribute("aria-expanded", "false"), this.view === "done" && this.reset(), e && (this.hasButton() ? this.launcher.focus() : this.returnFocus?.isConnected && this.returnFocus.focus(), this.returnFocus = null));
551
+ }
552
+ currentView() {
553
+ return this.isOpen() ? this.view === "done" ? "done" : (this.view === "form" || this.view === "question") && this.kind ? this.kind.key : "choose" : "button";
554
+ }
555
+ showView(e) {
556
+ if (clearTimeout(this.closeTimer), e === "button") this.close(!1);
557
+ else {
558
+ if (this.reset(), this.knownHidden.clear(), this.meToo = {}, e === "choose" && this.offerKnown(), e === "done") this.view = "done";
559
+ else if (e !== "choose") {
560
+ let t = this.kinds.find((t) => t.key === e);
561
+ t && this.pick(t, !1);
562
+ }
563
+ this.isOpen() ? this.render() : this.open(!1);
564
+ }
565
+ }
566
+ word(e, t) {
567
+ return this.config.settings.wording?.[e]?.trim() || t;
568
+ }
569
+ kindTitle(e, t = e.label) {
570
+ return this.word(ee[e.key], t);
571
+ }
572
+ setSuspended(e) {
573
+ this.wrap.style.display = e ? "none" : "";
574
+ }
575
+ destroy() {
576
+ clearTimeout(this.closeTimer), this.wrap.remove();
577
+ }
578
+ reset() {
579
+ this.view = "choose", this.kind = null, this.shot = { kind: "none" }, this.message = "", this.rating = void 0, this.barrier = void 0, this.answers = {}, this.includeLogs = !1, this.queued = !1, this.asked = null, this.answer = "", this.openedAt = this.isOpen() ? Date.now() : 0, this.hp = "", this.kinds.length === 1 && this.pick(this.kinds[0], !1);
580
+ }
581
+ holdOpen() {
582
+ clearTimeout(this.closeTimer);
583
+ }
584
+ focusFirst() {
585
+ for (let e of [
586
+ "[data-autofocus]",
587
+ ".choice",
588
+ "textarea",
589
+ "button"
590
+ ]) {
591
+ let t = this.panel.querySelector(e);
592
+ if (t) {
593
+ t.focus();
594
+ return;
595
+ }
596
+ }
597
+ }
598
+ announce(e) {
599
+ this.live.textContent = "", setTimeout(() => {
600
+ this.live.textContent = e;
601
+ }, 30);
602
+ }
603
+ pick(e, t = !0) {
604
+ this.kind = e, this.view = "form", this.rating = void 0, !this.email && !this.emailEdited && this.config.settings.identifyPrefill !== !1 && (this.email = this.handlers.user()?.email || ""), e.type === "PROBLEM" && this.shot.kind === "none" && this.capture(), e.type !== "PROBLEM" && this.shot.kind === "busy" && (this.shot = { kind: "none" }), t && (this.render(), this.focusFirst());
605
+ }
606
+ async capture() {
607
+ this.shot = { kind: "busy" }, this.render();
608
+ try {
609
+ let e = await this.handlers.takeScreenshot();
610
+ if (this.shot.kind !== "busy") return;
611
+ this.shot = {
612
+ kind: "ready",
613
+ shot: e
614
+ }, this.announce("Screenshot added.");
615
+ } catch {
616
+ if (this.shot.kind !== "busy") return;
617
+ this.shot = { kind: "failed" }, this.announce("Couldn't take a screenshot.");
618
+ }
619
+ this.renderKeepingFocus();
620
+ }
621
+ async markUp() {
622
+ if (this.shot.kind === "ready") {
623
+ this.setSuspended(!0);
624
+ try {
625
+ let e = await this.handlers.markUp(this.shot.shot);
626
+ e && (this.shot = {
627
+ kind: "ready",
628
+ shot: e
629
+ }, this.announce(e.annotations.length ? `Screenshot marked up with ${e.annotations.length} ${e.annotations.length === 1 ? "mark" : "marks"}.` : "Screenshot updated."));
630
+ } catch {} finally {
631
+ this.setSuspended(!1), this.render(), this.panel.querySelector("[data-markup]")?.focus();
632
+ }
633
+ }
634
+ }
635
+ renderKeepingFocus() {
636
+ let e = this.root.activeElement, t = e?.dataset?.key, n = e?.tagName === "TEXTAREA" ? [e.selectionStart, e.selectionEnd] : null;
637
+ if (this.render(), t) {
638
+ let e = this.panel.querySelector(`[data-key="${t}"]`);
639
+ e?.focus(), n && e instanceof HTMLTextAreaElement && e.setSelectionRange(n[0], n[1]);
640
+ }
641
+ }
642
+ header(e, t, n) {
643
+ let r = H("div", { class: "head" });
644
+ if (t) {
645
+ let e = H("button", {
646
+ type: "button",
647
+ class: "icon-btn",
648
+ "aria-label": "Back",
649
+ "data-key": "back"
650
+ });
651
+ e.append(W(G.back)), e.addEventListener("click", () => {
652
+ n ? n() : (this.view = "choose", this.kind = null, this.render(), this.focusFirst());
653
+ }), r.append(e);
654
+ }
655
+ r.append(H("h2", {
656
+ class: "title",
657
+ id: `pnx-title-${this.uid}`
658
+ }, e));
659
+ let i = H("button", {
660
+ type: "button",
661
+ class: "icon-btn",
662
+ "aria-label": "Close feedback",
663
+ "data-key": "close"
664
+ });
665
+ return i.append(W(G.close)), i.addEventListener("click", () => this.close()), r.append(i), r;
666
+ }
667
+ powered() {
668
+ return this.config.branding?.poweredBy ? H("div", { class: "powered" }, H("a", {
669
+ href: "https://getpinax.com",
670
+ target: "_blank",
671
+ rel: "noopener"
672
+ }, "Powered by Pinax")) : null;
673
+ }
674
+ logo() {
675
+ let e = this.config.branding?.logoUrl;
676
+ if (!e || !/^https?:\/\//i.test(e)) return null;
677
+ let t = H("img", {
678
+ src: e,
679
+ alt: "",
680
+ class: "logo",
681
+ referrerpolicy: "no-referrer"
682
+ });
683
+ return t.addEventListener("error", () => t.remove()), H("div", { class: "brand" }, t);
684
+ }
685
+ render() {
686
+ let e = [], t = this.logo();
687
+ t && e.push(t), this.view === "done" ? e.push(...this.renderDone()) : this.view === "question" && this.kind && this.asked?.question ? e.push(...this.renderQuestion(this.kind, this.asked.question)) : this.view === "form" && this.kind ? e.push(...this.renderForm(this.kind)) : e.push(...this.renderChoose());
688
+ let n = this.powered();
689
+ n && e.push(n), this.panel.replaceChildren(...e);
690
+ }
691
+ renderChoose() {
692
+ let e = this.knownShown(), t = this.word("chooserTitle", Q), n = H("ul", { class: "choices" });
693
+ for (let e of this.kinds) {
694
+ let t = H("button", {
695
+ type: "button",
696
+ class: "choice"
697
+ }, H("span", {
698
+ class: "dot",
699
+ "aria-hidden": "true"
700
+ }), H("span", {}, this.kindTitle(e), H("small", {}, e.desc)));
701
+ t.style.setProperty("--dot", e.dot), t.addEventListener("click", () => this.pick(e)), n.append(H("li", {}, t));
702
+ }
703
+ return e.length ? [
704
+ this.header("We know about this", !1),
705
+ ...this.renderKnown(e),
706
+ H("h3", { class: "subtitle" }, t),
707
+ n
708
+ ] : [this.header(t, !1), n];
709
+ }
710
+ knownShown() {
711
+ return this.config.settings.knownIssues?.enabled === !1 ? [] : this.known.filter((e) => !this.knownHidden.has(e.id));
712
+ }
713
+ offerKnown() {
714
+ try {
715
+ this.known = this.handlers.knownIssues?.().slice(0, 3) ?? [];
716
+ } catch {
717
+ this.known = [];
718
+ }
719
+ this.knownShown().length && (this.view = "choose", this.kind = null);
720
+ }
721
+ renderKnown(e) {
722
+ let t = this.config.settings.knownIssues?.notify !== !1, n = H("ul", { class: "known" }), r = !0;
723
+ e.forEach((e, i) => {
724
+ let a = this.meToo[e.id], o = `pnx-k${i}-${this.uid}`, s = H("p", {
725
+ class: "error",
726
+ role: "alert",
727
+ id: `pnx-k${i}-err-${this.uid}`
728
+ }), c = H("li", {}, H("p", {
729
+ class: "known-title",
730
+ id: o
731
+ }, e.title));
732
+ if (!a || a === "busy") {
733
+ let t = H("button", {
734
+ type: "button",
735
+ class: "chip primary",
736
+ "aria-describedby": o,
737
+ "data-key": `metoo-${i}`,
738
+ "data-autofocus": r || void 0,
739
+ disabled: a === "busy"
740
+ }, "Me too");
741
+ r = !1, t.addEventListener("click", () => this.sendMeToo(e, i, s)), c.append(t, s);
742
+ } else if (a === "emailed" || !t) c.append(H("p", { class: "known-thanks" }, a === "emailed" ? "Thanks. We'll email you when it's fixed." : "Thanks, we've added you."));
743
+ else {
744
+ let t = `pnx-k${i}-email-${this.uid}`, n = `${t}-hint`, r = H("input", {
745
+ id: t,
746
+ type: "email",
747
+ inputmode: "email",
748
+ autocomplete: "email",
749
+ maxlength: 254,
750
+ "aria-describedby": n,
751
+ "data-key": `known-email-${i}`,
752
+ placeholder: "you@example.com"
753
+ });
754
+ r.value = this.email, r.addEventListener("input", () => {
755
+ this.email = r.value, this.emailEdited = !0;
756
+ });
757
+ let o = H("button", {
758
+ type: "button",
759
+ class: "chip primary",
760
+ "data-key": `known-send-${i}`,
761
+ disabled: a === "sending"
762
+ }, a === "sending" ? "Sending…" : "Send");
763
+ o.addEventListener("click", () => this.sendMeToo(e, i, s, r)), c.append(H("p", { class: "known-thanks" }, "Thanks, we've added you."), H("div", { class: "field" }, H("label", { for: t }, "Email me when it's fixed"), r, H("span", {
764
+ class: "hint",
765
+ id: n
766
+ }, "Only used to tell you when it's fixed.")), s, o);
767
+ }
768
+ n.append(c);
769
+ });
770
+ let i = H("button", {
771
+ type: "button",
772
+ class: "link",
773
+ "data-key": "known-else"
774
+ }, "Report something else");
775
+ return i.addEventListener("click", () => {
776
+ for (let t of e) this.knownHidden.add(t.id);
777
+ this.kinds.length === 1 ? this.pick(this.kinds[0]) : (this.render(), this.panel.querySelector(".choice")?.focus());
778
+ }), [n, i];
779
+ }
780
+ async sendMeToo(e, t, n, r) {
781
+ let i = this.meToo[e.id];
782
+ if (i === "busy" || i === "sending") return;
783
+ n.textContent = "";
784
+ let a = r ? this.email.trim() : void 0;
785
+ if (r && (!a || !d(a))) {
786
+ n.textContent = "Please check your email address.", r.setAttribute("aria-invalid", "true"), r.setAttribute("aria-errormessage", n.id), r.focus();
787
+ return;
788
+ }
789
+ this.meToo[e.id] = r ? "sending" : "busy", this.renderKeepingFocus();
790
+ let o = !1;
791
+ try {
792
+ o = await this.handlers.meToo?.(e.id, a) ?? !1;
793
+ } catch {
794
+ o = !1;
795
+ }
796
+ if (o || r ? this.meToo[e.id] = o && r ? "emailed" : "done" : delete this.meToo[e.id], !this.isOpen() || this.view !== "choose") return;
797
+ this.render();
798
+ let s = (e) => this.panel.querySelector(`[data-key="${e}"]`);
799
+ if (o) (s(`known-email-${t}`) ?? s("known-else"))?.focus(), this.announce(r ? "Thanks. We'll email you when it's fixed." : "Thanks, we've added you.");
800
+ else {
801
+ let e = this.panel.querySelector(`#pnx-k${t}-err-${this.uid}`);
802
+ e && (e.textContent = "Something went wrong. Please try again."), s(r ? `known-send-${t}` : `metoo-${t}`)?.focus();
803
+ }
804
+ }
805
+ renderShot(e) {
806
+ let t = this.shot;
807
+ if (t.kind === "none") {
808
+ if (e.type === "GENERAL") return null;
809
+ let t = H("button", {
810
+ type: "button",
811
+ class: "chip",
812
+ "data-key": "add-shot"
813
+ }, W(G.camera), "Add a screenshot");
814
+ return t.addEventListener("click", () => this.capture()), H("div", { class: "shot-actions" }, t);
815
+ }
816
+ if (t.kind === "busy") return H("div", {
817
+ class: "shot",
818
+ "aria-busy": "true"
819
+ }, H("span", { class: "wait" }, "Taking a screenshot…"));
820
+ if (t.kind === "failed") {
821
+ let e = H("button", {
822
+ type: "button",
823
+ class: "chip",
824
+ "data-key": "retry-shot"
825
+ }, "Try again");
826
+ return e.addEventListener("click", () => this.capture()), H("div", { class: "field" }, H("span", { class: "hint" }, "Couldn't take a screenshot of this page."), H("div", { class: "shot-actions" }, e));
827
+ }
828
+ let n = t.shot.annotations.length, r = t.shot.autoBlurred ?? 0, i = H("img", {
829
+ src: t.shot.dataUrl,
830
+ alt: `Screenshot of this page${n ? ` with ${n} ${n === 1 ? "mark" : "marks"}` : ""}${r ? `, ${r} private ${r === 1 ? "detail" : "details"} blurred` : ""}`
831
+ }), a = H("button", {
832
+ type: "button",
833
+ class: "chip primary",
834
+ "data-markup": !0,
835
+ "data-key": "markup"
836
+ }, W(G.pen), n ? "Edit marks" : "Mark up");
837
+ a.addEventListener("click", () => this.markUp());
838
+ let o = H("button", {
839
+ type: "button",
840
+ class: "chip",
841
+ "data-key": "remove-shot"
842
+ }, W(G.trash), "Remove", H("span", { class: "sr" }, " screenshot"));
843
+ return o.addEventListener("click", () => {
844
+ this.shot = { kind: "none" }, this.announce("Screenshot removed."), this.render(), this.panel.querySelector("[data-key=\"add-shot\"]")?.focus();
845
+ }), H("div", { class: "field" }, H("div", { class: "shot" }, i, H("span", {
846
+ class: "tag",
847
+ "aria-hidden": "true"
848
+ }, "Screenshot")), H("div", { class: "shot-actions" }, a, o), r ? H("span", { class: "hint auto-blur" }, H("i", { "aria-hidden": "true" }), `We blurred ${r === 1 ? "1 private detail" : `${r} private details`} for you.`) : null);
849
+ }
850
+ renderStars() {
851
+ let e = H("div", {
852
+ class: "stars",
853
+ role: "radiogroup",
854
+ "aria-labelledby": `pnx-rate-${this.uid}`
855
+ }), t = [], n = (this.rating ?? 1) - 1;
856
+ for (let e = 1; e <= 5; e++) {
857
+ let r = H("button", {
858
+ type: "button",
859
+ class: this.rating !== void 0 && e <= this.rating ? "star on" : "star",
860
+ role: "radio",
861
+ "aria-checked": this.rating === e ? "true" : "false",
862
+ "aria-label": `${e} ${e === 1 ? "star" : "stars"}`,
863
+ tabindex: e - 1 === n ? 0 : -1,
864
+ "data-key": `star-${e}`
865
+ }, "★");
866
+ r.addEventListener("click", () => {
867
+ this.rating = this.rating === e ? void 0 : e, this.renderKeepingFocus();
868
+ }), r.addEventListener("keydown", (e) => {
869
+ let t = e.key === "ArrowRight" || e.key === "ArrowUp" ? 1 : e.key === "ArrowLeft" || e.key === "ArrowDown" ? -1 : 0;
870
+ if (!t) return;
871
+ e.preventDefault();
872
+ let n = Math.min(5, Math.max(1, (this.rating ?? 0) + t || 1));
873
+ this.rating = n, this.render(), this.panel.querySelector(`[data-key="star-${n}"]`)?.focus();
874
+ }), t.push(r);
875
+ }
876
+ return e.append(...t), H("div", { class: "field" }, H("span", {
877
+ class: "legend",
878
+ id: `pnx-rate-${this.uid}`
879
+ }, "How's your visit so far? (optional)"), e);
880
+ }
881
+ renderForm(e) {
882
+ if (e.type === "ACCESSIBILITY") return this.renderAccessibility(e);
883
+ let t = e.type === "GENERAL" && this.config.settings.rating !== !1, n = this.kindTitle(e, t ? "How was your visit?" : e.label), r = [this.header(n, this.kinds.length > 1)], i = this.renderShot(e);
884
+ i && r.push(i), t && r.push(this.renderStars());
885
+ let a = `pnx-msg-${this.uid}`, o = H("textarea", {
886
+ id: a,
887
+ maxlength: 5e3,
888
+ "data-key": "message",
889
+ "data-autofocus": e.type !== "PROBLEM" && !t || void 0,
890
+ placeholder: this.word("messagePlaceholder", e.type === "PROBLEM" ? "What happened?" : e.type === "IDEA" ? "What would make this better?" : "Tell us what you think")
891
+ });
892
+ return o.value = this.message, o.addEventListener("input", () => {
893
+ this.message = o.value;
894
+ }), r.push(H("div", { class: "field" }, H("label", { for: a }, e.type === "PROBLEM" ? "What went wrong?" : e.type === "IDEA" ? "Your idea" : "Anything to add?"), o)), r.push(...this.renderFields(e)), r.push(...this.renderEmailAndSend(e, o, e.type === "PROBLEM" ? "Only used to tell you about this report." : "Only used to reply to you about this.")), r;
895
+ }
896
+ renderEmailAndSend(e, t, n) {
897
+ let r = [], i = `pnx-email-${this.uid}`, a = `pnx-email-hint-${this.uid}`, o = H("input", {
898
+ id: i,
899
+ type: "email",
900
+ inputmode: "email",
901
+ autocomplete: "email",
902
+ maxlength: 320,
903
+ "aria-describedby": a,
904
+ "data-key": "email",
905
+ placeholder: "you@example.com"
906
+ });
907
+ o.value = this.email, o.addEventListener("input", () => {
908
+ this.email = o.value, this.emailEdited = !0;
909
+ }), r.push(H("div", { class: "field" }, H("label", { for: i }, "Your email (optional)"), o, H("span", {
910
+ class: "hint",
911
+ id: a
912
+ }, n)));
913
+ let s = H("p", {
914
+ class: "error",
915
+ role: "alert",
916
+ id: `pnx-err-${this.uid}`
917
+ }), c = H("button", {
918
+ type: "button",
919
+ class: "send",
920
+ "data-key": "send",
921
+ "aria-describedby": `pnx-notice-${this.uid}`,
922
+ disabled: this.sending
923
+ }, this.sending ? "Sending…" : "Send");
924
+ return this.colourSend(c, e), c.addEventListener("click", () => this.send(e, s, o, t)), r.push(this.renderPrivacy(), this.honeypot(), s, c), r;
925
+ }
926
+ attachments() {
927
+ try {
928
+ return this.handlers.attachments?.() ?? {
929
+ logs: !0,
930
+ askLogs: !1,
931
+ replay: !1
932
+ };
933
+ } catch {
934
+ return {
935
+ logs: !1,
936
+ askLogs: !1,
937
+ replay: !1
938
+ };
939
+ }
940
+ }
941
+ renderPrivacy() {
942
+ let e = this.attachments();
943
+ this.shown = e;
944
+ let t = H("div", { class: "privacy" });
945
+ if (e.askLogs) {
946
+ let e = `pnx-logs-${this.uid}`, n = H("input", {
947
+ id: e,
948
+ type: "checkbox",
949
+ "data-key": "include-logs"
950
+ });
951
+ n.checked = this.includeLogs, n.addEventListener("change", () => {
952
+ this.includeLogs = n.checked, this.updateNotice();
953
+ }), t.append(H("div", { class: "field check" }, n, H("label", { for: e }, "Include technical details (console messages and failed requests) to help fix this")));
954
+ }
955
+ this.noticeText = H("span", {});
956
+ let n = H("p", {
957
+ class: "notice",
958
+ id: `pnx-notice-${this.uid}`
959
+ }, this.noticeText), r = this.config.settings.privacyUrl;
960
+ return r && /^https:\/\//i.test(r) && n.append(" ", H("a", {
961
+ href: r,
962
+ target: "_blank",
963
+ rel: "noopener noreferrer"
964
+ }, "Privacy policy", H("span", { class: "sr" }, " (opens in a new tab)"))), t.append(n), this.privacy = t, this.updateNotice(), t;
965
+ }
966
+ updateNotice() {
967
+ if (!this.noticeText) return;
968
+ let e = this.shown, t = ["the page address", "your browser details"];
969
+ this.shot.kind === "ready" && t.push("the screenshot"), (e.logs || e.askLogs && this.includeLogs) && t.push("technical logs"), e.replay && t.push("a recording of the last 30 seconds");
970
+ let n = "";
971
+ try {
972
+ n = this.handlers.site?.() ?? "";
973
+ } catch {}
974
+ n = n || location.hostname.replace(/^www\./, "") || "this website", this.noticeText.textContent = `Sent to ${n} with your note: ${t.join(", ")}.`;
975
+ }
976
+ refresh() {
977
+ let e = this.privacy;
978
+ if (!e?.isConnected) return;
979
+ let t = this.attachments();
980
+ if (t.askLogs === this.shown.askLogs) {
981
+ this.shown = t, this.updateNotice();
982
+ return;
983
+ }
984
+ let n = e.contains(this.root.activeElement), r = this.renderPrivacy();
985
+ e.replaceWith(r), n && (r.querySelector("input") ?? this.panel.querySelector("[data-key=\"send\"]"))?.focus();
986
+ }
987
+ renderAccessibility(e) {
988
+ let t = [this.header(this.kindTitle(e), this.kinds.length > 1)], n = `pnx-a11y-note-${this.uid}`;
989
+ t.push(H("p", {
990
+ class: "a11y-note",
991
+ id: n
992
+ }, "We'll pass this to the team that runs this website. We also check this page for common accessibility problems and send the results with it."));
993
+ let r = `pnx-barrier-${this.uid}`, i = H("fieldset", {
994
+ class: "field barriers",
995
+ "aria-labelledby": r,
996
+ "aria-describedby": n
997
+ }, H("legend", {
998
+ class: "legend",
999
+ id: r
1000
+ }, "What's getting in the way? ", H("span", { class: "optional" }, "(optional)")));
1001
+ X.forEach(([e, t], n) => {
1002
+ let r = `pnx-b${n}-${this.uid}`, a = H("input", {
1003
+ id: r,
1004
+ type: "radio",
1005
+ name: `pnx-barrier-${this.uid}`,
1006
+ value: e,
1007
+ "data-key": `barrier-${e}`,
1008
+ "data-autofocus": (this.barrier ? this.barrier === e : n === 0) || void 0
1009
+ });
1010
+ a.checked = this.barrier === e, a.addEventListener("change", () => {
1011
+ a.checked && (this.barrier = e);
1012
+ }), i.append(H("div", { class: "radio" }, a, H("label", { for: r }, t)));
1013
+ }), t.push(i);
1014
+ let a = `pnx-msg-${this.uid}`, o = H("textarea", {
1015
+ id: a,
1016
+ maxlength: 5e3,
1017
+ "data-key": "message",
1018
+ "aria-describedby": n,
1019
+ placeholder: this.word("messagePlaceholder", "For example: I couldn't reach the Pay button with the Tab key")
1020
+ });
1021
+ o.value = this.message, o.addEventListener("input", () => {
1022
+ this.message = o.value;
1023
+ }), t.push(H("div", { class: "field" }, H("label", { for: a }, "What were you trying to do, and what stopped you?"), o));
1024
+ let s = this.renderShot(e);
1025
+ return s && t.push(s), t.push(...this.renderEmailAndSend(e, o, "Only used to reply to you about this.")), t;
1026
+ }
1027
+ honeypot() {
1028
+ let e = H("input", {
1029
+ type: "text",
1030
+ name: "website",
1031
+ tabindex: -1,
1032
+ autocomplete: "off",
1033
+ "aria-label": "Leave this empty"
1034
+ });
1035
+ e.value = this.hp, e.addEventListener("input", () => {
1036
+ this.hp = e.value;
1037
+ });
1038
+ let t = H("div", { "aria-hidden": "true" }, e);
1039
+ return t.style.cssText = "position:absolute;left:-10000px;top:auto;width:1px;height:1px;overflow:hidden", t;
1040
+ }
1041
+ async send(e, t, n, r) {
1042
+ if (this.sending) return;
1043
+ t.textContent = "", n.removeAttribute("aria-invalid");
1044
+ let i = this.email.trim();
1045
+ if (i && !d(i)) {
1046
+ t.textContent = "Please check your email address, or leave it empty.", n.setAttribute("aria-invalid", "true"), n.setAttribute("aria-errormessage", t.id), n.focus();
1047
+ return;
1048
+ }
1049
+ if (this.shot.kind === "busy") {
1050
+ t.textContent = "One moment, the screenshot is still being taken.";
1051
+ return;
1052
+ }
1053
+ for (let n of this.fieldsFor(e)) {
1054
+ let e = this.answers[n.id];
1055
+ if (!n.required || (n.type === "checkbox" ? e === !0 : e)) continue;
1056
+ let r = this.panel.querySelector(`[data-key="field-${n.id}"]`);
1057
+ t.textContent = n.type === "checkbox" ? `Please tick “${n.label}”.` : n.type === "select" ? `Please choose an answer for “${n.label}”.` : `Please fill in “${n.label}”.`, r?.setAttribute("aria-invalid", "true"), r?.setAttribute("aria-errormessage", t.id), r?.focus();
1058
+ return;
1059
+ }
1060
+ let a = this.shot.kind === "ready" ? this.shot.shot : void 0, o = e.type === "GENERAL" ? this.rating : void 0;
1061
+ if (!m({
1062
+ type: e.type,
1063
+ message: this.message,
1064
+ rating: o,
1065
+ screenshot: a?.dataUrl,
1066
+ barrier: e.type === "ACCESSIBILITY" ? this.barrier : void 0
1067
+ })) {
1068
+ t.textContent = e.type === "GENERAL" && this.config.settings.rating !== !1 ? "Add a few words or a star rating." : e.type === "ACCESSIBILITY" ? "Choose what's in the way, or add a few words." : "Add a few words so we know what you mean.", r.focus();
1069
+ return;
1070
+ }
1071
+ this.sending = !0, this.renderKeepingFocus(), this.announce("Sending…");
1072
+ let s = await this.askFollowUp(e);
1073
+ this.view !== "form" || this.kind !== e || !this.isOpen() ? (this.sending = !1, this.isOpen() && this.renderKeepingFocus()) : s ? (this.sending = !1, this.view = "question", this.render(), this.focusFirst()) : await this.submitNow(e, i, o, a);
1074
+ }
1075
+ async askFollowUp(e) {
1076
+ let t = this.handlers.followUp, n = this.message.trim();
1077
+ if (!t || e.type === "GENERAL" || e.type === "ACCESSIBILITY" || !n || n.length > 140) return null;
1078
+ if (this.asked?.message === n) return this.asked.question;
1079
+ let r = null;
1080
+ try {
1081
+ r = (await t({
1082
+ type: e.type,
1083
+ message: n
1084
+ }))?.trim() || null;
1085
+ } catch {
1086
+ r = null;
1087
+ }
1088
+ return this.asked = {
1089
+ message: n,
1090
+ question: r?.slice(0, 300) || null
1091
+ }, this.asked.question;
1092
+ }
1093
+ async submitNow(e, t, n, r, i) {
1094
+ this.sending = !0, this.renderKeepingFocus();
1095
+ let a;
1096
+ try {
1097
+ a = await this.handlers.submit({
1098
+ type: e.type,
1099
+ message: this.message,
1100
+ rating: n,
1101
+ email: t || void 0,
1102
+ shot: r,
1103
+ followUp: i,
1104
+ fields: this.fieldAnswers(e),
1105
+ barrier: e.type === "ACCESSIBILITY" ? this.barrier : void 0,
1106
+ includeLogs: this.shown.askLogs && this.includeLogs ? !0 : void 0,
1107
+ listed: {
1108
+ logs: this.shown.logs || this.shown.askLogs && this.includeLogs,
1109
+ replay: this.shown.replay
1110
+ },
1111
+ hp: this.hp || void 0,
1112
+ elapsedMs: this.openedAt ? Math.max(0, Date.now() - this.openedAt) : void 0
1113
+ });
1114
+ } catch {
1115
+ a = {
1116
+ status: "error",
1117
+ message: "Something went wrong. Please try again."
1118
+ };
1119
+ }
1120
+ if (this.sending = !1, a.status === "error") {
1121
+ this.view = "form", this.render();
1122
+ let e = this.panel.querySelector(".error");
1123
+ e && (e.textContent = a.message), this.panel.querySelector("[data-key=\"send\"]")?.focus();
1124
+ } else this.queued = a.status === "queued", this.view = "done", this.render(), this.focusFirst(), this.announce(this.queued ? "Saved. We'll send it when you're back online." : this.word("confirmation", $)), this.closeTimer = setTimeout(() => this.close(this.panel.contains(this.root.activeElement)), Z);
1125
+ }
1126
+ renderQuestion(e, t) {
1127
+ let n = [this.header("One quick question", !0, () => {
1128
+ this.view = "form", this.render(), this.panel.querySelector("[data-key=\"message\"]")?.focus();
1129
+ })], r = H("div", { class: "note" }, H("span", {
1130
+ class: "dot",
1131
+ "aria-hidden": "true"
1132
+ }), H("span", {}, H("span", { class: "sr" }, "Your note: "), `“${this.message.trim()}”`));
1133
+ r.style.setProperty("--dot", e.dot), n.push(r);
1134
+ let i = `pnx-answer-${this.uid}`, a = `pnx-answer-hint-${this.uid}`, o = H("textarea", {
1135
+ id: i,
1136
+ class: "answer",
1137
+ maxlength: 2e3,
1138
+ "data-key": "answer",
1139
+ "data-autofocus": !0,
1140
+ "aria-describedby": a,
1141
+ placeholder: "Your answer"
1142
+ });
1143
+ o.value = this.answer, o.addEventListener("input", () => {
1144
+ this.answer = o.value;
1145
+ }), n.push(H("div", { class: "field" }, H("label", {
1146
+ for: i,
1147
+ class: "question"
1148
+ }, t), o, H("span", {
1149
+ class: "hint",
1150
+ id: a
1151
+ }, "Optional. It helps us fix it faster.")));
1152
+ let s = H("p", {
1153
+ class: "error",
1154
+ role: "alert"
1155
+ }), c = this.email.trim(), l = e.type === "GENERAL" ? this.rating : void 0, u = this.shot.kind === "ready" ? this.shot.shot : void 0, d = H("button", {
1156
+ type: "button",
1157
+ class: "send",
1158
+ "data-key": "send",
1159
+ disabled: this.sending
1160
+ }, this.sending ? "Sending…" : "Send");
1161
+ this.colourSend(d, e), d.addEventListener("click", () => {
1162
+ if (this.sending) return;
1163
+ let n = this.answer.trim();
1164
+ this.announce("Sending…"), this.submitNow(e, c, l, u, n ? {
1165
+ question: t,
1166
+ answer: n.slice(0, 2e3)
1167
+ } : void 0);
1168
+ });
1169
+ let f = H("button", {
1170
+ type: "button",
1171
+ class: "link skip",
1172
+ "data-key": "skip",
1173
+ disabled: this.sending
1174
+ }, "Skip and send");
1175
+ return f.addEventListener("click", () => {
1176
+ this.sending || (this.announce("Sending…"), this.submitNow(e, c, l, u));
1177
+ }), n.push(s, d, f), n;
1178
+ }
1179
+ colourSend(e, t) {
1180
+ let n = this.sendColour ?? t.send;
1181
+ e.style.setProperty("--type", n), e.style.setProperty("--type-ink", this.sendColour ? B(n) : t.ink);
1182
+ }
1183
+ fieldsFor(e) {
1184
+ if (e.key === "accessibility") return [];
1185
+ let t = e.key;
1186
+ return (this.config.settings.fields ?? []).filter((e) => e.types?.[t] !== !1);
1187
+ }
1188
+ fieldAnswers(e) {
1189
+ let t = [];
1190
+ for (let n of this.fieldsFor(e)) {
1191
+ let e = this.answers[n.id];
1192
+ n.type === "checkbox" ? t.push({
1193
+ id: n.id,
1194
+ value: e === !0
1195
+ }) : typeof e == "string" && e.trim() && t.push({
1196
+ id: n.id,
1197
+ value: e.trim()
1198
+ });
1199
+ }
1200
+ return t.length ? t : void 0;
1201
+ }
1202
+ renderFields(e) {
1203
+ return this.fieldsFor(e).map((e, t) => {
1204
+ let n = `pnx-f${t}-${this.uid}`, r = `field-${e.id}`, i = (e) => {
1205
+ e.removeAttribute("aria-invalid"), e.removeAttribute("aria-errormessage");
1206
+ }, a = (t) => H("label", {
1207
+ for: n,
1208
+ class: t
1209
+ }, e.label, e.required ? null : H("span", { class: "optional" }, " (optional)"));
1210
+ if (e.type === "checkbox") {
1211
+ let t = H("input", {
1212
+ id: n,
1213
+ type: "checkbox",
1214
+ "data-key": r,
1215
+ "aria-required": e.required ? "true" : void 0
1216
+ });
1217
+ return t.checked = this.answers[e.id] === !0, t.addEventListener("change", () => {
1218
+ this.answers[e.id] = t.checked, i(t);
1219
+ }), H("div", { class: "field check" }, t, a());
1220
+ }
1221
+ if (e.type === "select") {
1222
+ let t = H("select", {
1223
+ id: n,
1224
+ "data-key": r,
1225
+ "aria-required": e.required ? "true" : void 0
1226
+ }, H("option", { value: "" }, "Choose…"), ...e.options.map((e) => H("option", { value: e }, e)));
1227
+ return t.value = String(this.answers[e.id] ?? ""), t.addEventListener("change", () => {
1228
+ this.answers[e.id] = t.value, i(t);
1229
+ }), H("div", { class: "field" }, a(), t);
1230
+ }
1231
+ let o = H("input", {
1232
+ id: n,
1233
+ type: "text",
1234
+ maxlength: 200,
1235
+ "data-key": r,
1236
+ "aria-required": e.required ? "true" : void 0
1237
+ });
1238
+ return o.value = String(this.answers[e.id] ?? ""), o.addEventListener("input", () => {
1239
+ this.answers[e.id] = o.value, i(o);
1240
+ }), H("div", { class: "field" }, a(), o);
1241
+ });
1242
+ }
1243
+ renderDone() {
1244
+ let e = H("button", {
1245
+ type: "button",
1246
+ class: "link",
1247
+ "data-key": "again"
1248
+ }, "Send another");
1249
+ e.addEventListener("click", () => {
1250
+ this.reset(), this.render(), this.focusFirst();
1251
+ });
1252
+ let t = H("div", { class: "head" });
1253
+ t.append(H("span", { class: "title" }));
1254
+ let n = H("button", {
1255
+ type: "button",
1256
+ class: "icon-btn",
1257
+ "aria-label": "Close feedback"
1258
+ });
1259
+ return n.append(W(G.close)), n.addEventListener("click", () => this.close()), t.append(n), [t, H("div", { class: "done" }, H("span", {
1260
+ class: "tick",
1261
+ "aria-hidden": "true"
1262
+ }, "✓"), H("h2", {
1263
+ class: "title",
1264
+ id: `pnx-title-${this.uid}`,
1265
+ tabindex: -1,
1266
+ "data-autofocus": !0
1267
+ }, this.queued ? "Saved for later" : this.word("confirmation", $)), this.queued ? H("p", {}, "You're offline. We'll send it as soon as you're back.", this.email.trim() ? " If you leave this page first, it goes without your email address." : "") : null, e)];
1268
+ }
1269
+ };
1270
+ export { N as a, o as c, g as d, F as i, b as l, q as n, L as o, H as r, k as s, te as t, v as u };
1271
+
1272
+ //# sourceMappingURL=widget-BpTBdX2R.mjs.map