@wexio/messenger-widget-react 1.0.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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +133 -0
  3. package/dist/widget-react-AgErOR36.js +325 -0
  4. package/dist/widget-react-AgErOR36.js.map +1 -0
  5. package/dist/widget-react-BAOIDvhV.js +4250 -0
  6. package/dist/widget-react-BAOIDvhV.js.map +1 -0
  7. package/dist/widget-react-BfPdgAQ-.js +5767 -0
  8. package/dist/widget-react-BfPdgAQ-.js.map +1 -0
  9. package/dist/widget-react-BxvW64LH.js +4429 -0
  10. package/dist/widget-react-BxvW64LH.js.map +1 -0
  11. package/dist/widget-react-C5COLy3m.js +23847 -0
  12. package/dist/widget-react-C5COLy3m.js.map +1 -0
  13. package/dist/widget-react-CAWxn8I0.js +247 -0
  14. package/dist/widget-react-CAWxn8I0.js.map +1 -0
  15. package/dist/widget-react-CDPzwV1i.js +11685 -0
  16. package/dist/widget-react-CDPzwV1i.js.map +1 -0
  17. package/dist/widget-react-CPYwD6FR.js +498 -0
  18. package/dist/widget-react-CPYwD6FR.js.map +1 -0
  19. package/dist/widget-react-CUBFPjaV.js +23 -0
  20. package/dist/widget-react-CUBFPjaV.js.map +1 -0
  21. package/dist/widget-react-CUuKGDZN.js +355 -0
  22. package/dist/widget-react-CUuKGDZN.js.map +1 -0
  23. package/dist/widget-react-CZs0xRrr.js +1336 -0
  24. package/dist/widget-react-CZs0xRrr.js.map +1 -0
  25. package/dist/widget-react-Cj_zbk_F.js +325 -0
  26. package/dist/widget-react-Cj_zbk_F.js.map +1 -0
  27. package/dist/widget-react-D-QrEVpv.js +125 -0
  28. package/dist/widget-react-D-QrEVpv.js.map +1 -0
  29. package/dist/widget-react-D8TPnM9r.js +26 -0
  30. package/dist/widget-react-D8TPnM9r.js.map +1 -0
  31. package/dist/widget-react-DE7AVrCo.js +5737 -0
  32. package/dist/widget-react-DE7AVrCo.js.map +1 -0
  33. package/dist/widget-react-DOX6j7_Q.js +30 -0
  34. package/dist/widget-react-DOX6j7_Q.js.map +1 -0
  35. package/dist/widget-react-DSw03RG7.js +262 -0
  36. package/dist/widget-react-DSw03RG7.js.map +1 -0
  37. package/dist/widget-react-Dew7YaLU.js +16 -0
  38. package/dist/widget-react-Dew7YaLU.js.map +1 -0
  39. package/dist/widget-react-DtOeNw5z.js +325 -0
  40. package/dist/widget-react-DtOeNw5z.js.map +1 -0
  41. package/dist/widget-react-DwL_rsx_.js +630 -0
  42. package/dist/widget-react-DwL_rsx_.js.map +1 -0
  43. package/dist/widget-react.d.ts +301 -0
  44. package/dist/widget-react.js +22285 -0
  45. package/dist/widget-react.js.map +1 -0
  46. package/package.json +41 -0
@@ -0,0 +1,498 @@
1
+ import "react";
2
+ import "react-dom";
3
+ import "react/jsx-runtime";
4
+ import "react-dom/client";
5
+ import { d as e, l as t, o as n, s as r } from "./widget-react-DE7AVrCo.js";
6
+ import { i, n as a, t as o } from "./widget-react-BxvW64LH.js";
7
+ import { t as s } from "./widget-react-Dew7YaLU.js";
8
+ import { t as c } from "./widget-react-D8TPnM9r.js";
9
+ import { t as l } from "./widget-react-CZs0xRrr.js";
10
+ import { useEffect as u, useRef as d, useState as f } from "react";
11
+ import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
12
+ var g = o("square", [["rect", {
13
+ width: "18",
14
+ height: "18",
15
+ x: "3",
16
+ y: "3",
17
+ rx: "2",
18
+ key: "afitv7"
19
+ }]]);
20
+ //#endregion
21
+ //#region node_modules/wavesurfer.js/dist/plugins/record.esm.js
22
+ function _(e, t, n, r) {
23
+ return new (n || (n = Promise))((function(i, a) {
24
+ function o(e) {
25
+ try {
26
+ c(r.next(e));
27
+ } catch (e) {
28
+ a(e);
29
+ }
30
+ }
31
+ function s(e) {
32
+ try {
33
+ c(r.throw(e));
34
+ } catch (e) {
35
+ a(e);
36
+ }
37
+ }
38
+ function c(e) {
39
+ var t;
40
+ e.done ? i(e.value) : (t = e.value, t instanceof n ? t : new n((function(e) {
41
+ e(t);
42
+ }))).then(o, s);
43
+ }
44
+ c((r = r.apply(e, t || [])).next());
45
+ }));
46
+ }
47
+ var v = class {
48
+ constructor() {
49
+ this.listeners = {};
50
+ }
51
+ on(e, t, n) {
52
+ if (this.listeners[e] || (this.listeners[e] = /* @__PURE__ */ new Set()), n?.once) {
53
+ let n = (...r) => {
54
+ this.un(e, n), t(...r);
55
+ };
56
+ return this.listeners[e].add(n), () => this.un(e, n);
57
+ }
58
+ return this.listeners[e].add(t), () => this.un(e, t);
59
+ }
60
+ un(e, t) {
61
+ var n;
62
+ (n = this.listeners[e]) == null || n.delete(t);
63
+ }
64
+ once(e, t) {
65
+ return this.on(e, t, { once: !0 });
66
+ }
67
+ unAll() {
68
+ this.listeners = {};
69
+ }
70
+ emit(e, ...t) {
71
+ this.listeners[e] && this.listeners[e].forEach(((e) => e(...t)));
72
+ }
73
+ }, y = class extends v {
74
+ constructor(e) {
75
+ super(), this.subscriptions = [], this.isDestroyed = !1, this.options = e;
76
+ }
77
+ onInit() {}
78
+ _init(e) {
79
+ this.isDestroyed && (this.subscriptions = [], this.isDestroyed = !1), this.wavesurfer = e, this.onInit();
80
+ }
81
+ destroy() {
82
+ this.emit("destroy"), this.subscriptions.forEach(((e) => e())), this.subscriptions = [], this.isDestroyed = !0, this.wavesurfer = void 0;
83
+ }
84
+ }, b = class extends v {
85
+ constructor() {
86
+ super(...arguments), this.animationFrameId = null, this.isRunning = !1;
87
+ }
88
+ start() {
89
+ if (this.isRunning) return;
90
+ this.isRunning = !0;
91
+ let e = () => {
92
+ this.isRunning && (this.emit("tick"), this.animationFrameId = requestAnimationFrame(e));
93
+ };
94
+ e();
95
+ }
96
+ stop() {
97
+ this.isRunning = !1, this.animationFrameId !== null && (cancelAnimationFrame(this.animationFrameId), this.animationFrameId = null);
98
+ }
99
+ destroy() {
100
+ this.stop();
101
+ }
102
+ }, x = 100, S = [
103
+ "audio/webm",
104
+ "audio/wav",
105
+ "audio/mpeg",
106
+ "audio/mp4",
107
+ "audio/mp3"
108
+ ], C = class e extends y {
109
+ constructor(e) {
110
+ var t, n, r;
111
+ super(Object.assign(Object.assign({}, e), {
112
+ audioBitsPerSecond: e.audioBitsPerSecond ?? 128e3,
113
+ scrollingWaveform: (t = e.scrollingWaveform) != null && t,
114
+ scrollingWaveformWindow: e.scrollingWaveformWindow ?? 5,
115
+ continuousWaveform: (n = e.continuousWaveform) != null && n,
116
+ renderRecordedAudio: (r = e.renderRecordedAudio) == null || r,
117
+ mediaRecorderTimeslice: e.mediaRecorderTimeslice ?? void 0
118
+ })), this.stream = null, this.mediaRecorder = null, this.dataWindow = null, this.isWaveformPaused = !1, this.lastStartTime = 0, this.lastDuration = 0, this.duration = 0, this.micStream = null, this.recordedBlobUrl = null, this.timer = new b(), this.subscriptions.push(this.timer.on("tick", (() => {
119
+ let e = performance.now() - this.lastStartTime;
120
+ this.duration = this.isPaused() ? this.duration : this.lastDuration + e, this.emit("record-progress", this.duration);
121
+ })));
122
+ }
123
+ static create(t) {
124
+ return new e(t || {});
125
+ }
126
+ renderMicStream(e) {
127
+ let t = new AudioContext(), n = t.createMediaStreamSource(e), r = t.createAnalyser();
128
+ n.connect(r), (this.options.continuousWaveform || this.options.scrollingWaveform) && (r.fftSize = 32);
129
+ let i = r.frequencyBinCount, a = new Float32Array(i), o = 0;
130
+ this.wavesurfer && (this.originalOptions ?? (this.originalOptions = Object.assign({}, this.wavesurfer.options)), this.wavesurfer.options.interact = !1, this.options.scrollingWaveform && (this.wavesurfer.options.cursorWidth = 0, this.wavesurfer.options.normalize = !0, this.wavesurfer.options.maxPeak = 1));
131
+ let s = setInterval((() => {
132
+ if (!this.isWaveformPaused) {
133
+ if (r.getFloatTimeDomainData(a), this.options.scrollingWaveform) {
134
+ let e = Math.floor((this.options.scrollingWaveformWindow || 0) * x), t = 0;
135
+ for (let e = 0; e < i; e++) {
136
+ let n = Math.abs(a[e]);
137
+ n > t && (t = n);
138
+ }
139
+ this.dataWindow || (this.dataWindow = new Float32Array(e));
140
+ let n = new Float32Array(e);
141
+ if (this.dataWindow && this.dataWindow.length > 0) {
142
+ let t = e - 1, r = this.dataWindow.slice(-t);
143
+ n.set(r, 0);
144
+ }
145
+ n[e - 1] = t, this.dataWindow = n;
146
+ } else if (this.options.continuousWaveform) {
147
+ if (!this.dataWindow) {
148
+ let e = this.options.continuousWaveformDuration ? Math.round(this.options.continuousWaveformDuration * x) : (this.wavesurfer?.getWidth() ?? 0) * window.devicePixelRatio;
149
+ this.dataWindow = new Float32Array(e);
150
+ }
151
+ let e = 0;
152
+ for (let t = 0; t < i; t++) {
153
+ let n = Math.abs(a[t]);
154
+ n > e && (e = n);
155
+ }
156
+ if (o + 1 > this.dataWindow.length) {
157
+ let e = new Float32Array(2 * this.dataWindow.length);
158
+ e.set(this.dataWindow, 0), this.dataWindow = e;
159
+ }
160
+ this.dataWindow[o] = e, o++;
161
+ } else this.dataWindow = a;
162
+ if (this.wavesurfer) {
163
+ let e = (this.dataWindow?.length ?? 0) / x;
164
+ this.wavesurfer.load("", [this.dataWindow], this.options.scrollingWaveform ? this.options.scrollingWaveformWindow : e).then((() => {
165
+ this.wavesurfer && this.options.continuousWaveform && (this.wavesurfer.setTime(this.getDuration() / 1e3), this.wavesurfer.options.minPxPerSec || this.wavesurfer.setOptions({ minPxPerSec: this.wavesurfer.getWidth() / this.wavesurfer.getDuration() }));
166
+ })).catch(((e) => {
167
+ console.error("Error rendering real-time recording data:", e);
168
+ }));
169
+ }
170
+ }
171
+ }), 10);
172
+ return {
173
+ onDestroy: () => {
174
+ clearInterval(s), n?.disconnect(), t?.close();
175
+ },
176
+ onEnd: () => {
177
+ this.isWaveformPaused = !0, this.stopMic();
178
+ }
179
+ };
180
+ }
181
+ startMic(e) {
182
+ return _(this, void 0, void 0, (function* () {
183
+ let t;
184
+ this.micStream && this.stopMic();
185
+ try {
186
+ t = yield navigator.mediaDevices.getUserMedia({ audio: e == null || e });
187
+ } catch (e) {
188
+ throw Error("Error accessing the microphone: " + e.message);
189
+ }
190
+ let n = this.renderMicStream(t);
191
+ return this.micStream = n, this.unsubscribeDestroy = this.once("destroy", n.onDestroy), this.unsubscribeRecordEnd = this.once("record-end", n.onEnd), this.stream = t, t;
192
+ }));
193
+ }
194
+ stopMic() {
195
+ var e, t, n;
196
+ (e = this.micStream) == null || e.onDestroy(), (t = this.unsubscribeDestroy) == null || t.call(this), (n = this.unsubscribeRecordEnd) == null || n.call(this), this.micStream = null, this.unsubscribeDestroy = void 0, this.unsubscribeRecordEnd = void 0, this.stream && (this.stream.getTracks().forEach(((e) => e.stop())), this.stream = null, this.mediaRecorder = null);
197
+ }
198
+ startRecording(e) {
199
+ return _(this, void 0, void 0, (function* () {
200
+ let t = this.stream || (yield this.startMic(e));
201
+ this.dataWindow = null;
202
+ let n = this.mediaRecorder || new MediaRecorder(t, {
203
+ mimeType: this.options.mimeType || S.find(((e) => MediaRecorder.isTypeSupported(e))),
204
+ audioBitsPerSecond: this.options.audioBitsPerSecond
205
+ });
206
+ this.mediaRecorder = n, this.stopRecording();
207
+ let r = [];
208
+ n.ondataavailable = (e) => {
209
+ e.data.size > 0 && r.push(e.data), this.emit("record-data-available", e.data);
210
+ };
211
+ let i = (e) => {
212
+ var t;
213
+ let i = new Blob(r, { type: n.mimeType });
214
+ this.emit(e, i), this.options.renderRecordedAudio && (this.applyOriginalOptionsIfNeeded(), this.recordedBlobUrl && URL.revokeObjectURL(this.recordedBlobUrl), this.recordedBlobUrl = URL.createObjectURL(i), (t = this.wavesurfer) == null || t.load(this.recordedBlobUrl));
215
+ };
216
+ n.onpause = () => i("record-pause"), n.onstop = () => i("record-end"), n.start(this.options.mediaRecorderTimeslice), this.lastStartTime = performance.now(), this.lastDuration = 0, this.duration = 0, this.isWaveformPaused = !1, this.timer.start(), this.emit("record-start");
217
+ }));
218
+ }
219
+ getDuration() {
220
+ return this.duration;
221
+ }
222
+ isRecording() {
223
+ return this.mediaRecorder?.state === "recording";
224
+ }
225
+ isPaused() {
226
+ return this.mediaRecorder?.state === "paused";
227
+ }
228
+ isActive() {
229
+ return this.mediaRecorder?.state !== "inactive";
230
+ }
231
+ stopRecording() {
232
+ var e;
233
+ this.isActive() && ((e = this.mediaRecorder) == null || e.stop(), this.timer.stop());
234
+ }
235
+ pauseRecording() {
236
+ var e, t;
237
+ this.isRecording() && (this.isWaveformPaused = !0, (e = this.mediaRecorder) == null || e.requestData(), (t = this.mediaRecorder) == null || t.pause(), this.timer.stop(), this.lastDuration = this.duration);
238
+ }
239
+ resumeRecording() {
240
+ var e;
241
+ this.isPaused() && (this.isWaveformPaused = !1, (e = this.mediaRecorder) == null || e.resume(), this.timer.start(), this.lastStartTime = performance.now(), this.emit("record-resume"));
242
+ }
243
+ static getAvailableAudioDevices() {
244
+ return _(this, void 0, void 0, (function* () {
245
+ return navigator.mediaDevices.enumerateDevices().then(((e) => e.filter(((e) => e.kind === "audioinput"))));
246
+ }));
247
+ }
248
+ destroy() {
249
+ this.applyOriginalOptionsIfNeeded(), super.destroy(), this.stopRecording(), this.stopMic(), this.recordedBlobUrl && (URL.revokeObjectURL(this.recordedBlobUrl), this.recordedBlobUrl = null);
250
+ }
251
+ applyOriginalOptionsIfNeeded() {
252
+ this.wavesurfer && this.originalOptions && (this.wavesurfer.setOptions(this.originalOptions), delete this.originalOptions);
253
+ }
254
+ };
255
+ //#endregion
256
+ //#region components/widget/tabs/messages-tab/composer/voice-recorder-bar/helpers.ts
257
+ function w(e) {
258
+ let t = Math.max(0, e);
259
+ return `${Math.floor(t / 60)}:${(t % 60).toString().padStart(2, "0")}`;
260
+ }
261
+ function T() {
262
+ if (typeof MediaRecorder > "u") return null;
263
+ for (let e of [
264
+ "audio/webm;codecs=opus",
265
+ "audio/webm",
266
+ "audio/mp4",
267
+ "audio/ogg"
268
+ ]) if (MediaRecorder.isTypeSupported?.(e)) return e;
269
+ return null;
270
+ }
271
+ async function E(e) {
272
+ return new Promise((t, n) => {
273
+ let r = new FileReader();
274
+ r.onload = () => {
275
+ let e = r.result;
276
+ if (typeof e != "string") {
277
+ n(/* @__PURE__ */ Error("FileReader returned non-string result"));
278
+ return;
279
+ }
280
+ let i = e.indexOf(",");
281
+ t(i >= 0 ? e.slice(i + 1) : e);
282
+ }, r.onerror = () => n(r.error ?? /* @__PURE__ */ Error("read failed")), r.readAsDataURL(e);
283
+ });
284
+ }
285
+ //#endregion
286
+ //#region components/widget/tabs/messages-tab/composer/voice-recorder-bar/index.tsx
287
+ function D({ onComplete: o, onCancel: c, onError: _ }) {
288
+ let v = i("messages"), y = d(null), b = d(null), x = d(null), S = d(null), D = d([]), k = d(null), [A, j] = f("recording"), [M, N] = f(0), [P, F] = f(!1), I = d(null), L = d(!1);
289
+ return u(() => {
290
+ let e = y.current;
291
+ if (!e) return;
292
+ if (typeof window > "u" || !window.MediaRecorder) {
293
+ _("unsupported");
294
+ return;
295
+ }
296
+ let t = !1;
297
+ L.current = !1;
298
+ let n = getComputedStyle(e), r = n.getPropertyValue("--wx-primary").trim() || "#5b6cff", i = n.getPropertyValue("--wx-fg-muted").trim() || "#6b7280", a = l.create({
299
+ container: e,
300
+ waveColor: i,
301
+ progressColor: r,
302
+ cursorColor: r,
303
+ cursorWidth: 2,
304
+ height: 32,
305
+ barWidth: 2,
306
+ barGap: 2,
307
+ barRadius: 2,
308
+ interact: !0,
309
+ hideScrollbar: !0
310
+ });
311
+ b.current = a, a.on("play", () => F(!0)), a.on("pause", () => F(!1)), a.on("finish", () => F(!1));
312
+ let o = a.registerPlugin(C.create({
313
+ continuousWaveform: !0,
314
+ continuousWaveformDuration: 60,
315
+ renderRecordedAudio: !1
316
+ }));
317
+ x.current = o;
318
+ let s = null, c = null;
319
+ return o.startMic().then((e) => {
320
+ if (t || L.current) {
321
+ try {
322
+ e.getTracks().forEach((e) => {
323
+ e.stop();
324
+ });
325
+ } catch {}
326
+ try {
327
+ o.stopMic();
328
+ } catch {}
329
+ return;
330
+ }
331
+ let n = T(), r = n ? new MediaRecorder(e, { mimeType: n }) : new MediaRecorder(e);
332
+ S.current = r, c = r, D.current = [], r.addEventListener("dataavailable", (e) => {
333
+ e.data && e.data.size > 0 && D.current.push(e.data);
334
+ }), r.addEventListener("stop", () => {
335
+ if (t || L.current) return;
336
+ try {
337
+ o.stopMic();
338
+ } catch {}
339
+ s !== null && (clearInterval(s), s = null, k.current = null);
340
+ let e = r.mimeType || n || "audio/webm", i = new Blob(D.current, { type: e });
341
+ E(i).then((n) => {
342
+ if (t || L.current) return;
343
+ let r = e.includes("mp4") ? "mp4" : "webm";
344
+ I.current = {
345
+ base64: n,
346
+ mimetype: e.split(";")[0].trim(),
347
+ size: i.size,
348
+ filename: `voice-${Date.now()}.${r}`
349
+ }, a.loadBlob(i).then(() => {
350
+ if (!(t || L.current)) {
351
+ try {
352
+ a.setOptions({ interact: !0 });
353
+ } catch {}
354
+ try {
355
+ a.setTime(0);
356
+ } catch {}
357
+ }
358
+ }).catch(() => {}), j("preview");
359
+ }).catch(() => _("failed"));
360
+ }), r.start();
361
+ let i = performance.now();
362
+ s = window.setInterval(() => {
363
+ let e = performance.now() - i, t = Math.floor(e / 1e3);
364
+ N((e) => e === t ? e : t);
365
+ }, 250), k.current = s;
366
+ }).catch((e) => {
367
+ if (t) return;
368
+ let n = e?.message ?? "";
369
+ _(n.includes("Permission") || n.includes("denied") ? "denied" : "failed");
370
+ }), () => {
371
+ t = !0, s !== null && clearInterval(s);
372
+ try {
373
+ c?.state === "recording" && c.stop();
374
+ } catch {}
375
+ try {
376
+ o.stopMic();
377
+ } catch {}
378
+ a.destroy(), b.current === a && (b.current = null), x.current === o && (x.current = null), S.current === c && (S.current = null);
379
+ };
380
+ }, []), /* @__PURE__ */ h(e.div, {
381
+ initial: {
382
+ opacity: 0,
383
+ y: 6
384
+ },
385
+ animate: {
386
+ opacity: 1,
387
+ y: 0
388
+ },
389
+ transition: { duration: .18 },
390
+ className: a("flex items-center gap-1.5 rounded-wx-lg border border-wx-border bg-wx-bg px-2 py-2"),
391
+ children: [
392
+ /* @__PURE__ */ m(O, {
393
+ Icon: t,
394
+ onClick: () => {
395
+ L.current = !0;
396
+ try {
397
+ S.current?.state === "recording" && S.current.stop();
398
+ } catch {}
399
+ try {
400
+ x.current?.stopMic();
401
+ } catch {}
402
+ try {
403
+ b.current?.pause();
404
+ } catch {}
405
+ c();
406
+ },
407
+ ariaLabel: v("cancelRecording"),
408
+ intent: "ghost"
409
+ }),
410
+ /* @__PURE__ */ h("div", {
411
+ className: "flex h-9 min-w-0 flex-1 items-center gap-2 rounded-full bg-wx-bg-elevated px-3",
412
+ children: [
413
+ A === "recording" && /* @__PURE__ */ m("span", {
414
+ "aria-hidden": "true",
415
+ className: "h-2 w-2 shrink-0 animate-pulse rounded-full bg-wx-danger"
416
+ }),
417
+ /* @__PURE__ */ m("div", {
418
+ ref: y,
419
+ "aria-hidden": "true",
420
+ className: a("min-w-0 flex-1 overflow-hidden", A !== "preview" && "pointer-events-none")
421
+ }),
422
+ /* @__PURE__ */ m("span", {
423
+ className: "shrink-0 font-mono text-xs tabular-nums text-wx-fg-muted",
424
+ children: w(M)
425
+ })
426
+ ]
427
+ }),
428
+ A === "recording" && /* @__PURE__ */ m(e.button, {
429
+ type: "button",
430
+ onClick: () => {
431
+ try {
432
+ S.current?.state === "recording" && S.current.stop();
433
+ } catch {}
434
+ },
435
+ "aria-label": v("stopRecording"),
436
+ whileHover: { scale: 1.08 },
437
+ whileTap: { scale: .9 },
438
+ transition: {
439
+ type: "spring",
440
+ stiffness: 400,
441
+ damping: 22
442
+ },
443
+ className: a("flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition-colors", "text-wx-fg-muted hover:bg-wx-bg-elevated hover:text-wx-fg"),
444
+ children: /* @__PURE__ */ m(g, { size: 14 })
445
+ }),
446
+ A === "preview" && /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(O, {
447
+ Icon: P ? n : r,
448
+ onClick: () => {
449
+ let e = b.current;
450
+ e && (e.isPlaying() ? e.pause() : e.play());
451
+ },
452
+ ariaLabel: v(P ? "pauseRecording" : "playPreview"),
453
+ intent: "ghost"
454
+ }), /* @__PURE__ */ m(e.button, {
455
+ type: "button",
456
+ onClick: () => {
457
+ let e = I.current;
458
+ e && o(e);
459
+ },
460
+ "aria-label": v("sendCta"),
461
+ whileHover: { scale: 1.08 },
462
+ whileTap: { scale: .9 },
463
+ transition: {
464
+ type: "spring",
465
+ stiffness: 400,
466
+ damping: 22
467
+ },
468
+ className: a("flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition-colors", "bg-wx-primary text-wx-primary-fg hover:bg-wx-primary-hover"),
469
+ children: /* @__PURE__ */ m(s, { size: 14 })
470
+ })] })
471
+ ]
472
+ }, "voice-recorder");
473
+ }
474
+ function O({ Icon: t, onClick: n, ariaLabel: r, intent: i, size: o = 16 }) {
475
+ let s = c();
476
+ return /* @__PURE__ */ m(e.button, {
477
+ type: "button",
478
+ onClick: n,
479
+ "aria-label": r,
480
+ whileHover: { scale: 1.08 },
481
+ whileTap: { scale: .9 },
482
+ transition: {
483
+ type: "spring",
484
+ stiffness: 400,
485
+ damping: 22
486
+ },
487
+ ...s.parentHandlers,
488
+ className: a("flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition-colors", i === "primary" ? "bg-wx-primary text-wx-primary-fg hover:bg-wx-primary-hover" : "text-wx-fg-muted hover:bg-wx-bg-elevated hover:text-wx-fg"),
489
+ children: /* @__PURE__ */ m(t, {
490
+ ref: s.iconRef,
491
+ size: o
492
+ })
493
+ });
494
+ }
495
+ //#endregion
496
+ export { D as VoiceRecorderBar };
497
+
498
+ //# sourceMappingURL=widget-react-CPYwD6FR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-react-CPYwD6FR.js","names":[],"sources":["../node_modules/lucide-react/dist/esm/icons/square.mjs","../node_modules/wavesurfer.js/dist/plugins/record.esm.js","../components/widget/tabs/messages-tab/composer/voice-recorder-bar/helpers.ts","../components/widget/tabs/messages-tab/composer/voice-recorder-bar/index.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }]\n];\nconst Square = createLucideIcon(\"square\", __iconNode);\n\nexport { __iconNode, Square as default };\n//# sourceMappingURL=square.mjs.map\n","function i(i,t,e,s){return new(e||(e=Promise))((function(r,o){function n(i){try{d(s.next(i))}catch(i){o(i)}}function a(i){try{d(s.throw(i))}catch(i){o(i)}}function d(i){var t;i.done?r(i.value):(t=i.value,t instanceof e?t:new e((function(i){i(t)}))).then(n,a)}d((s=s.apply(i,t||[])).next())}))}\"function\"==typeof SuppressedError&&SuppressedError;class t{constructor(){this.listeners={}}on(i,t,e){if(this.listeners[i]||(this.listeners[i]=new Set),null==e?void 0:e.once){const e=(...s)=>{this.un(i,e),t(...s)};return this.listeners[i].add(e),()=>this.un(i,e)}return this.listeners[i].add(t),()=>this.un(i,t)}un(i,t){var e;null===(e=this.listeners[i])||void 0===e||e.delete(t)}once(i,t){return this.on(i,t,{once:!0})}unAll(){this.listeners={}}emit(i,...t){this.listeners[i]&&this.listeners[i].forEach((i=>i(...t)))}}class e extends t{constructor(i){super(),this.subscriptions=[],this.isDestroyed=!1,this.options=i}onInit(){}_init(i){this.isDestroyed&&(this.subscriptions=[],this.isDestroyed=!1),this.wavesurfer=i,this.onInit()}destroy(){this.emit(\"destroy\"),this.subscriptions.forEach((i=>i())),this.subscriptions=[],this.isDestroyed=!0,this.wavesurfer=void 0}}class s extends t{constructor(){super(...arguments),this.animationFrameId=null,this.isRunning=!1}start(){if(this.isRunning)return;this.isRunning=!0;const i=()=>{this.isRunning&&(this.emit(\"tick\"),this.animationFrameId=requestAnimationFrame(i))};i()}stop(){this.isRunning=!1,null!==this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}destroy(){this.stop()}}const r=100,o=[\"audio/webm\",\"audio/wav\",\"audio/mpeg\",\"audio/mp4\",\"audio/mp3\"];class n extends e{constructor(i){var t,e,r,o,n,a;super(Object.assign(Object.assign({},i),{audioBitsPerSecond:null!==(t=i.audioBitsPerSecond)&&void 0!==t?t:128e3,scrollingWaveform:null!==(e=i.scrollingWaveform)&&void 0!==e&&e,scrollingWaveformWindow:null!==(r=i.scrollingWaveformWindow)&&void 0!==r?r:5,continuousWaveform:null!==(o=i.continuousWaveform)&&void 0!==o&&o,renderRecordedAudio:null===(n=i.renderRecordedAudio)||void 0===n||n,mediaRecorderTimeslice:null!==(a=i.mediaRecorderTimeslice)&&void 0!==a?a:void 0})),this.stream=null,this.mediaRecorder=null,this.dataWindow=null,this.isWaveformPaused=!1,this.lastStartTime=0,this.lastDuration=0,this.duration=0,this.micStream=null,this.recordedBlobUrl=null,this.timer=new s,this.subscriptions.push(this.timer.on(\"tick\",(()=>{const i=performance.now()-this.lastStartTime;this.duration=this.isPaused()?this.duration:this.lastDuration+i,this.emit(\"record-progress\",this.duration)})))}static create(i){return new n(i||{})}renderMicStream(i){var t;const e=new AudioContext,s=e.createMediaStreamSource(i),o=e.createAnalyser();s.connect(o),(this.options.continuousWaveform||this.options.scrollingWaveform)&&(o.fftSize=32);const n=o.frequencyBinCount,a=new Float32Array(n);let d=0;this.wavesurfer&&(null!==(t=this.originalOptions)&&void 0!==t||(this.originalOptions=Object.assign({},this.wavesurfer.options)),this.wavesurfer.options.interact=!1,this.options.scrollingWaveform&&(this.wavesurfer.options.cursorWidth=0,this.wavesurfer.options.normalize=!0,this.wavesurfer.options.maxPeak=1));const h=setInterval((()=>{var i,t,e,s;if(!this.isWaveformPaused){if(o.getFloatTimeDomainData(a),this.options.scrollingWaveform){const i=Math.floor((this.options.scrollingWaveformWindow||0)*r);let t=0;for(let i=0;i<n;i++){const e=Math.abs(a[i]);e>t&&(t=e)}this.dataWindow||(this.dataWindow=new Float32Array(i));const e=new Float32Array(i);if(this.dataWindow&&this.dataWindow.length>0){const t=i-1,s=this.dataWindow.slice(-t);e.set(s,0)}e[i-1]=t,this.dataWindow=e}else if(this.options.continuousWaveform){if(!this.dataWindow){const e=this.options.continuousWaveformDuration?Math.round(this.options.continuousWaveformDuration*r):(null!==(t=null===(i=this.wavesurfer)||void 0===i?void 0:i.getWidth())&&void 0!==t?t:0)*window.devicePixelRatio;this.dataWindow=new Float32Array(e)}let e=0;for(let i=0;i<n;i++){const t=Math.abs(a[i]);t>e&&(e=t)}if(d+1>this.dataWindow.length){const i=new Float32Array(2*this.dataWindow.length);i.set(this.dataWindow,0),this.dataWindow=i}this.dataWindow[d]=e,d++}else this.dataWindow=a;if(this.wavesurfer){const i=(null!==(s=null===(e=this.dataWindow)||void 0===e?void 0:e.length)&&void 0!==s?s:0)/r;this.wavesurfer.load(\"\",[this.dataWindow],this.options.scrollingWaveform?this.options.scrollingWaveformWindow:i).then((()=>{this.wavesurfer&&this.options.continuousWaveform&&(this.wavesurfer.setTime(this.getDuration()/1e3),this.wavesurfer.options.minPxPerSec||this.wavesurfer.setOptions({minPxPerSec:this.wavesurfer.getWidth()/this.wavesurfer.getDuration()}))})).catch((i=>{console.error(\"Error rendering real-time recording data:\",i)}))}}}),10);return{onDestroy:()=>{clearInterval(h),null==s||s.disconnect(),null==e||e.close()},onEnd:()=>{this.isWaveformPaused=!0,this.stopMic()}}}startMic(t){return i(this,void 0,void 0,(function*(){let i;this.micStream&&this.stopMic();try{i=yield navigator.mediaDevices.getUserMedia({audio:null==t||t})}catch(i){throw new Error(\"Error accessing the microphone: \"+i.message)}const e=this.renderMicStream(i);return this.micStream=e,this.unsubscribeDestroy=this.once(\"destroy\",e.onDestroy),this.unsubscribeRecordEnd=this.once(\"record-end\",e.onEnd),this.stream=i,i}))}stopMic(){var i,t,e;null===(i=this.micStream)||void 0===i||i.onDestroy(),null===(t=this.unsubscribeDestroy)||void 0===t||t.call(this),null===(e=this.unsubscribeRecordEnd)||void 0===e||e.call(this),this.micStream=null,this.unsubscribeDestroy=void 0,this.unsubscribeRecordEnd=void 0,this.stream&&(this.stream.getTracks().forEach((i=>i.stop())),this.stream=null,this.mediaRecorder=null)}startRecording(t){return i(this,void 0,void 0,(function*(){const i=this.stream||(yield this.startMic(t));this.dataWindow=null;const e=this.mediaRecorder||new MediaRecorder(i,{mimeType:this.options.mimeType||o.find((i=>MediaRecorder.isTypeSupported(i))),audioBitsPerSecond:this.options.audioBitsPerSecond});this.mediaRecorder=e,this.stopRecording();const s=[];e.ondataavailable=i=>{i.data.size>0&&s.push(i.data),this.emit(\"record-data-available\",i.data)};const r=i=>{var t;const r=new Blob(s,{type:e.mimeType});this.emit(i,r),this.options.renderRecordedAudio&&(this.applyOriginalOptionsIfNeeded(),this.recordedBlobUrl&&URL.revokeObjectURL(this.recordedBlobUrl),this.recordedBlobUrl=URL.createObjectURL(r),null===(t=this.wavesurfer)||void 0===t||t.load(this.recordedBlobUrl))};e.onpause=()=>r(\"record-pause\"),e.onstop=()=>r(\"record-end\"),e.start(this.options.mediaRecorderTimeslice),this.lastStartTime=performance.now(),this.lastDuration=0,this.duration=0,this.isWaveformPaused=!1,this.timer.start(),this.emit(\"record-start\")}))}getDuration(){return this.duration}isRecording(){var i;return\"recording\"===(null===(i=this.mediaRecorder)||void 0===i?void 0:i.state)}isPaused(){var i;return\"paused\"===(null===(i=this.mediaRecorder)||void 0===i?void 0:i.state)}isActive(){var i;return\"inactive\"!==(null===(i=this.mediaRecorder)||void 0===i?void 0:i.state)}stopRecording(){var i;this.isActive()&&(null===(i=this.mediaRecorder)||void 0===i||i.stop(),this.timer.stop())}pauseRecording(){var i,t;this.isRecording()&&(this.isWaveformPaused=!0,null===(i=this.mediaRecorder)||void 0===i||i.requestData(),null===(t=this.mediaRecorder)||void 0===t||t.pause(),this.timer.stop(),this.lastDuration=this.duration)}resumeRecording(){var i;this.isPaused()&&(this.isWaveformPaused=!1,null===(i=this.mediaRecorder)||void 0===i||i.resume(),this.timer.start(),this.lastStartTime=performance.now(),this.emit(\"record-resume\"))}static getAvailableAudioDevices(){return i(this,void 0,void 0,(function*(){return navigator.mediaDevices.enumerateDevices().then((i=>i.filter((i=>\"audioinput\"===i.kind))))}))}destroy(){this.applyOriginalOptionsIfNeeded(),super.destroy(),this.stopRecording(),this.stopMic(),this.recordedBlobUrl&&(URL.revokeObjectURL(this.recordedBlobUrl),this.recordedBlobUrl=null)}applyOriginalOptionsIfNeeded(){this.wavesurfer&&this.originalOptions&&(this.wavesurfer.setOptions(this.originalOptions),delete this.originalOptions)}}export{n as default};\n","/**\n * Pure helpers for the voice recorder bar — duration formatting, MIME\n * selection, and base64 decoding. Kept out of the component so the\n * formatting + MIME logic can be unit-tested in isolation.\n */\n\n/** Format a second count as `m:ss` (e.g. 75 → \"1:15\"). Clamps negatives. */\nexport function formatDuration(totalSec: number): string {\n const safe = Math.max(0, totalSec);\n const m = Math.floor(safe / 60);\n const s = safe % 60;\n return `${m}:${s.toString().padStart(2, \"0\")}`;\n}\n\n/**\n * Per-browser MIME pick. Chrome/Firefox prefer `audio/webm`; Safari\n * only supports `audio/mp4`. Returning `null` lets the MediaRecorder\n * pick its own default — the BE accepts both opus + aac via the\n * existing audio-mime allowlist.\n */\nexport function pickMime(): string | null {\n if (typeof MediaRecorder === \"undefined\") return null;\n const candidates = [\"audio/webm;codecs=opus\", \"audio/webm\", \"audio/mp4\", \"audio/ogg\"];\n for (const m of candidates) {\n if (MediaRecorder.isTypeSupported?.(m)) return m;\n }\n return null;\n}\n\n/** Decode a Blob to its raw base64 payload (strips the data-URL prefix). */\nexport async function blobToBase64(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const result = reader.result;\n if (typeof result !== \"string\") {\n reject(new Error(\"FileReader returned non-string result\"));\n return;\n }\n const comma = result.indexOf(\",\");\n resolve(comma >= 0 ? result.slice(comma + 1) : result);\n };\n reader.onerror = () => reject(reader.error ?? new Error(\"read failed\"));\n reader.readAsDataURL(blob);\n });\n}\n","\"use client\";\n\n// `lucide-animated` has no `SendIcon` (or `SquareIcon` runtime export\n// — typing-only). Use static lucide-react for both glyphs; the\n// composer's morph button also uses the same `Send` icon, so the\n// visitor sees a consistent send affordance across the widget.\nimport { Send, Square } from \"lucide-react\";\nimport { motion } from \"motion/react\";\nimport { useTranslations } from \"next-intl\";\nimport { type ComponentType, useEffect, useRef, useState } from \"react\";\nimport WaveSurfer from \"wavesurfer.js\";\nimport RecordPlugin from \"wavesurfer.js/dist/plugins/record.esm.js\";\nimport { PauseIcon, PlayIcon, XIcon } from \"@/components/widget/icons/animated\";\nimport { useIconHover } from \"@/lib/use-icon-hover\";\nimport { cn } from \"@/lib/utils\";\nimport { blobToBase64, formatDuration, pickMime } from \"./helpers\";\n\nexport interface VoiceRecording {\n /** MIME of the captured blob (`audio/webm;codecs=opus` on Chrome,\n * `audio/mp4` on Safari). */\n mimetype: string;\n /** Raw base64 payload — no `data:…;base64,` prefix; ready for the\n * BE's `uploadVisitorMedia` mutation. */\n base64: string;\n /** Decoded byte length — caller compares against the 10 MB cap. */\n size: number;\n /** `voice-<ts>.<ext>` — picked from the recorder's mimetype. */\n filename: string;\n}\n\ninterface VoiceRecorderBarProps {\n /** Visitor tapped Send in preview — ship the blob + close. */\n onComplete: (rec: VoiceRecording) => void;\n /** Visitor tapped Cancel at any phase — close, no upload. */\n onCancel: () => void;\n /** Mic permission denied / no MediaRecorder support / etc. */\n onError: (kind: \"denied\" | \"unsupported\" | \"failed\") => void;\n}\n\n/**\n * Replaces the chat composer while the visitor is recording a voice\n * note. Two phases — `recording` → `preview` — and a hand-rolled\n * `MediaRecorder` for capture so we don't depend on the\n * `wavesurfer.js` Record plugin's internal `record-end` plumbing\n * (which has subtle event-unsubscribe races when its `stopMic` runs;\n * the symptom was the Stop button silently doing nothing in some\n * browsers). The plugin is still in play — but only for the live\n * mic-stream visualisation; the recorded blob comes from our own\n * recorder.\n *\n * **Lifecycle**:\n * - mount → ask for mic permission, hand the stream to the\n * plugin for the live waveform AND start our own\n * `MediaRecorder` collecting chunks.\n * - stop → stop OUR recorder; its `onstop` builds the blob,\n * stops the plugin's live render, loads the blob into\n * wavesurfer for playback, and flips phase to `preview`.\n * - cancel → bail (no upload).\n * - send → hand the cached blob to `onComplete`.\n *\n * **Brand fidelity**: wavesurfer canvas can't resolve CSS variables;\n * we read `--wx-primary` / `--wx-fg-muted` from the document root on\n * mount and feed real hex values to the instance so the waveform\n * matches the operator's accent in both themes.\n */\nexport function VoiceRecorderBar({ onComplete, onCancel, onError }: VoiceRecorderBarProps) {\n const t = useTranslations(\"messages\");\n const containerRef = useRef<HTMLDivElement | null>(null);\n const wavesurferRef = useRef<WaveSurfer | null>(null);\n // Narrow shape of the plugin API surface we actually call. We\n // don't subscribe to its events — we just use it for mic + waveform.\n const recordPluginRef = useRef<{\n startMic: () => Promise<MediaStream>;\n stopMic: () => void;\n } | null>(null);\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const chunksRef = useRef<Blob[]>([]);\n const tickIntervalRef = useRef<number | null>(null);\n\n const [phase, setPhase] = useState<\"recording\" | \"preview\">(\"recording\");\n const [elapsedSec, setElapsedSec] = useState(0);\n const [previewPlaying, setPreviewPlaying] = useState(false);\n // Encoded blob — held so Send fires onComplete with no second\n // base64 round-trip.\n const recordedRef = useRef<VoiceRecording | null>(null);\n // True only when the visitor explicitly cancelled (X button).\n // Different from the per-effect \"strict-mode cancelled\" flag —\n // that one lives inside the effect closure so the React 18\n // dev-strict double-mount doesn't wedge state.\n const userCancelledRef = useRef(false);\n\n // Mount-only — the recorder instance is single-shot per session, so\n // `onError` (and the other captured callbacks) are deliberately NOT\n // deps: re-running this would re-acquire the mic on every parent\n // render that passes a fresh callback identity.\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional mount-only mic-acquisition effect — see note above\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n if (typeof window === \"undefined\" || !window.MediaRecorder) {\n onError(\"unsupported\");\n return;\n }\n\n // `effectCancelled` is captured in this effect's closure ONLY —\n // each strict-mode re-mount gets its own. The old ref-based flag\n // was shared across both runs: the first cleanup set it to true,\n // the second effect's async `startMic().then(...)` then bailed\n // because the ref was still true. Result on dev: recorder never\n // even started. Local-scoping the flag fixes it.\n let effectCancelled = false;\n userCancelledRef.current = false;\n\n // Read the theme tokens off the CONTAINER, not\n // `document.documentElement` — in the React-component embed the\n // `--wx-*` vars live on the Shadow DOM host, never on the host\n // page's `<html>`, so `documentElement` would resolve to empty and\n // the waveform would always fall back to the hardcoded colours.\n // The container inherits the vars in every embed mode.\n const styles = getComputedStyle(container);\n const primary = styles.getPropertyValue(\"--wx-primary\").trim() || \"#5b6cff\";\n const muted = styles.getPropertyValue(\"--wx-fg-muted\").trim() || \"#6b7280\";\n\n const ws = WaveSurfer.create({\n container,\n waveColor: muted,\n progressColor: primary,\n cursorColor: primary,\n cursorWidth: 2,\n height: 32,\n barWidth: 2,\n barGap: 2,\n barRadius: 2,\n interact: true,\n // `continuousWaveform` makes wavesurfer's internal scroll element\n // wider than the bar — it would otherwise paint its own\n // horizontal scrollbar under the waveform. Visitors never scroll\n // a live recording / short voice note, so hide it.\n hideScrollbar: true,\n });\n wavesurferRef.current = ws;\n\n ws.on(\"play\", () => setPreviewPlaying(true));\n ws.on(\"pause\", () => setPreviewPlaying(false));\n ws.on(\"finish\", () => setPreviewPlaying(false));\n\n const plugin = ws.registerPlugin(\n RecordPlugin.create({\n continuousWaveform: true,\n continuousWaveformDuration: 60,\n // `renderRecordedAudio: false` — we drive the playback load\n // ourselves once recording stops, so the plugin shouldn't\n // try to load its own (empty) buffer.\n renderRecordedAudio: false,\n }),\n ) as unknown as NonNullable<typeof recordPluginRef.current>;\n recordPluginRef.current = plugin;\n\n // Local mirrors captured in this effect's closure — used by\n // cleanup so we tear down THIS effect's resources, not whatever\n // the (newer) component instance has set into the shared refs.\n let localTickInterval: number | null = null;\n let localRecorder: MediaRecorder | null = null;\n\n /**\n * Two-step bring-up so the plugin's live waveform AND our\n * MediaRecorder both feed off the same mic stream:\n *\n * 1. `plugin.startMic()` does `getUserMedia` + sets up an\n * AudioContext → AnalyserNode → canvas-drawing interval.\n * 2. We attach `MediaRecorder` to that stream for capture.\n *\n * If `getUserMedia` rejects, surface as `denied`; everything\n * else lands in `failed`.\n */\n plugin\n .startMic()\n .then((stream) => {\n if (effectCancelled || userCancelledRef.current) {\n // Strict-mode tear-down: cleanup already ran (it called\n // plugin.stopMic() while `this.stream` was still null\n // because getUserMedia hadn't resolved yet). Now that\n // getUserMedia HAS resolved, the plugin set its `stream`\n // to this freshly-acquired one — nobody will release it\n // unless we do. Stop the tracks here so the OS mic\n // indicator clears.\n try {\n stream.getTracks().forEach((track) => {\n track.stop();\n });\n } catch {}\n try {\n plugin.stopMic();\n } catch {}\n return;\n }\n const mime = pickMime();\n const recorder = mime\n ? new MediaRecorder(stream, { mimeType: mime })\n : new MediaRecorder(stream);\n mediaRecorderRef.current = recorder;\n localRecorder = recorder;\n chunksRef.current = [];\n recorder.addEventListener(\"dataavailable\", (e) => {\n if (e.data && e.data.size > 0) chunksRef.current.push(e.data);\n });\n recorder.addEventListener(\"stop\", () => {\n // strict-mode tear-down OR user cancel → discard the take.\n if (effectCancelled || userCancelledRef.current) return;\n // Release the mic + live-waveform render IMMEDIATELY (not\n // after base64 encoding). FileReader can take hundreds of\n // ms on long recordings — without this the browser keeps\n // the \"tab is using microphone\" indicator on for that\n // whole window after the visitor already tapped Stop.\n try {\n plugin.stopMic();\n } catch {}\n if (localTickInterval !== null) {\n clearInterval(localTickInterval);\n localTickInterval = null;\n tickIntervalRef.current = null;\n }\n const finalMime = recorder.mimeType || mime || \"audio/webm\";\n const blob = new Blob(chunksRef.current, { type: finalMime });\n blobToBase64(blob)\n .then((base64) => {\n if (effectCancelled || userCancelledRef.current) return;\n const ext = finalMime.includes(\"mp4\") ? \"mp4\" : \"webm\";\n // `recorder.mimeType` carries the codec param\n // (`audio/webm;codecs=opus`). The upload allowlist (client +\n // the BE's `WebUploadService.ALLOWED_MIMES`) matches the BARE\n // type `audio/webm`, so the codec suffix 415s. Strip it for the\n // upload — the blob above keeps the full type for local\n // playback, where the codec still gets inferred.\n const uploadMime = finalMime.split(\";\")[0].trim();\n recordedRef.current = {\n base64,\n mimetype: uploadMime,\n size: blob.size,\n filename: `voice-${Date.now()}.${ext}`,\n };\n // Load the playable blob THEN reset cursor +\n // re-enable seeking:\n // 1. The plugin's `renderMicStream` force-sets\n // `interact: false` and (because we set\n // `renderRecordedAudio: false`) never restores\n // it — re-flip here so the visitor can scrub.\n // 2. During recording the plugin called\n // `setTime(duration / 1000)` on every tick, so\n // after stop the cursor sits at the end. Reset\n // to 0 so playback starts at the beginning.\n //\n // `loadBlob(blob)` — NOT `load(objectURL)`: wavesurfer's\n // `load()` does a `fetch()` of the URL, and a host page\n // with a strict `connect-src` CSP (no `blob:`) blocks\n // fetching `blob:` URLs — the preview would hang on a\n // forever spinner. `loadBlob` decodes the in-memory Blob\n // directly, no network request, no CSP surface.\n ws.loadBlob(blob)\n .then(() => {\n if (effectCancelled || userCancelledRef.current) return;\n try {\n ws.setOptions({ interact: true });\n } catch {}\n try {\n ws.setTime(0);\n } catch {}\n })\n .catch(() => {});\n setPhase(\"preview\");\n })\n .catch(() => onError(\"failed\"));\n });\n recorder.start();\n\n // Drive the duration counter from our own tick — independent\n // of the plugin so the counter survives any plugin oddity.\n // Only setElapsedSec when the displayed second changes so we\n // don't trigger 10 renders/sec.\n const startedAt = performance.now();\n localTickInterval = window.setInterval(() => {\n const ms = performance.now() - startedAt;\n const sec = Math.floor(ms / 1000);\n setElapsedSec((prev) => (prev === sec ? prev : sec));\n }, 250);\n tickIntervalRef.current = localTickInterval;\n })\n .catch((err: Error) => {\n if (effectCancelled) return;\n const msg = err?.message ?? \"\";\n onError(msg.includes(\"Permission\") || msg.includes(\"denied\") ? \"denied\" : \"failed\");\n });\n\n return () => {\n effectCancelled = true;\n if (localTickInterval !== null) {\n clearInterval(localTickInterval);\n }\n try {\n if (localRecorder?.state === \"recording\") {\n localRecorder.stop();\n }\n } catch {}\n try {\n plugin.stopMic();\n } catch {}\n ws.destroy();\n // Only null shared refs if this effect's instance is still the\n // one parked there — protects against the strict-mode race\n // where the second effect's setup races past this cleanup.\n if (wavesurferRef.current === ws) wavesurferRef.current = null;\n if (recordPluginRef.current === plugin) recordPluginRef.current = null;\n if (mediaRecorderRef.current === localRecorder) {\n mediaRecorderRef.current = null;\n }\n };\n }, []);\n\n const handleCancel = () => {\n userCancelledRef.current = true;\n try {\n if (mediaRecorderRef.current?.state === \"recording\") {\n mediaRecorderRef.current.stop();\n }\n } catch {}\n try {\n recordPluginRef.current?.stopMic();\n } catch {}\n try {\n wavesurferRef.current?.pause();\n } catch {}\n onCancel();\n };\n\n const handleStop = () => {\n // Stops OUR MediaRecorder. Its `stop` listener does the rest —\n // builds the blob, swaps wavesurfer to playback mode, flips\n // phase to `preview`.\n try {\n if (mediaRecorderRef.current?.state === \"recording\") {\n mediaRecorderRef.current.stop();\n }\n } catch {}\n };\n\n const handlePreviewToggle = () => {\n const ws = wavesurferRef.current;\n if (!ws) return;\n if (ws.isPlaying()) {\n ws.pause();\n } else {\n ws.play();\n }\n };\n\n const handleSend = () => {\n const rec = recordedRef.current;\n if (!rec) return;\n onComplete(rec);\n };\n\n return (\n <motion.div\n key=\"voice-recorder\"\n initial={{ opacity: 0, y: 6 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.18 }}\n className={cn(\n \"flex items-center gap-1.5 rounded-wx-lg border border-wx-border bg-wx-bg px-2 py-2\",\n )}\n >\n <IconBtn\n Icon={XIcon}\n onClick={handleCancel}\n ariaLabel={t(\"cancelRecording\")}\n intent=\"ghost\"\n />\n\n {/* `min-w-0` on BOTH flex levels is load-bearing: a flex item's\n default `min-width: auto` won't let it shrink below its\n content's intrinsic width. wavesurfer's continuous-waveform\n canvas can be far wider than a narrow embedded preview — so\n without `min-w-0` the container refuses to shrink, grows to\n fit, wavesurfer's ResizeObserver re-renders even wider, and\n the bar oscillates forever. `overflow-hidden` on the\n waveform host clips any residual overscroll. */}\n <div className=\"flex h-9 min-w-0 flex-1 items-center gap-2 rounded-full bg-wx-bg-elevated px-3\">\n {phase === \"recording\" && (\n <span\n aria-hidden=\"true\"\n className=\"h-2 w-2 shrink-0 animate-pulse rounded-full bg-wx-danger\"\n />\n )}\n <div\n ref={containerRef}\n aria-hidden=\"true\"\n className={cn(\n \"min-w-0 flex-1 overflow-hidden\",\n // Click-to-seek only matters in preview; during recording\n // the canvas has nothing to seek to and we don't want\n // it competing with action buttons for taps.\n phase !== \"preview\" && \"pointer-events-none\",\n )}\n />\n <span className=\"shrink-0 font-mono text-xs tabular-nums text-wx-fg-muted\">\n {formatDuration(elapsedSec)}\n </span>\n </div>\n\n {phase === \"recording\" && (\n <motion.button\n type=\"button\"\n onClick={handleStop}\n aria-label={t(\"stopRecording\")}\n whileHover={{ scale: 1.08 }}\n whileTap={{ scale: 0.9 }}\n transition={{ type: \"spring\", stiffness: 400, damping: 22 }}\n className={cn(\n \"flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition-colors\",\n \"text-wx-fg-muted hover:bg-wx-bg-elevated hover:text-wx-fg\",\n )}\n >\n <Square size={14} />\n </motion.button>\n )}\n\n {phase === \"preview\" && (\n <>\n <IconBtn\n Icon={previewPlaying ? PauseIcon : PlayIcon}\n onClick={handlePreviewToggle}\n ariaLabel={previewPlaying ? t(\"pauseRecording\") : t(\"playPreview\")}\n intent=\"ghost\"\n />\n <motion.button\n type=\"button\"\n onClick={handleSend}\n aria-label={t(\"sendCta\")}\n whileHover={{ scale: 1.08 }}\n whileTap={{ scale: 0.9 }}\n transition={{ type: \"spring\", stiffness: 400, damping: 22 }}\n className={cn(\n \"flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition-colors\",\n \"bg-wx-primary text-wx-primary-fg hover:bg-wx-primary-hover\",\n )}\n >\n <Send size={14} />\n </motion.button>\n </>\n )}\n </motion.div>\n );\n}\n\n/**\n * Tight icon button for the recorder bar. Every glyph in here is a\n * `lucide-animated` icon, which wraps its SVG in a `<div>` that\n * exposes `startAnimation` / `stopAnimation` on its ref handle —\n * `useIconHover` propagates the button-level hover/focus to those\n * methods so the icon animates only when the visitor hovers the tap\n * target, not the SVG itself (the SVG sits behind the button's\n * hit area, so direct hover never works the way visitors expect).\n *\n * Type-wise, every lucide-animated icon's ref handle implements the\n * same `startAnimation?()` / `stopAnimation?()` shape — the union of\n * those handles is structurally compatible with `useIconHover`'s\n * default, so a single helper covers every icon we use.\n */\ntype LucideAnimatedHandle = {\n // Match `lucide-animated`'s per-icon `*IconHandle` types, which declare\n // these as non-optional. Marking them optional here makes the local\n // type unassignable from the real handle (TS can't widen `() => void`\n // to `(() => void) | undefined` at a covariant ref position), which\n // surfaces as the `Icon={XIcon}` build error.\n startAnimation: () => void;\n stopAnimation: () => void;\n};\n\ntype LucideAnimatedIcon = ComponentType<{\n ref?: React.Ref<LucideAnimatedHandle>;\n size?: number;\n}>;\n\nfunction IconBtn({\n Icon,\n onClick,\n ariaLabel,\n intent,\n size = 16,\n}: {\n Icon: LucideAnimatedIcon;\n onClick: () => void;\n ariaLabel: string;\n intent: \"ghost\" | \"primary\";\n size?: number;\n}) {\n const hover = useIconHover<LucideAnimatedHandle>();\n return (\n <motion.button\n type=\"button\"\n onClick={onClick}\n aria-label={ariaLabel}\n whileHover={{ scale: 1.08 }}\n whileTap={{ scale: 0.9 }}\n transition={{ type: \"spring\", stiffness: 400, damping: 22 }}\n {...hover.parentHandlers}\n className={cn(\n \"flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition-colors\",\n intent === \"primary\"\n ? \"bg-wx-primary text-wx-primary-fg hover:bg-wx-primary-hover\"\n : \"text-wx-fg-muted hover:bg-wx-bg-elevated hover:text-wx-fg\",\n )}\n >\n <Icon ref={hover.iconRef} size={size} />\n </motion.button>\n );\n}\n"],"x_google_ignoreList":[0,1],"mappings":";;;;;;;;;;;AAYA,IAAM,IAAS,EAAiB,UAAU,CAFxC,CAAC,QAAQ;CAAE,OAAO;CAAM,QAAQ;CAAM,GAAG;CAAK,GAAG;CAAK,IAAI;CAAK,KAAK;CAAU,CAAC,CAEvC,CAAW;;;ACZrD,SAAS,EAAE,GAAE,GAAE,GAAE,GAAE;CAAC,OAAO,KAAI,MAAI,IAAE,WAAW,SAAS,GAAE,GAAE;EAAC,SAAS,EAAE,GAAE;GAAC,IAAG;IAAC,EAAE,EAAE,KAAK,EAAE,CAAC;YAAO,GAAE;IAAC,EAAE,EAAE;;;EAAE,SAAS,EAAE,GAAE;GAAC,IAAG;IAAC,EAAE,EAAE,MAAM,EAAE,CAAC;YAAO,GAAE;IAAC,EAAE,EAAE;;;EAAE,SAAS,EAAE,GAAE;GAAC,IAAI;GAAE,EAAE,OAAK,EAAE,EAAE,MAAM,IAAE,IAAE,EAAE,OAAM,aAAa,IAAE,IAAE,IAAI,GAAG,SAAS,GAAE;IAAC,EAAE,EAAE;MAAG,EAAE,KAAK,GAAE,EAAE;;EAAC,GAAG,IAAE,EAAE,MAAM,GAAE,KAAG,EAAE,CAAC,EAAE,MAAM,CAAC;IAAG;;AAAqD,IAAM,IAAN,MAAO;CAAC,cAAa;EAAC,KAAK,YAAU,EAAE;;CAAC,GAAG,GAAE,GAAE,GAAE;EAAC,IAAG,KAAK,UAAU,OAAK,KAAK,UAAU,qBAAG,IAAI,KAAG,GAAQ,GAAW,MAAK;GAAC,IAAM,KAAG,GAAG,MAAI;IAAC,KAAK,GAAG,GAAE,EAAE,EAAC,EAAE,GAAG,EAAE;;GAAE,OAAO,KAAK,UAAU,GAAG,IAAI,EAAE,QAAK,KAAK,GAAG,GAAE,EAAE;;EAAC,OAAO,KAAK,UAAU,GAAG,IAAI,EAAE,QAAK,KAAK,GAAG,GAAE,EAAE;;CAAC,GAAG,GAAE,GAAE;EAAC,IAAI;EAAE,CAAQ,IAAE,KAAK,UAAU,OAAzB,QAA0C,EAAE,OAAO,EAAE;;CAAC,KAAK,GAAE,GAAE;EAAC,OAAO,KAAK,GAAG,GAAE,GAAE,EAAC,MAAK,CAAC,GAAE,CAAC;;CAAC,QAAO;EAAC,KAAK,YAAU,EAAE;;CAAC,KAAK,GAAE,GAAG,GAAE;EAAC,KAAK,UAAU,MAAI,KAAK,UAAU,GAAG,UAAS,MAAG,EAAE,GAAG,EAAE,EAAE;;GAAQ,IAAN,cAAgB,EAAC;CAAC,YAAY,GAAE;EAAC,OAAO,EAAC,KAAK,gBAAc,EAAE,EAAC,KAAK,cAAY,CAAC,GAAE,KAAK,UAAQ;;CAAE,SAAQ;CAAE,MAAM,GAAE;EAAC,KAAK,gBAAc,KAAK,gBAAc,EAAE,EAAC,KAAK,cAAY,CAAC,IAAG,KAAK,aAAW,GAAE,KAAK,QAAQ;;CAAC,UAAS;EAAC,KAAK,KAAK,UAAU,EAAC,KAAK,cAAc,UAAS,MAAG,GAAG,EAAE,EAAC,KAAK,gBAAc,EAAE,EAAC,KAAK,cAAY,CAAC,GAAE,KAAK,aAAW,KAAK;;GAAS,IAAN,cAAgB,EAAC;CAAC,cAAa;EAAC,MAAM,GAAG,UAAU,EAAC,KAAK,mBAAiB,MAAK,KAAK,YAAU,CAAC;;CAAE,QAAO;EAAC,IAAG,KAAK,WAAU;EAAO,KAAK,YAAU,CAAC;EAAE,IAAM,UAAM;GAAC,KAAK,cAAY,KAAK,KAAK,OAAO,EAAC,KAAK,mBAAiB,sBAAsB,EAAE;;EAAG,GAAG;;CAAC,OAAM;EAAC,KAAK,YAAU,CAAC,GAAS,KAAK,qBAAZ,SAA+B,qBAAqB,KAAK,iBAAiB,EAAC,KAAK,mBAAiB;;CAAM,UAAS;EAAC,KAAK,MAAM;;GAAQ,IAAE,KAAI,IAAE;CAAC;CAAa;CAAY;CAAa;CAAY;CAAY,EAAO,IAAN,MAAM,UAAU,EAAC;CAAC,YAAY,GAAE;EAAC,IAAM,GAAI,GAAE;EAAI,MAAM,OAAO,OAAO,OAAO,OAAO,EAAE,EAAC,EAAE,EAAC;GAAC,oBAA6B,EAAE,sBAAkC;GAAM,oBAA0B,IAAE,EAAE,sBAAZ,QAA4C;GAAE,yBAAkC,EAAE,2BAAuC;GAAE,qBAA2B,IAAE,EAAE,uBAAZ,QAA6C;GAAE,sBAA4B,IAAE,EAAE,wBAAZ,QAA8C;GAAE,wBAAiC,EAAE,0BAAsC,KAAK;GAAE,CAAC,CAAC,EAAC,KAAK,SAAO,MAAK,KAAK,gBAAc,MAAK,KAAK,aAAW,MAAK,KAAK,mBAAiB,CAAC,GAAE,KAAK,gBAAc,GAAE,KAAK,eAAa,GAAE,KAAK,WAAS,GAAE,KAAK,YAAU,MAAK,KAAK,kBAAgB,MAAK,KAAK,QAAM,IAAI,GAAC,EAAC,KAAK,cAAc,KAAK,KAAK,MAAM,GAAG,eAAY;GAAC,IAAM,IAAE,YAAY,KAAK,GAAC,KAAK;GAAc,KAAK,WAAS,KAAK,UAAU,GAAC,KAAK,WAAS,KAAK,eAAa,GAAE,KAAK,KAAK,mBAAkB,KAAK,SAAS;KAAG,CAAC;;CAAC,OAAO,OAAO,GAAE;EAAC,OAAO,IAAI,EAAE,KAAG,EAAE,CAAC;;CAAC,gBAAgB,GAAE;EAAO,IAAM,IAAE,IAAI,cAAY,EAAC,IAAE,EAAE,wBAAwB,EAAE,EAAC,IAAE,EAAE,gBAAgB;EAAC,EAAE,QAAQ,EAAE,GAAE,KAAK,QAAQ,sBAAoB,KAAK,QAAQ,uBAAqB,EAAE,UAAQ;EAAI,IAAM,IAAE,EAAE,mBAAkB,IAAE,IAAI,aAAa,EAAE,EAAK,IAAE;EAAE,KAAK,eAAuB,KAAK,oBAA+B,KAAK,kBAAgB,OAAO,OAAO,EAAE,EAAC,KAAK,WAAW,QAAQ,GAAE,KAAK,WAAW,QAAQ,WAAS,CAAC,GAAE,KAAK,QAAQ,sBAAoB,KAAK,WAAW,QAAQ,cAAY,GAAE,KAAK,WAAW,QAAQ,YAAU,CAAC,GAAE,KAAK,WAAW,QAAQ,UAAQ;EAAI,IAAM,IAAE,mBAAiB;GAAa,IAAG,CAAC,KAAK,kBAAiB;IAAC,IAAG,EAAE,uBAAuB,EAAE,EAAC,KAAK,QAAQ,mBAAkB;KAAC,IAAM,IAAE,KAAK,OAAO,KAAK,QAAQ,2BAAyB,KAAG,EAAE,EAAK,IAAE;KAAE,KAAI,IAAI,IAAE,GAAE,IAAE,GAAE,KAAI;MAAC,IAAM,IAAE,KAAK,IAAI,EAAE,GAAG;MAAC,IAAE,MAAI,IAAE;;KAAG,KAAK,eAAa,KAAK,aAAW,IAAI,aAAa,EAAE;KAAE,IAAM,IAAE,IAAI,aAAa,EAAE;KAAC,IAAG,KAAK,cAAY,KAAK,WAAW,SAAO,GAAE;MAAC,IAAM,IAAE,IAAE,GAAE,IAAE,KAAK,WAAW,MAAM,CAAC,EAAE;MAAC,EAAE,IAAI,GAAE,EAAE;;KAAC,EAAE,IAAE,KAAG,GAAE,KAAK,aAAW;WAAO,IAAG,KAAK,QAAQ,oBAAmB;KAAC,IAAG,CAAC,KAAK,YAAW;MAAC,IAAM,IAAE,KAAK,QAAQ,6BAA2B,KAAK,MAAM,KAAK,QAAQ,6BAA2B,EAAE,IAAsB,KAAK,YAAiC,UAAU,IAAgB,KAAG,OAAO;MAAiB,KAAK,aAAW,IAAI,aAAa,EAAE;;KAAC,IAAI,IAAE;KAAE,KAAI,IAAI,IAAE,GAAE,IAAE,GAAE,KAAI;MAAC,IAAM,IAAE,KAAK,IAAI,EAAE,GAAG;MAAC,IAAE,MAAI,IAAE;;KAAG,IAAG,IAAE,IAAE,KAAK,WAAW,QAAO;MAAC,IAAM,IAAE,IAAI,aAAa,IAAE,KAAK,WAAW,OAAO;MAAC,EAAE,IAAI,KAAK,YAAW,EAAE,EAAC,KAAK,aAAW;;KAAE,KAAK,WAAW,KAAG,GAAE;WAAS,KAAK,aAAW;IAAE,IAAG,KAAK,YAAW;KAAC,IAAM,KAAuB,KAAK,YAAiC,UAAsB,KAAG;KAAE,KAAK,WAAW,KAAK,IAAG,CAAC,KAAK,WAAW,EAAC,KAAK,QAAQ,oBAAkB,KAAK,QAAQ,0BAAwB,EAAE,CAAC,YAAU;MAAC,KAAK,cAAY,KAAK,QAAQ,uBAAqB,KAAK,WAAW,QAAQ,KAAK,aAAa,GAAC,IAAI,EAAC,KAAK,WAAW,QAAQ,eAAa,KAAK,WAAW,WAAW,EAAC,aAAY,KAAK,WAAW,UAAU,GAAC,KAAK,WAAW,aAAa,EAAC,CAAC;QAAI,CAAC,QAAO,MAAG;MAAC,QAAQ,MAAM,6CAA4C,EAAE;QAAG;;;MAAK,GAAG;EAAC,OAAM;GAAC,iBAAc;IAAC,cAAc,EAAE,EAAO,GAAK,YAAY,EAAO,GAAK,OAAO;;GAAE,aAAU;IAAC,KAAK,mBAAiB,CAAC,GAAE,KAAK,SAAS;;GAAE;;CAAC,SAAS,GAAE;EAAC,OAAO,EAAE,MAAK,KAAK,GAAE,KAAK,IAAG,aAAW;GAAC,IAAI;GAAE,KAAK,aAAW,KAAK,SAAS;GAAC,IAAG;IAAC,IAAE,MAAM,UAAU,aAAa,aAAa,EAAC,OAAY,KAAN,QAAS,GAAE,CAAC;YAAO,GAAE;IAAC,MAAU,MAAM,qCAAmC,EAAE,QAAQ;;GAAC,IAAM,IAAE,KAAK,gBAAgB,EAAE;GAAC,OAAO,KAAK,YAAU,GAAE,KAAK,qBAAmB,KAAK,KAAK,WAAU,EAAE,UAAU,EAAC,KAAK,uBAAqB,KAAK,KAAK,cAAa,EAAE,MAAM,EAAC,KAAK,SAAO,GAAE;KAAI;;CAAC,UAAS;EAAC,IAAI,GAAE,GAAE;EAAE,CAAQ,IAAE,KAAK,cAAf,QAAuC,EAAE,WAAW,GAAS,IAAE,KAAK,uBAAf,QAAgD,EAAE,KAAK,KAAK,GAAS,IAAE,KAAK,yBAAf,QAAkD,EAAE,KAAK,KAAK,EAAC,KAAK,YAAU,MAAK,KAAK,qBAAmB,KAAK,GAAE,KAAK,uBAAqB,KAAK,GAAE,KAAK,WAAS,KAAK,OAAO,WAAW,CAAC,UAAS,MAAG,EAAE,MAAM,EAAE,EAAC,KAAK,SAAO,MAAK,KAAK,gBAAc;;CAAM,eAAe,GAAE;EAAC,OAAO,EAAE,MAAK,KAAK,GAAE,KAAK,IAAG,aAAW;GAAC,IAAM,IAAE,KAAK,WAAS,MAAM,KAAK,SAAS,EAAE;GAAE,KAAK,aAAW;GAAK,IAAM,IAAE,KAAK,iBAAe,IAAI,cAAc,GAAE;IAAC,UAAS,KAAK,QAAQ,YAAU,EAAE,OAAM,MAAG,cAAc,gBAAgB,EAAE,EAAE;IAAC,oBAAmB,KAAK,QAAQ;IAAmB,CAAC;GAAC,KAAK,gBAAc,GAAE,KAAK,eAAe;GAAC,IAAM,IAAE,EAAE;GAAC,EAAE,mBAAgB,MAAG;IAAC,EAAE,KAAK,OAAK,KAAG,EAAE,KAAK,EAAE,KAAK,EAAC,KAAK,KAAK,yBAAwB,EAAE,KAAK;;GAAE,IAAM,KAAE,MAAG;IAAC,IAAI;IAAE,IAAM,IAAE,IAAI,KAAK,GAAE,EAAC,MAAK,EAAE,UAAS,CAAC;IAAC,KAAK,KAAK,GAAE,EAAE,EAAC,KAAK,QAAQ,wBAAsB,KAAK,8BAA8B,EAAC,KAAK,mBAAiB,IAAI,gBAAgB,KAAK,gBAAgB,EAAC,KAAK,kBAAgB,IAAI,gBAAgB,EAAE,GAAS,IAAE,KAAK,eAAf,QAAwC,EAAE,KAAK,KAAK,gBAAgB;;GAAG,EAAE,gBAAY,EAAE,eAAe,EAAC,EAAE,eAAW,EAAE,aAAa,EAAC,EAAE,MAAM,KAAK,QAAQ,uBAAuB,EAAC,KAAK,gBAAc,YAAY,KAAK,EAAC,KAAK,eAAa,GAAE,KAAK,WAAS,GAAE,KAAK,mBAAiB,CAAC,GAAE,KAAK,MAAM,OAAO,EAAC,KAAK,KAAK,eAAe;KAAG;;CAAC,cAAa;EAAC,OAAO,KAAK;;CAAS,cAAa;EAAO,OAA+B,KAAK,eAAoC,UAAlE;;CAAyE,WAAU;EAAO,OAA4B,KAAK,eAAoC,UAA/D;;CAAsE,WAAU;EAAO,OAA8B,KAAK,eAAoC,UAAjE;;CAAwE,gBAAe;EAAC,IAAI;EAAE,KAAK,UAAU,MAAW,IAAE,KAAK,kBAAf,QAA2C,EAAE,MAAM,EAAC,KAAK,MAAM,MAAM;;CAAE,iBAAgB;EAAC,IAAI,GAAE;EAAE,KAAK,aAAa,KAAG,KAAK,mBAAiB,CAAC,IAAU,IAAE,KAAK,kBAAf,QAA2C,EAAE,aAAa,GAAS,IAAE,KAAK,kBAAf,QAA2C,EAAE,OAAO,EAAC,KAAK,MAAM,MAAM,EAAC,KAAK,eAAa,KAAK;;CAAU,kBAAiB;EAAC,IAAI;EAAE,KAAK,UAAU,KAAG,KAAK,mBAAiB,CAAC,IAAU,IAAE,KAAK,kBAAf,QAA2C,EAAE,QAAQ,EAAC,KAAK,MAAM,OAAO,EAAC,KAAK,gBAAc,YAAY,KAAK,EAAC,KAAK,KAAK,gBAAgB;;CAAE,OAAO,2BAA0B;EAAC,OAAO,EAAE,MAAK,KAAK,GAAE,KAAK,IAAG,aAAW;GAAC,OAAO,UAAU,aAAa,kBAAkB,CAAC,OAAM,MAAG,EAAE,SAAQ,MAAkB,EAAE,SAAjB,cAAuB,EAAE;KAAG;;CAAC,UAAS;EAAC,KAAK,8BAA8B,EAAC,MAAM,SAAS,EAAC,KAAK,eAAe,EAAC,KAAK,SAAS,EAAC,KAAK,oBAAkB,IAAI,gBAAgB,KAAK,gBAAgB,EAAC,KAAK,kBAAgB;;CAAM,+BAA8B;EAAC,KAAK,cAAY,KAAK,oBAAkB,KAAK,WAAW,WAAW,KAAK,gBAAgB,EAAC,OAAO,KAAK;;;;;ACOz4P,SAAgB,EAAe,GAA0B;CACvD,IAAM,IAAO,KAAK,IAAI,GAAG,EAAS;CAGlC,OAAO,GAFG,KAAK,MAAM,IAAO,GAElB,CAAE,IADF,IAAO,IACA,UAAU,CAAC,SAAS,GAAG,IAAI;;AAS9C,SAAgB,IAA0B;CACxC,IAAI,OAAO,gBAAkB,KAAa,OAAO;CAEjD,KAAK,IAAM,KAAK;EADI;EAA0B;EAAc;EAAa;EACzD,EACd,IAAI,cAAc,kBAAkB,EAAE,EAAE,OAAO;CAEjD,OAAO;;AAIT,eAAsB,EAAa,GAA6B;CAC9D,OAAO,IAAI,SAAS,GAAS,MAAW;EACtC,IAAM,IAAS,IAAI,YAAY;EAW/B,AAVA,EAAO,eAAe;GACpB,IAAM,IAAS,EAAO;GACtB,IAAI,OAAO,KAAW,UAAU;IAC9B,EAAO,gBAAI,MAAM,wCAAwC,CAAC;IAC1D;;GAEF,IAAM,IAAQ,EAAO,QAAQ,IAAI;GACjC,EAAQ,KAAS,IAAI,EAAO,MAAM,IAAQ,EAAE,GAAG,EAAO;KAExD,EAAO,gBAAgB,EAAO,EAAO,SAAS,gBAAI,MAAM,cAAc,CAAC,EACvE,EAAO,cAAc,EAAK;GAC1B;;;;ACqBJ,SAAgB,EAAiB,EAAE,eAAY,aAAU,cAAkC;CACzF,IAAM,IAAI,EAAgB,WAAW,EAC/B,IAAe,EAA8B,KAAK,EAClD,IAAgB,EAA0B,KAAK,EAG/C,IAAkB,EAGd,KAAK,EACT,IAAmB,EAA6B,KAAK,EACrD,IAAY,EAAe,EAAE,CAAC,EAC9B,IAAkB,EAAsB,KAAK,EAE7C,CAAC,GAAO,KAAY,EAAkC,YAAY,EAClE,CAAC,GAAY,KAAiB,EAAS,EAAE,EACzC,CAAC,GAAgB,KAAqB,EAAS,GAAM,EAGrD,IAAc,EAA8B,KAAK,EAKjD,IAAmB,EAAO,GAAM;CAiRtC,OA1QA,QAAgB;EACd,IAAM,IAAY,EAAa;EAC/B,IAAI,CAAC,GAAW;EAEhB,IAAI,OAAO,SAAW,OAAe,CAAC,OAAO,eAAe;GAC1D,EAAQ,cAAc;GACtB;;EASF,IAAI,IAAkB;EACtB,EAAiB,UAAU;EAQ3B,IAAM,IAAS,iBAAiB,EAAU,EACpC,IAAU,EAAO,iBAAiB,eAAe,CAAC,MAAM,IAAI,WAC5D,IAAQ,EAAO,iBAAiB,gBAAgB,CAAC,MAAM,IAAI,WAE3D,IAAK,EAAW,OAAO;GAC3B;GACA,WAAW;GACX,eAAe;GACf,aAAa;GACb,aAAa;GACb,QAAQ;GACR,UAAU;GACV,QAAQ;GACR,WAAW;GACX,UAAU;GAKV,eAAe;GAChB,CAAC;EAKF,AAJA,EAAc,UAAU,GAExB,EAAG,GAAG,cAAc,EAAkB,GAAK,CAAC,EAC5C,EAAG,GAAG,eAAe,EAAkB,GAAM,CAAC,EAC9C,EAAG,GAAG,gBAAgB,EAAkB,GAAM,CAAC;EAE/C,IAAM,IAAS,EAAG,eAChB,EAAa,OAAO;GAClB,oBAAoB;GACpB,4BAA4B;GAI5B,qBAAqB;GACtB,CAAC,CACH;EACD,EAAgB,UAAU;EAK1B,IAAI,IAAmC,MACnC,IAAsC;EAmI1C,OAtHA,EACG,UAAU,CACV,MAAM,MAAW;GAChB,IAAI,KAAmB,EAAiB,SAAS;IAQ/C,IAAI;KACF,EAAO,WAAW,CAAC,SAAS,MAAU;MACpC,EAAM,MAAM;OACZ;YACI;IACR,IAAI;KACF,EAAO,SAAS;YACV;IACR;;GAEF,IAAM,IAAO,GAAU,EACjB,IAAW,IACb,IAAI,cAAc,GAAQ,EAAE,UAAU,GAAM,CAAC,GAC7C,IAAI,cAAc,EAAO;GA0E7B,AAzEA,EAAiB,UAAU,GAC3B,IAAgB,GAChB,EAAU,UAAU,EAAE,EACtB,EAAS,iBAAiB,kBAAkB,MAAM;IAChD,AAAI,EAAE,QAAQ,EAAE,KAAK,OAAO,KAAG,EAAU,QAAQ,KAAK,EAAE,KAAK;KAC7D,EACF,EAAS,iBAAiB,cAAc;IAEtC,IAAI,KAAmB,EAAiB,SAAS;IAMjD,IAAI;KACF,EAAO,SAAS;YACV;IACR,AAAI,MAAsB,SACxB,cAAc,EAAkB,EAChC,IAAoB,MACpB,EAAgB,UAAU;IAE5B,IAAM,IAAY,EAAS,YAAY,KAAQ,cACzC,IAAO,IAAI,KAAK,EAAU,SAAS,EAAE,MAAM,GAAW,CAAC;IAC7D,EAAa,EAAK,CACf,MAAM,MAAW;KAChB,IAAI,KAAmB,EAAiB,SAAS;KACjD,IAAM,IAAM,EAAU,SAAS,MAAM,GAAG,QAAQ;KA0ChD,AAlCA,EAAY,UAAU;MACpB;MACA,UAHiB,EAAU,MAAM,IAAI,CAAC,GAAG,MAG/B;MACV,MAAM,EAAK;MACX,UAAU,SAAS,KAAK,KAAK,CAAC,GAAG;MAClC,EAkBD,EAAG,SAAS,EAAK,CACd,WAAW;MACN,WAAmB,EAAiB,UACxC;WAAI;QACF,EAAG,WAAW,EAAE,UAAU,IAAM,CAAC;eAC3B;OACR,IAAI;QACF,EAAG,QAAQ,EAAE;eACP;;OACR,CACD,YAAY,GAAG,EAClB,EAAS,UAAU;MACnB,CACD,YAAY,EAAQ,SAAS,CAAC;KACjC,EACF,EAAS,OAAO;GAMhB,IAAM,IAAY,YAAY,KAAK;GAMnC,AALA,IAAoB,OAAO,kBAAkB;IAC3C,IAAM,IAAK,YAAY,KAAK,GAAG,GACzB,IAAM,KAAK,MAAM,IAAK,IAAK;IACjC,GAAe,MAAU,MAAS,IAAM,IAAO,EAAK;MACnD,IAAI,EACP,EAAgB,UAAU;IAC1B,CACD,OAAO,MAAe;GACrB,IAAI,GAAiB;GACrB,IAAM,IAAM,GAAK,WAAW;GAC5B,EAAQ,EAAI,SAAS,aAAa,IAAI,EAAI,SAAS,SAAS,GAAG,WAAW,SAAS;IACnF,QAES;GAEX,AADA,IAAkB,IACd,MAAsB,QACxB,cAAc,EAAkB;GAElC,IAAI;IACF,AAAI,GAAe,UAAU,eAC3B,EAAc,MAAM;WAEhB;GACR,IAAI;IACF,EAAO,SAAS;WACV;GAOR,AANA,EAAG,SAAS,EAIR,EAAc,YAAY,MAAI,EAAc,UAAU,OACtD,EAAgB,YAAY,MAAQ,EAAgB,UAAU,OAC9D,EAAiB,YAAY,MAC/B,EAAiB,UAAU;;IAG9B,EAAE,CAAC,EA8CJ,kBAAC,EAAO,KAAR;EAEE,SAAS;GAAE,SAAS;GAAG,GAAG;GAAG;EAC7B,SAAS;GAAE,SAAS;GAAG,GAAG;GAAG;EAC7B,YAAY,EAAE,UAAU,KAAM;EAC9B,WAAW,EACT,qFACD;YAPH;GASE,kBAAC,GAAD;IACE,MAAM;IACN,eAvDqB;KACzB,EAAiB,UAAU;KAC3B,IAAI;MACF,AAAI,EAAiB,SAAS,UAAU,eACtC,EAAiB,QAAQ,MAAM;aAE3B;KACR,IAAI;MACF,EAAgB,SAAS,SAAS;aAC5B;KACR,IAAI;MACF,EAAc,SAAS,OAAO;aACxB;KACR,GAAU;;IA2CN,WAAW,EAAE,kBAAkB;IAC/B,QAAO;IACP,CAAA;GAUF,kBAAC,OAAD;IAAK,WAAU;cAAf;KACG,MAAU,eACT,kBAAC,QAAD;MACE,eAAY;MACZ,WAAU;MACV,CAAA;KAEJ,kBAAC,OAAD;MACE,KAAK;MACL,eAAY;MACZ,WAAW,EACT,kCAIA,MAAU,aAAa,sBACxB;MACD,CAAA;KACF,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAe,EAAW;MACtB,CAAA;KACH;;GAEL,MAAU,eACT,kBAAC,EAAO,QAAR;IACE,MAAK;IACL,eA9EiB;KAIvB,IAAI;MACF,AAAI,EAAiB,SAAS,UAAU,eACtC,EAAiB,QAAQ,MAAM;aAE3B;;IAuEF,cAAY,EAAE,gBAAgB;IAC9B,YAAY,EAAE,OAAO,MAAM;IAC3B,UAAU,EAAE,OAAO,IAAK;IACxB,YAAY;KAAE,MAAM;KAAU,WAAW;KAAK,SAAS;KAAI;IAC3D,WAAW,EACT,oFACA,4DACD;cAED,kBAAC,GAAD,EAAQ,MAAM,IAAM,CAAA;IACN,CAAA;GAGjB,MAAU,aACT,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;IACE,MAAM,IAAiB,IAAY;IACnC,eArFwB;KAChC,IAAM,IAAK,EAAc;KACpB,MACD,EAAG,WAAW,GAChB,EAAG,OAAO,GAEV,EAAG,MAAM;;IAgFH,WAA4B,EAAjB,IAAmB,mBAAsB,cAAc;IAClE,QAAO;IACP,CAAA,EACF,kBAAC,EAAO,QAAR;IACE,MAAK;IACL,eAjFe;KACvB,IAAM,IAAM,EAAY;KACnB,KACL,EAAW,EAAI;;IA+EP,cAAY,EAAE,UAAU;IACxB,YAAY,EAAE,OAAO,MAAM;IAC3B,UAAU,EAAE,OAAO,IAAK;IACxB,YAAY;KAAE,MAAM;KAAU,WAAW;KAAK,SAAS;KAAI;IAC3D,WAAW,EACT,oFACA,6DACD;cAED,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA;IACJ,CAAA,CACf,EAAA,CAAA;GAEM;IAvFP,iBAuFO;;AAiCjB,SAAS,EAAQ,EACf,SACA,YACA,cACA,WACA,UAAO,MAON;CACD,IAAM,IAAQ,GAAoC;CAClD,OACE,kBAAC,EAAO,QAAR;EACE,MAAK;EACI;EACT,cAAY;EACZ,YAAY,EAAE,OAAO,MAAM;EAC3B,UAAU,EAAE,OAAO,IAAK;EACxB,YAAY;GAAE,MAAM;GAAU,WAAW;GAAK,SAAS;GAAI;EAC3D,GAAI,EAAM;EACV,WAAW,EACT,oFACA,MAAW,YACP,+DACA,4DACL;YAED,kBAAC,GAAD;GAAM,KAAK,EAAM;GAAe;GAAQ,CAAA;EAC1B,CAAA"}
@@ -0,0 +1,23 @@
1
+ import "react";
2
+ import "react-dom";
3
+ import "react/jsx-runtime";
4
+ import "react-dom/client";
5
+ import { t as e } from "./widget-react-BxvW64LH.js";
6
+ var t = e("external-link", [
7
+ ["path", {
8
+ d: "M15 3h6v6",
9
+ key: "1q9fwt"
10
+ }],
11
+ ["path", {
12
+ d: "M10 14 21 3",
13
+ key: "gplh6r"
14
+ }],
15
+ ["path", {
16
+ d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",
17
+ key: "a6xqqp"
18
+ }]
19
+ ]);
20
+ //#endregion
21
+ export { t };
22
+
23
+ //# sourceMappingURL=widget-react-CUBFPjaV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-react-CUBFPjaV.js","names":[],"sources":["../node_modules/lucide-react/dist/esm/icons/external-link.mjs"],"sourcesContent":["/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M15 3h6v6\", key: \"1q9fwt\" }],\n [\"path\", { d: \"M10 14 21 3\", key: \"gplh6r\" }],\n [\"path\", { d: \"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\", key: \"a6xqqp\" }]\n];\nconst ExternalLink = createLucideIcon(\"external-link\", __iconNode);\n\nexport { __iconNode, ExternalLink as default };\n//# sourceMappingURL=external-link.mjs.map\n"],"x_google_ignoreList":[0],"mappings":";;;;;AAcA,IAAM,IAAe,EAAiB,iBAAiB;CAJrD,CAAC,QAAQ;EAAE,GAAG;EAAa,KAAK;EAAU,CAAC;CAC3C,CAAC,QAAQ;EAAE,GAAG;EAAe,KAAK;EAAU,CAAC;CAC7C,CAAC,QAAQ;EAAE,GAAG;EAA4D,KAAK;EAAU,CAAC;CAErC,CAAW"}