@mediansh/widget 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/dist/{chunk-3KEM4W7J.js → chunk-3ZXE5RBN.js} +2 -2
- package/dist/chunk-77KIJLPP.js +43 -0
- package/dist/{chunk-W6NPKKCE.js → chunk-HLALDSPM.js} +1 -39
- package/dist/{chunk-W6NPKKCE.js.map → chunk-HLALDSPM.js.map} +1 -1
- package/dist/{chunk-DVQ7V3LR.js → chunk-R3S6Y434.js} +9 -7
- package/dist/{chunk-DVQ7V3LR.js.map → chunk-R3S6Y434.js.map} +1 -1
- package/dist/dist-VC6ZVTA2.js +1658 -0
- package/dist/dist-VC6ZVTA2.js.map +1 -0
- package/dist/{highlighted-body-OFNGDK62-DW3EMPTG.js → highlighted-body-OFNGDK62-T25BCWKJ.js} +4 -3
- package/dist/highlighted-body-OFNGDK62-T25BCWKJ.js.map +1 -0
- package/dist/index.d.ts +68 -7
- package/dist/index.js +1476 -902
- package/dist/index.js.map +1 -1
- package/dist/mermaid-GHXKKRXX-U6EYEPWB.js +11 -0
- package/dist/mermaid-GHXKKRXX-U6EYEPWB.js.map +1 -0
- package/dist/{message-markdown-LOE74LBE.js → message-markdown-KQVNAD42.js} +5 -4
- package/dist/{message-markdown-LOE74LBE.js.map → message-markdown-KQVNAD42.js.map} +1 -1
- package/dist/widget.css +1 -1
- package/package.json +19 -4
- package/dist/highlighted-body-OFNGDK62-DW3EMPTG.js.map +0 -1
- package/dist/mermaid-GHXKKRXX-N3BSVIR6.js +0 -10
- /package/dist/{chunk-3KEM4W7J.js.map → chunk-3ZXE5RBN.js.map} +0 -0
- /package/dist/{mermaid-GHXKKRXX-N3BSVIR6.js.map → chunk-77KIJLPP.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
cn
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3ZXE5RBN.js";
|
|
5
5
|
import {
|
|
6
|
-
__export,
|
|
7
6
|
clsx
|
|
8
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HLALDSPM.js";
|
|
8
|
+
import {
|
|
9
|
+
__export
|
|
10
|
+
} from "./chunk-77KIJLPP.js";
|
|
9
11
|
|
|
10
12
|
// ../../apps/web/src/components/support-widget/sdk/median-support.tsx
|
|
11
|
-
import { useEffect as
|
|
13
|
+
import { useEffect as useEffect26 } from "react";
|
|
12
14
|
|
|
13
15
|
// ../../apps/web/src/components/support-widget/markdown-chunk.tsx
|
|
14
16
|
import { lazy, useSyncExternalStore } from "react";
|
|
15
|
-
var load = () => import("./message-markdown-
|
|
17
|
+
var load = () => import("./message-markdown-KQVNAD42.js");
|
|
16
18
|
var MessageMarkdown = lazy(async () => ({
|
|
17
19
|
default: (await load()).MessageMarkdown
|
|
18
20
|
}));
|
|
@@ -61,18 +63,18 @@ function useMarkdownReady() {
|
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
// ../../apps/web/src/components/support-widget/widget-launcher.tsx
|
|
64
|
-
import { useCallback as useCallback7, useEffect as
|
|
66
|
+
import { useCallback as useCallback7, useEffect as useEffect10, useRef as useRef14, useState as useState15 } from "react";
|
|
65
67
|
|
|
66
68
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/lib/SSRBase.es.js
|
|
67
69
|
import * as e from "react";
|
|
68
70
|
var w = e.forwardRef((l5, s4) => {
|
|
69
71
|
const {
|
|
70
|
-
alt:
|
|
71
|
-
color:
|
|
72
|
-
size:
|
|
73
|
-
weight:
|
|
72
|
+
alt: r42,
|
|
73
|
+
color: a30 = "currentColor",
|
|
74
|
+
size: t14 = "1em",
|
|
75
|
+
weight: o54 = "regular",
|
|
74
76
|
mirrored: i3 = false,
|
|
75
|
-
children:
|
|
77
|
+
children: n2,
|
|
76
78
|
weights: c8,
|
|
77
79
|
...m5
|
|
78
80
|
} = l5;
|
|
@@ -81,16 +83,16 @@ var w = e.forwardRef((l5, s4) => {
|
|
|
81
83
|
{
|
|
82
84
|
ref: s4,
|
|
83
85
|
xmlns: "http://www.w3.org/2000/svg",
|
|
84
|
-
width:
|
|
85
|
-
height:
|
|
86
|
-
fill:
|
|
86
|
+
width: t14,
|
|
87
|
+
height: t14,
|
|
88
|
+
fill: a30,
|
|
87
89
|
viewBox: "0 0 256 256",
|
|
88
90
|
transform: i3 ? "scale(-1, 1)" : void 0,
|
|
89
91
|
...m5
|
|
90
92
|
},
|
|
91
|
-
!!
|
|
92
|
-
|
|
93
|
-
c8.get(
|
|
93
|
+
!!r42 && /* @__PURE__ */ e.createElement("title", null, r42),
|
|
94
|
+
n2,
|
|
95
|
+
c8.get(o54)
|
|
94
96
|
);
|
|
95
97
|
});
|
|
96
98
|
w.displayName = "SSRBase";
|
|
@@ -128,7 +130,7 @@ var a = /* @__PURE__ */ new Map([
|
|
|
128
130
|
]);
|
|
129
131
|
|
|
130
132
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowDown.es.js
|
|
131
|
-
var r = o.forwardRef((
|
|
133
|
+
var r = o.forwardRef((e62, t14) => /* @__PURE__ */ o.createElement(w, { ref: t14, ...e62, weights: a }));
|
|
132
134
|
r.displayName = "ArrowDownIcon";
|
|
133
135
|
|
|
134
136
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowRight.es.js
|
|
@@ -164,7 +166,7 @@ var a2 = /* @__PURE__ */ new Map([
|
|
|
164
166
|
]);
|
|
165
167
|
|
|
166
168
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowRight.es.js
|
|
167
|
-
var o2 = r2.forwardRef((
|
|
169
|
+
var o2 = r2.forwardRef((t14, e62) => /* @__PURE__ */ r2.createElement(w, { ref: e62, ...t14, weights: a2 }));
|
|
168
170
|
o2.displayName = "ArrowRightIcon";
|
|
169
171
|
|
|
170
172
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowUp.es.js
|
|
@@ -200,7 +202,7 @@ var a3 = /* @__PURE__ */ new Map([
|
|
|
200
202
|
]);
|
|
201
203
|
|
|
202
204
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowUp.es.js
|
|
203
|
-
var o3 = r3.forwardRef((
|
|
205
|
+
var o3 = r3.forwardRef((e62, t14) => /* @__PURE__ */ r3.createElement(w, { ref: t14, ...e62, weights: a3 }));
|
|
204
206
|
o3.displayName = "ArrowUpIcon";
|
|
205
207
|
|
|
206
208
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsClockwise.es.js
|
|
@@ -236,7 +238,7 @@ var e5 = /* @__PURE__ */ new Map([
|
|
|
236
238
|
]);
|
|
237
239
|
|
|
238
240
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsClockwise.es.js
|
|
239
|
-
var r4 = o4.forwardRef((
|
|
241
|
+
var r4 = o4.forwardRef((e62, s4) => /* @__PURE__ */ o4.createElement(w, { ref: s4, ...e62, weights: e5 }));
|
|
240
242
|
r4.displayName = "ArrowsClockwiseIcon";
|
|
241
243
|
|
|
242
244
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsIn.es.js
|
|
@@ -278,7 +280,7 @@ var e6 = /* @__PURE__ */ new Map([
|
|
|
278
280
|
]);
|
|
279
281
|
|
|
280
282
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsIn.es.js
|
|
281
|
-
var o5 = r5.forwardRef((
|
|
283
|
+
var o5 = r5.forwardRef((e62, s4) => /* @__PURE__ */ r5.createElement(w, { ref: s4, ...e62, weights: e6 }));
|
|
282
284
|
o5.displayName = "ArrowsInIcon";
|
|
283
285
|
|
|
284
286
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsOut.es.js
|
|
@@ -314,7 +316,7 @@ var e7 = /* @__PURE__ */ new Map([
|
|
|
314
316
|
]);
|
|
315
317
|
|
|
316
318
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsOut.es.js
|
|
317
|
-
var o6 = r6.forwardRef((
|
|
319
|
+
var o6 = r6.forwardRef((t14, e62) => /* @__PURE__ */ r6.createElement(w, { ref: e62, ...t14, weights: e7 }));
|
|
318
320
|
o6.displayName = "ArrowsOutIcon";
|
|
319
321
|
|
|
320
322
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Bug.es.js
|
|
@@ -350,7 +352,7 @@ var e8 = /* @__PURE__ */ new Map([
|
|
|
350
352
|
]);
|
|
351
353
|
|
|
352
354
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Bug.es.js
|
|
353
|
-
var e9 = o7.forwardRef((
|
|
355
|
+
var e9 = o7.forwardRef((r42, t14) => /* @__PURE__ */ o7.createElement(w, { ref: t14, ...r42, weights: e8 }));
|
|
354
356
|
e9.displayName = "BugIcon";
|
|
355
357
|
|
|
356
358
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/CaretDown.es.js
|
|
@@ -386,7 +388,7 @@ var t = /* @__PURE__ */ new Map([
|
|
|
386
388
|
]);
|
|
387
389
|
|
|
388
390
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/CaretDown.es.js
|
|
389
|
-
var e11 = o8.forwardRef((
|
|
391
|
+
var e11 = o8.forwardRef((r42, t14) => /* @__PURE__ */ o8.createElement(w, { ref: t14, ...r42, weights: t }));
|
|
390
392
|
e11.displayName = "CaretDownIcon";
|
|
391
393
|
|
|
392
394
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/CaretRight.es.js
|
|
@@ -422,7 +424,7 @@ var t2 = /* @__PURE__ */ new Map([
|
|
|
422
424
|
]);
|
|
423
425
|
|
|
424
426
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/CaretRight.es.js
|
|
425
|
-
var e13 = t3.forwardRef((
|
|
427
|
+
var e13 = t3.forwardRef((r42, o54) => /* @__PURE__ */ t3.createElement(w, { ref: o54, ...r42, weights: t2 }));
|
|
426
428
|
e13.displayName = "CaretRightIcon";
|
|
427
429
|
|
|
428
430
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ChatCircleDots.es.js
|
|
@@ -464,7 +466,7 @@ var e14 = /* @__PURE__ */ new Map([
|
|
|
464
466
|
]);
|
|
465
467
|
|
|
466
468
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ChatCircleDots.es.js
|
|
467
|
-
var o9 = t4.forwardRef((
|
|
469
|
+
var o9 = t4.forwardRef((e62, r42) => /* @__PURE__ */ t4.createElement(w, { ref: r42, ...e62, weights: e14 }));
|
|
468
470
|
o9.displayName = "ChatCircleDotsIcon";
|
|
469
471
|
|
|
470
472
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Check.es.js
|
|
@@ -506,7 +508,7 @@ var a9 = /* @__PURE__ */ new Map([
|
|
|
506
508
|
]);
|
|
507
509
|
|
|
508
510
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Check.es.js
|
|
509
|
-
var o10 = e16.forwardRef((
|
|
511
|
+
var o10 = e16.forwardRef((r42, t14) => /* @__PURE__ */ e16.createElement(w, { ref: t14, ...r42, weights: a9 }));
|
|
510
512
|
o10.displayName = "CheckIcon";
|
|
511
513
|
|
|
512
514
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/EnvelopeSimple.es.js
|
|
@@ -578,7 +580,7 @@ var a11 = /* @__PURE__ */ new Map([
|
|
|
578
580
|
]);
|
|
579
581
|
|
|
580
582
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/File.es.js
|
|
581
|
-
var o12 = e20.forwardRef((
|
|
583
|
+
var o12 = e20.forwardRef((r42, t14) => /* @__PURE__ */ e20.createElement(w, { ref: t14, ...r42, weights: a11 }));
|
|
582
584
|
o12.displayName = "FileIcon";
|
|
583
585
|
|
|
584
586
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ImageSquare.es.js
|
|
@@ -620,7 +622,7 @@ var e21 = /* @__PURE__ */ new Map([
|
|
|
620
622
|
]);
|
|
621
623
|
|
|
622
624
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ImageSquare.es.js
|
|
623
|
-
var a13 = e22.forwardRef((
|
|
625
|
+
var a13 = e22.forwardRef((r42, o54) => /* @__PURE__ */ e22.createElement(w, { ref: o54, ...r42, weights: e21 }));
|
|
624
626
|
a13.displayName = "ImageSquareIcon";
|
|
625
627
|
|
|
626
628
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Lightbulb.es.js
|
|
@@ -662,7 +664,7 @@ var e23 = /* @__PURE__ */ new Map([
|
|
|
662
664
|
]);
|
|
663
665
|
|
|
664
666
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Lightbulb.es.js
|
|
665
|
-
var o13 = t5.forwardRef((
|
|
667
|
+
var o13 = t5.forwardRef((e62, r42) => /* @__PURE__ */ t5.createElement(w, { ref: r42, ...e62, weights: e23 }));
|
|
666
668
|
o13.displayName = "LightbulbIcon";
|
|
667
669
|
|
|
668
670
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/LockSimple.es.js
|
|
@@ -704,7 +706,7 @@ var e24 = /* @__PURE__ */ new Map([
|
|
|
704
706
|
]);
|
|
705
707
|
|
|
706
708
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/LockSimple.es.js
|
|
707
|
-
var e25 = o14.forwardRef((m5,
|
|
709
|
+
var e25 = o14.forwardRef((m5, r42) => /* @__PURE__ */ o14.createElement(w, { ref: r42, ...m5, weights: e24 }));
|
|
708
710
|
e25.displayName = "LockSimpleIcon";
|
|
709
711
|
|
|
710
712
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Play.es.js
|
|
@@ -746,7 +748,7 @@ var a16 = /* @__PURE__ */ new Map([
|
|
|
746
748
|
]);
|
|
747
749
|
|
|
748
750
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Play.es.js
|
|
749
|
-
var a17 = o15.forwardRef((
|
|
751
|
+
var a17 = o15.forwardRef((e62, r42) => /* @__PURE__ */ o15.createElement(w, { ref: r42, ...e62, weights: a16 }));
|
|
750
752
|
a17.displayName = "PlayIcon";
|
|
751
753
|
|
|
752
754
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Plus.es.js
|
|
@@ -788,7 +790,7 @@ var a18 = /* @__PURE__ */ new Map([
|
|
|
788
790
|
]);
|
|
789
791
|
|
|
790
792
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Plus.es.js
|
|
791
|
-
var e28 = o16.forwardRef((
|
|
793
|
+
var e28 = o16.forwardRef((r42, s4) => /* @__PURE__ */ o16.createElement(w, { ref: s4, ...r42, weights: a18 }));
|
|
792
794
|
e28.displayName = "PlusIcon";
|
|
793
795
|
|
|
794
796
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Sparkle.es.js
|
|
@@ -830,7 +832,7 @@ var l = /* @__PURE__ */ new Map([
|
|
|
830
832
|
]);
|
|
831
833
|
|
|
832
834
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Sparkle.es.js
|
|
833
|
-
var r7 = e29.forwardRef((
|
|
835
|
+
var r7 = e29.forwardRef((o54, a30) => /* @__PURE__ */ e29.createElement(w, { ref: a30, ...o54, weights: l }));
|
|
834
836
|
r7.displayName = "SparkleIcon";
|
|
835
837
|
|
|
836
838
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Star.es.js
|
|
@@ -872,7 +874,7 @@ var l2 = /* @__PURE__ */ new Map([
|
|
|
872
874
|
]);
|
|
873
875
|
|
|
874
876
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Star.es.js
|
|
875
|
-
var t6 = r8.forwardRef((
|
|
877
|
+
var t6 = r8.forwardRef((o54, a30) => /* @__PURE__ */ r8.createElement(w, { ref: a30, ...o54, weights: l2 }));
|
|
876
878
|
t6.displayName = "StarIcon";
|
|
877
879
|
|
|
878
880
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/UserCircle.es.js
|
|
@@ -914,7 +916,7 @@ var a21 = /* @__PURE__ */ new Map([
|
|
|
914
916
|
]);
|
|
915
917
|
|
|
916
918
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/UserCircle.es.js
|
|
917
|
-
var r9 = e31.forwardRef((
|
|
919
|
+
var r9 = e31.forwardRef((o54, s4) => /* @__PURE__ */ e31.createElement(w, { ref: s4, ...o54, weights: a21 }));
|
|
918
920
|
r9.displayName = "UserCircleIcon";
|
|
919
921
|
|
|
920
922
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/WarningCircle.es.js
|
|
@@ -950,7 +952,7 @@ var a22 = /* @__PURE__ */ new Map([
|
|
|
950
952
|
]);
|
|
951
953
|
|
|
952
954
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/WarningCircle.es.js
|
|
953
|
-
var e33 = r10.forwardRef((
|
|
955
|
+
var e33 = r10.forwardRef((o54, a30) => /* @__PURE__ */ r10.createElement(w, { ref: a30, ...o54, weights: a22 }));
|
|
954
956
|
e33.displayName = "WarningCircleIcon";
|
|
955
957
|
|
|
956
958
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/X.es.js
|
|
@@ -992,7 +994,7 @@ var a23 = /* @__PURE__ */ new Map([
|
|
|
992
994
|
]);
|
|
993
995
|
|
|
994
996
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/X.es.js
|
|
995
|
-
var e35 = o17.forwardRef((
|
|
997
|
+
var e35 = o17.forwardRef((r42, t14) => /* @__PURE__ */ o17.createElement(w, { ref: t14, ...r42, weights: a23 }));
|
|
996
998
|
e35.displayName = "XIcon";
|
|
997
999
|
|
|
998
1000
|
// ../../apps/web/src/components/icons.tsx
|
|
@@ -1007,8 +1009,15 @@ function icon(Base, name, weight = "fill") {
|
|
|
1007
1009
|
var Bug = /* @__PURE__ */ icon(e9, "Bug");
|
|
1008
1010
|
var ChatCircleDots = /* @__PURE__ */ icon(o9, "ChatCircleDots");
|
|
1009
1011
|
var EnvelopeSimple = /* @__PURE__ */ icon(o11, "EnvelopeSimple");
|
|
1010
|
-
var
|
|
1012
|
+
var File2 = /* @__PURE__ */ icon(o12, "File");
|
|
1011
1013
|
var ImageSquare = /* @__PURE__ */ icon(a13, "ImageSquare");
|
|
1014
|
+
var LIFEBUOY = [
|
|
1015
|
+
"M128,24A104,104,0,1,0,232,128,104,104,0,0,0,128,24Z",
|
|
1016
|
+
"M166.6,69.6L149.08,87.12A46,46,0,0,0,106.92,87.12L89.4,69.6A70,70,0,0,1,166.6,69.6Z",
|
|
1017
|
+
"M186.4,166.6L168.88,149.08A46,46,0,0,0,168.88,106.92L186.4,89.4A70,70,0,0,1,186.4,166.6Z",
|
|
1018
|
+
"M89.4,186.4L106.92,168.88A46,46,0,0,0,149.08,168.88L166.6,186.4A70,70,0,0,1,89.4,186.4Z",
|
|
1019
|
+
"M69.6,89.4L87.12,106.92A46,46,0,0,0,87.12,149.08L69.6,166.6A70,70,0,0,1,69.6,89.4Z"
|
|
1020
|
+
].join("");
|
|
1012
1021
|
var Lightbulb = /* @__PURE__ */ icon(o13, "Lightbulb");
|
|
1013
1022
|
var LockSimple = /* @__PURE__ */ icon(e25, "LockSimple");
|
|
1014
1023
|
var Play = /* @__PURE__ */ icon(a17, "Play");
|
|
@@ -1113,7 +1122,7 @@ function setSpot(spot) {
|
|
|
1113
1122
|
}
|
|
1114
1123
|
|
|
1115
1124
|
// ../../apps/web/src/components/support-widget/support-widget.tsx
|
|
1116
|
-
import { useState as
|
|
1125
|
+
import { useState as useState10 } from "react";
|
|
1117
1126
|
|
|
1118
1127
|
// ../../apps/web/src/components/ui/collapse.tsx
|
|
1119
1128
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
@@ -1121,17 +1130,21 @@ var COLLAPSE_MS = 200;
|
|
|
1121
1130
|
function Collapse({
|
|
1122
1131
|
isOpen,
|
|
1123
1132
|
id,
|
|
1133
|
+
direction = "vertical",
|
|
1124
1134
|
children,
|
|
1125
1135
|
className
|
|
1126
1136
|
}) {
|
|
1137
|
+
const isSideways = direction === "horizontal";
|
|
1127
1138
|
return /* @__PURE__ */ jsx2(
|
|
1128
1139
|
"div",
|
|
1129
1140
|
{
|
|
1130
1141
|
id,
|
|
1131
1142
|
inert: isOpen ? void 0 : true,
|
|
1132
1143
|
className: cn(
|
|
1133
|
-
"grid
|
|
1134
|
-
|
|
1144
|
+
"grid duration-200 ease-out motion-reduce:transition-none",
|
|
1145
|
+
isSideways ? "transition-[grid-template-columns,opacity]" : "transition-[grid-template-rows,opacity]",
|
|
1146
|
+
isSideways ? isOpen ? "grid-cols-[1fr]" : "grid-cols-[0fr]" : isOpen ? "grid-rows-[1fr]" : "grid-rows-[0fr]",
|
|
1147
|
+
isOpen ? "opacity-100" : "opacity-0",
|
|
1135
1148
|
className
|
|
1136
1149
|
),
|
|
1137
1150
|
children: /* @__PURE__ */ jsx2("div", { className: "overflow-hidden", children })
|
|
@@ -1144,57 +1157,57 @@ import * as React3 from "react";
|
|
|
1144
1157
|
|
|
1145
1158
|
// ../../node_modules/.bun/@shadcn+react@0.3.0+03aa47d54245a271/node_modules/@shadcn/react/dist/chunk-HBS6WEDP.js
|
|
1146
1159
|
import * as i2 from "react";
|
|
1147
|
-
function S({ defaultTagName:
|
|
1148
|
-
let
|
|
1149
|
-
if (!
|
|
1150
|
-
if (typeof
|
|
1151
|
-
if (!i2.isValidElement(
|
|
1152
|
-
let s4 =
|
|
1153
|
-
return i2.cloneElement(
|
|
1154
|
-
}
|
|
1155
|
-
function d(...
|
|
1156
|
-
let
|
|
1157
|
-
for (let
|
|
1158
|
-
if (!
|
|
1159
|
-
let
|
|
1160
|
-
for (let
|
|
1161
|
-
let
|
|
1162
|
-
if (
|
|
1163
|
-
let s4 =
|
|
1164
|
-
|
|
1160
|
+
function S({ defaultTagName: a30, props: r42, render: t14, state: n2 = {}, stateAttributesMapping: e62 }) {
|
|
1161
|
+
let o54 = d(R(n2, e62), r42);
|
|
1162
|
+
if (!t14) return i2.createElement(a30, o54);
|
|
1163
|
+
if (typeof t14 == "function") return t14(o54, n2);
|
|
1164
|
+
if (!i2.isValidElement(t14)) return null;
|
|
1165
|
+
let s4 = t14.props, u = { ...d(o54, s4), ref: f8(o54.ref, s4.ref) };
|
|
1166
|
+
return i2.cloneElement(t14, u);
|
|
1167
|
+
}
|
|
1168
|
+
function d(...a30) {
|
|
1169
|
+
let r42 = {};
|
|
1170
|
+
for (let t14 of a30) {
|
|
1171
|
+
if (!t14) continue;
|
|
1172
|
+
let n2 = t14;
|
|
1173
|
+
for (let e62 of Object.keys(n2)) {
|
|
1174
|
+
let o54 = n2[e62];
|
|
1175
|
+
if (o54 === void 0) continue;
|
|
1176
|
+
let s4 = r42[e62];
|
|
1177
|
+
e62 === "className" ? r42[e62] = [s4, o54].filter(Boolean).join(" ") : e62 === "style" ? r42[e62] = { ...s4, ...o54 } : e62 === "ref" ? r42[e62] = f8(s4, o54) : l4(e62) && typeof s4 == "function" && typeof o54 == "function" ? r42[e62] = p2(o54, s4) : r42[e62] = o54;
|
|
1165
1178
|
}
|
|
1166
1179
|
}
|
|
1167
|
-
return
|
|
1168
|
-
}
|
|
1169
|
-
function R(
|
|
1170
|
-
let
|
|
1171
|
-
for (let
|
|
1172
|
-
let
|
|
1173
|
-
if (
|
|
1174
|
-
Object.assign(
|
|
1180
|
+
return r42;
|
|
1181
|
+
}
|
|
1182
|
+
function R(a30, r42) {
|
|
1183
|
+
let t14 = {};
|
|
1184
|
+
for (let n2 of Object.keys(a30)) {
|
|
1185
|
+
let e62 = a30[n2], o54 = r42?.[n2]?.(e62);
|
|
1186
|
+
if (o54) {
|
|
1187
|
+
Object.assign(t14, o54);
|
|
1175
1188
|
continue;
|
|
1176
1189
|
}
|
|
1177
|
-
if (
|
|
1178
|
-
|
|
1190
|
+
if (n2 === "slot") {
|
|
1191
|
+
t14["data-slot"] = e62;
|
|
1179
1192
|
continue;
|
|
1180
1193
|
}
|
|
1181
|
-
let s4 = `data-${String(
|
|
1182
|
-
typeof
|
|
1194
|
+
let s4 = `data-${String(n2).replace(/[A-Z]/g, (c8) => `-${c8.toLowerCase()}`)}`;
|
|
1195
|
+
typeof e62 == "boolean" ? t14[s4] = e62 ? "" : void 0 : e62 != null && (t14[s4] = String(e62));
|
|
1183
1196
|
}
|
|
1184
|
-
return
|
|
1197
|
+
return t14;
|
|
1185
1198
|
}
|
|
1186
|
-
function p2(
|
|
1187
|
-
return function(
|
|
1188
|
-
|
|
1199
|
+
function p2(a30, r42) {
|
|
1200
|
+
return function(n2) {
|
|
1201
|
+
a30(n2), n2.defaultPrevented || r42(n2);
|
|
1189
1202
|
};
|
|
1190
1203
|
}
|
|
1191
|
-
function l4(
|
|
1192
|
-
return /^on[A-Z]/.test(
|
|
1204
|
+
function l4(a30) {
|
|
1205
|
+
return /^on[A-Z]/.test(a30);
|
|
1193
1206
|
}
|
|
1194
|
-
function f8(...
|
|
1195
|
-
let
|
|
1196
|
-
if (
|
|
1197
|
-
for (let
|
|
1207
|
+
function f8(...a30) {
|
|
1208
|
+
let r42 = a30.filter(Boolean);
|
|
1209
|
+
if (r42.length !== 0) return (t14) => {
|
|
1210
|
+
for (let n2 of r42) typeof n2 == "function" ? n2(t14) : n2 && (n2.current = t14);
|
|
1198
1211
|
};
|
|
1199
1212
|
}
|
|
1200
1213
|
|
|
@@ -1210,15 +1223,15 @@ var Be = /* @__PURE__ */ new Set(["ArrowDown", "ArrowUp", "End", "Home", "PageDo
|
|
|
1210
1223
|
var ge = { start: false, end: false };
|
|
1211
1224
|
var dt = [];
|
|
1212
1225
|
var Q = { currentAnchorId: null, visibleMessageIds: dt };
|
|
1213
|
-
function De({ content:
|
|
1214
|
-
if (!
|
|
1215
|
-
let
|
|
1216
|
-
return { start:
|
|
1217
|
-
}
|
|
1218
|
-
function Fe({ content:
|
|
1219
|
-
if (!
|
|
1220
|
-
let S2 =
|
|
1221
|
-
for (let C of ee(
|
|
1226
|
+
function De({ content: e62, scrollEdgeThreshold: t14, spacer: r42, viewport: n2 }) {
|
|
1227
|
+
if (!n2 || !e62) return ge;
|
|
1228
|
+
let o54 = Se({ content: e62, spacer: r42, viewport: n2 });
|
|
1229
|
+
return { start: n2.scrollTop > t14, end: o54 - n2.scrollTop - n2.clientHeight > t14 };
|
|
1230
|
+
}
|
|
1231
|
+
function Fe({ content: e62, scrollMargin: t14, scrollPreviousItemPeek: r42, spacer: n2, viewport: o54, visibleMessageIds: i3 }) {
|
|
1232
|
+
if (!e62 || !o54) return Q;
|
|
1233
|
+
let S2 = o54.getBoundingClientRect(), l5 = S2.top + t14 + r42, d2 = typeof IntersectionObserver > "u", E = [], b2 = null;
|
|
1234
|
+
for (let C of ee(e62, n2)) {
|
|
1222
1235
|
let p3 = C.dataset.messageId;
|
|
1223
1236
|
if (!p3) continue;
|
|
1224
1237
|
let m5 = C.dataset.scrollAnchor === "true", L = m5 || d2 ? C.getBoundingClientRect() : null;
|
|
@@ -1226,100 +1239,100 @@ function Fe({ content: e55, scrollMargin: t10, scrollPreviousItemPeek: r32, spac
|
|
|
1226
1239
|
}
|
|
1227
1240
|
return E.length === 0 && b2 === null ? Q : { currentAnchorId: b2, visibleMessageIds: E };
|
|
1228
1241
|
}
|
|
1229
|
-
function ee(
|
|
1230
|
-
return Array.from(
|
|
1242
|
+
function ee(e62, t14) {
|
|
1243
|
+
return Array.from(e62.children).filter((r42) => r42 instanceof HTMLElement && r42 !== t14);
|
|
1231
1244
|
}
|
|
1232
|
-
function je(
|
|
1233
|
-
for (let
|
|
1234
|
-
let
|
|
1235
|
-
if (
|
|
1245
|
+
function je(e62, t14) {
|
|
1246
|
+
for (let r42 = t14; r42 < e62.length; r42++) {
|
|
1247
|
+
let n2 = e62[r42];
|
|
1248
|
+
if (n2?.dataset.scrollAnchor === "true") return n2;
|
|
1236
1249
|
}
|
|
1237
1250
|
return null;
|
|
1238
1251
|
}
|
|
1239
|
-
function Ge(
|
|
1240
|
-
for (let
|
|
1252
|
+
function Ge(e62, t14) {
|
|
1253
|
+
for (let r42 of e62) if (r42.dataset.scrollAnchor === "true" && !t14.has(r42)) return r42;
|
|
1241
1254
|
return null;
|
|
1242
1255
|
}
|
|
1243
|
-
function Ne(
|
|
1244
|
-
let
|
|
1245
|
-
for (let
|
|
1256
|
+
function Ne(e62, t14) {
|
|
1257
|
+
let r42 = 0;
|
|
1258
|
+
for (let n2 = t14; n2 < e62.length; n2++) if (e62[n2]?.dataset.scrollAnchor === "true" && (r42 += 1, r42 > 1)) return true;
|
|
1246
1259
|
return false;
|
|
1247
1260
|
}
|
|
1248
|
-
function Ue(
|
|
1249
|
-
for (let
|
|
1250
|
-
let
|
|
1251
|
-
if (
|
|
1261
|
+
function Ue(e62) {
|
|
1262
|
+
for (let t14 = e62.length - 1; t14 >= 0; t14--) {
|
|
1263
|
+
let r42 = e62[t14];
|
|
1264
|
+
if (r42?.dataset.scrollAnchor === "true") return r42;
|
|
1252
1265
|
}
|
|
1253
1266
|
return null;
|
|
1254
1267
|
}
|
|
1255
|
-
function Ye({ content:
|
|
1256
|
-
let
|
|
1257
|
-
for (let
|
|
1258
|
-
if (!
|
|
1259
|
-
let i3 =
|
|
1260
|
-
if (i3.bottom >
|
|
1268
|
+
function Ye({ content: e62, spacer: t14, viewport: r42 }) {
|
|
1269
|
+
let n2 = r42.getBoundingClientRect();
|
|
1270
|
+
for (let o54 of ee(e62, t14)) {
|
|
1271
|
+
if (!o54.dataset.messageId) continue;
|
|
1272
|
+
let i3 = o54.getBoundingClientRect();
|
|
1273
|
+
if (i3.bottom > n2.top && i3.top < n2.bottom) return o54;
|
|
1261
1274
|
}
|
|
1262
1275
|
return null;
|
|
1263
1276
|
}
|
|
1264
|
-
function ze({ align:
|
|
1265
|
-
let i3 = pe(
|
|
1266
|
-
if (
|
|
1267
|
-
let d2 = Math.max(0,
|
|
1268
|
-
return i3 - l5.start - (d2 - S2) / 2 -
|
|
1277
|
+
function ze({ align: e62, element: t14, scrollMargin: r42, spacer: n2, viewport: o54 }) {
|
|
1278
|
+
let i3 = pe(t14, o54), S2 = t14.getBoundingClientRect().height, l5 = bt(n2);
|
|
1279
|
+
if (e62 === "center") {
|
|
1280
|
+
let d2 = Math.max(0, o54.clientHeight - l5.start - l5.end);
|
|
1281
|
+
return i3 - l5.start - (d2 - S2) / 2 - r42;
|
|
1269
1282
|
}
|
|
1270
|
-
if (
|
|
1271
|
-
if (
|
|
1272
|
-
let d2 = i3 + S2, E =
|
|
1273
|
-
return i3 >= E && d2 <= b2 ?
|
|
1283
|
+
if (e62 === "end") return i3 - o54.clientHeight + S2 + l5.end + r42;
|
|
1284
|
+
if (e62 === "nearest") {
|
|
1285
|
+
let d2 = i3 + S2, E = o54.scrollTop + l5.start, b2 = o54.scrollTop + o54.clientHeight - l5.end;
|
|
1286
|
+
return i3 >= E && d2 <= b2 ? o54.scrollTop : i3 < E ? i3 - l5.start - r42 : d2 - o54.clientHeight + l5.end + r42;
|
|
1274
1287
|
}
|
|
1275
|
-
return i3 - l5.start -
|
|
1288
|
+
return i3 - l5.start - r42;
|
|
1276
1289
|
}
|
|
1277
|
-
function pe(
|
|
1278
|
-
let
|
|
1279
|
-
return
|
|
1290
|
+
function pe(e62, t14) {
|
|
1291
|
+
let r42 = e62.getBoundingClientRect(), n2 = t14.getBoundingClientRect();
|
|
1292
|
+
return r42.top - n2.top + t14.scrollTop;
|
|
1280
1293
|
}
|
|
1281
|
-
function te(
|
|
1282
|
-
return
|
|
1294
|
+
function te(e62, t14) {
|
|
1295
|
+
return e62.getBoundingClientRect().top - t14.getBoundingClientRect().top;
|
|
1283
1296
|
}
|
|
1284
|
-
function qe({ content:
|
|
1285
|
-
let
|
|
1286
|
-
return
|
|
1297
|
+
function qe({ content: e62, scrollTop: t14, spacer: r42, viewport: n2 }) {
|
|
1298
|
+
let o54 = Se({ content: e62, spacer: r42, viewport: n2 });
|
|
1299
|
+
return t14 + n2.clientHeight - o54;
|
|
1287
1300
|
}
|
|
1288
|
-
function Se({ content:
|
|
1289
|
-
let
|
|
1290
|
-
for (let d2 of
|
|
1301
|
+
function Se({ content: e62, spacer: t14, viewport: r42 }) {
|
|
1302
|
+
let n2 = ee(e62, t14), o54 = We(e62), i3 = r42.getBoundingClientRect(), S2 = r42.scrollTop, l5 = o54.start + o54.end;
|
|
1303
|
+
for (let d2 of n2) {
|
|
1291
1304
|
let E = d2.getBoundingClientRect();
|
|
1292
|
-
l5 = Math.max(l5, E.bottom - i3.top + S2 +
|
|
1305
|
+
l5 = Math.max(l5, E.bottom - i3.top + S2 + o54.end);
|
|
1293
1306
|
}
|
|
1294
1307
|
return l5;
|
|
1295
1308
|
}
|
|
1296
|
-
function Ke(
|
|
1297
|
-
return Math.max(0,
|
|
1309
|
+
function Ke(e62) {
|
|
1310
|
+
return Math.max(0, e62.scrollHeight - e62.clientHeight);
|
|
1298
1311
|
}
|
|
1299
|
-
function We(
|
|
1300
|
-
let
|
|
1301
|
-
return { end: Re(
|
|
1312
|
+
function We(e62) {
|
|
1313
|
+
let t14 = window.getComputedStyle(e62);
|
|
1314
|
+
return { end: Re(t14.paddingBlockEnd || t14.paddingBottom), start: Re(t14.paddingBlockStart || t14.paddingTop) };
|
|
1302
1315
|
}
|
|
1303
|
-
function bt(
|
|
1304
|
-
let
|
|
1305
|
-
return
|
|
1316
|
+
function bt(e62) {
|
|
1317
|
+
let t14 = e62?.parentElement;
|
|
1318
|
+
return t14 ? We(t14) : { end: 0, start: 0 };
|
|
1306
1319
|
}
|
|
1307
|
-
function $e(
|
|
1308
|
-
if (!
|
|
1309
|
-
let
|
|
1310
|
-
return Re(
|
|
1320
|
+
function $e(e62) {
|
|
1321
|
+
if (!e62) return 0;
|
|
1322
|
+
let t14 = window.getComputedStyle(e62), r42 = t14.rowGap === "normal" ? t14.gap : t14.rowGap;
|
|
1323
|
+
return Re(r42);
|
|
1311
1324
|
}
|
|
1312
|
-
function Re(
|
|
1313
|
-
if (!
|
|
1314
|
-
let
|
|
1315
|
-
return Number.isFinite(
|
|
1325
|
+
function Re(e62) {
|
|
1326
|
+
if (!e62) return 0;
|
|
1327
|
+
let t14 = Number.parseFloat(e62);
|
|
1328
|
+
return Number.isFinite(t14) ? t14 : 0;
|
|
1316
1329
|
}
|
|
1317
|
-
function Je({ refs:
|
|
1318
|
-
let { streamingTurnRef:
|
|
1319
|
-
l5.current !== null && (window.clearTimeout(l5.current), l5.current = null), S2.current !== c8 && (S2.current = c8,
|
|
1320
|
-
l5.current = null, S2.current = false,
|
|
1330
|
+
function Je({ refs: e62, commitScrollState: t14, scheduleStateCommit: r42, scheduleVisibilitySync: n2 }) {
|
|
1331
|
+
let { streamingTurnRef: o54, autoScrollRef: i3, autoscrollingRef: S2, autoscrollingTimeoutRef: l5, contentRef: d2, defaultScrollPositionAppliedRef: E, itemCountRef: b2, messageElementsRef: C, modeRef: p3, pendingScrollToMessageRef: m5, prependRestoreRef: L, scrollMarginRef: y, scrollPreviousItemPeekRef: u, spacerGapRef: x, spacerHeightRef: Y, spacerRef: k, viewportRef: _ } = e62, G = g.useCallback((c8) => {
|
|
1332
|
+
l5.current !== null && (window.clearTimeout(l5.current), l5.current = null), S2.current !== c8 && (S2.current = c8, t14()), c8 && (l5.current = window.setTimeout(() => {
|
|
1333
|
+
l5.current = null, S2.current = false, t14();
|
|
1321
1334
|
}, ke));
|
|
1322
|
-
}, [
|
|
1335
|
+
}, [t14]), v = g.useCallback((c8) => {
|
|
1323
1336
|
let f9 = k.current;
|
|
1324
1337
|
if (!f9) return;
|
|
1325
1338
|
let h = Math.max(0, Math.ceil(c8));
|
|
@@ -1329,20 +1342,20 @@ function Je({ refs: e55, commitScrollState: t10, scheduleStateCommit: r32, sched
|
|
|
1329
1342
|
if (!P) return;
|
|
1330
1343
|
let V = Math.max(0, c8);
|
|
1331
1344
|
if (Math.abs(P.scrollTop - V) <= J) {
|
|
1332
|
-
P.scrollTop = V,
|
|
1345
|
+
P.scrollTop = V, t14();
|
|
1333
1346
|
return;
|
|
1334
1347
|
}
|
|
1335
|
-
h && G(true), P.scrollTo({ top: V, behavior: f9 }),
|
|
1336
|
-
}, [
|
|
1348
|
+
h && G(true), P.scrollTo({ top: V, behavior: f9 }), r42();
|
|
1349
|
+
}, [t14, r42, G]), N = g.useCallback(({ behavior: c8 = "auto" } = {}) => _.current ? (v(0), o54.current = null, p3.current = "free-scrolling", H(0, { behavior: c8 }), n2(), true) : false, [n2, H, v]), ne = g.useCallback(({ behavior: c8 = "auto" } = {}) => {
|
|
1337
1350
|
let f9 = _.current;
|
|
1338
|
-
return f9 ? (v(0),
|
|
1339
|
-
}, [
|
|
1351
|
+
return f9 ? (v(0), o54.current = null, p3.current = i3.current ? "following-bottom" : "free-scrolling", H(Ke(f9), { autoscrolling: true, behavior: c8 }), n2(), true) : false;
|
|
1352
|
+
}, [n2, H, v]), A = g.useCallback((c8, { align: f9 = "start", behavior: h = "auto", scrollMargin: P = y.current } = {}, { keepPreviousPeek: V = false } = {}) => {
|
|
1340
1353
|
let z = d2.current, q = _.current;
|
|
1341
1354
|
if (!z || !q || !z.contains(c8)) return false;
|
|
1342
1355
|
let K = ze({ align: f9, element: c8, scrollMargin: V ? P + u.current : P, spacer: k.current, viewport: q }), se = qe({ content: z, scrollTop: K, spacer: k.current, viewport: q });
|
|
1343
|
-
return v(se), L.current = { element: c8, viewportTop: te(c8, q) }, p3.current = V ? "anchored-to-message" : "settling-jump",
|
|
1344
|
-
}, [
|
|
1345
|
-
let c8 =
|
|
1356
|
+
return v(se), L.current = { element: c8, viewportTop: te(c8, q) }, p3.current = V ? "anchored-to-message" : "settling-jump", o54.current = V ? c8 : null, H(K, { behavior: h }), n2(), true;
|
|
1357
|
+
}, [n2, H, v]), B = g.useCallback(() => {
|
|
1358
|
+
let c8 = o54.current;
|
|
1346
1359
|
return !c8 || !c8.isConnected || p3.current !== "anchored-to-message" ? false : A(c8, { align: "start" }, { keepPreviousPeek: true });
|
|
1347
1360
|
}, [A]), D = g.useCallback((c8, f9) => {
|
|
1348
1361
|
let h = C.current.get(c8);
|
|
@@ -1355,52 +1368,52 @@ function Je({ refs: e55, commitScrollState: t10, scheduleStateCommit: r32, sched
|
|
|
1355
1368
|
return !f9 || !A(f9, c8.options) ? false : (m5.current = null, E.current = true, true);
|
|
1356
1369
|
}, [A]), reanchorToAnchoredMessage: B, scrollToElement: A, scrollToEnd: ne, scrollToMessage: D, scrollToStart: N };
|
|
1357
1370
|
}
|
|
1358
|
-
function Qe(
|
|
1359
|
-
let
|
|
1360
|
-
return { getSnapshot: () =>
|
|
1361
|
-
|
|
1362
|
-
}, subscribe: (
|
|
1363
|
-
let l5 =
|
|
1364
|
-
return
|
|
1365
|
-
|
|
1371
|
+
function Qe(e62, t14) {
|
|
1372
|
+
let r42 = e62, n2 = /* @__PURE__ */ new Set();
|
|
1373
|
+
return { getSnapshot: () => r42, hasListeners: () => n2.size > 0, setSnapshot: (o54) => {
|
|
1374
|
+
t14(r42, o54) || (r42 = o54, n2.forEach((i3) => i3()));
|
|
1375
|
+
}, subscribe: (o54, i3, S2) => {
|
|
1376
|
+
let l5 = n2.size === 0;
|
|
1377
|
+
return n2.add(o54), l5 && i3?.(), () => {
|
|
1378
|
+
n2.delete(o54), n2.size === 0 && S2?.();
|
|
1366
1379
|
};
|
|
1367
1380
|
} };
|
|
1368
1381
|
}
|
|
1369
|
-
function Xe(
|
|
1370
|
-
return Qe(
|
|
1382
|
+
function Xe(e62, t14) {
|
|
1383
|
+
return Qe(e62, t14);
|
|
1371
1384
|
}
|
|
1372
1385
|
function Ze() {
|
|
1373
1386
|
return Qe(Q, Tt);
|
|
1374
1387
|
}
|
|
1375
|
-
function et(
|
|
1376
|
-
return
|
|
1388
|
+
function et(e62, t14) {
|
|
1389
|
+
return e62.start === t14.start && e62.end === t14.end;
|
|
1377
1390
|
}
|
|
1378
|
-
function Tt(
|
|
1379
|
-
return
|
|
1391
|
+
function Tt(e62, t14) {
|
|
1392
|
+
return e62.currentAnchorId !== t14.currentAnchorId || e62.visibleMessageIds.length !== t14.visibleMessageIds.length ? false : e62.visibleMessageIds.every((r42, n2) => r42 === t14.visibleMessageIds[n2]);
|
|
1380
1393
|
}
|
|
1381
|
-
function tt({ autoScroll:
|
|
1382
|
-
let
|
|
1383
|
-
return A.current === null && (A.current = Xe(ge, et)), f9.current === null && (f9.current = Ze()),
|
|
1394
|
+
function tt({ autoScroll: e62, scrollEdgeThreshold: t14, scrollMargin: r42, scrollPreviousItemPeek: n2 }) {
|
|
1395
|
+
let o54 = g.useRef(e62), i3 = g.useRef(false), S2 = g.useRef(null), l5 = g.useRef(false), d2 = g.useRef(t14), E = g.useRef(0), b2 = g.useRef(null), C = g.useRef(0), p3 = g.useRef(e62 ? "following-bottom" : "free-scrolling"), m5 = g.useRef(/* @__PURE__ */ new Map()), L = g.useRef(null), y = g.useRef(null), u = g.useRef(null), x = g.useRef(n2), Y = g.useRef(true), k = g.useRef(null), _ = g.useRef(r42), G = g.useRef(null), v = g.useRef(0), H = g.useRef(0), N = g.useRef(null), ne = g.useRef(null), A = g.useRef(null), B = g.useRef(null), D = g.useRef(null), U = g.useRef(null), c8 = g.useRef(null), f9 = g.useRef(null), h = g.useRef(/* @__PURE__ */ new Set()), P = g.useRef(/* @__PURE__ */ new WeakSet());
|
|
1396
|
+
return A.current === null && (A.current = Xe(ge, et)), f9.current === null && (f9.current = Ze()), o54.current = e62, d2.current = t14, _.current = r42, x.current = n2, { autoScrollRef: o54, autoscrollingRef: i3, autoscrollingTimeoutRef: B, streamingTurnRef: u, contentRef: S2, defaultScrollPositionAppliedRef: l5, firstItemRef: b2, itemCountRef: E, lastScrollTopRef: C, messageElementsRef: m5, modeRef: p3, pendingScrollFrameRef: G, pendingScrollToMessageRef: L, prependRestoreRef: y, preserveScrollOnPrependRef: Y, rootRef: k, scrollEdgeThresholdRef: d2, scrollMarginRef: _, scrollPreviousItemPeekRef: x, spacerGapRef: v, spacerHeightRef: H, spacerRef: N, stateFrameRef: ne, stateStore: A.current, viewportRef: D, visibilityFrameRef: U, visibilityObserverRef: c8, visibilityStore: f9.current, visibleMessageIdsRef: h, handledScrollAnchorsRef: P };
|
|
1384
1397
|
}
|
|
1385
|
-
function rt(
|
|
1386
|
-
return g.useCallback((
|
|
1387
|
-
|
|
1388
|
-
}, [
|
|
1398
|
+
function rt(e62, t14) {
|
|
1399
|
+
return g.useCallback((r42) => {
|
|
1400
|
+
e62.current = r42, r42 && t14();
|
|
1401
|
+
}, [e62, t14]);
|
|
1389
1402
|
}
|
|
1390
|
-
function nt({ autoScroll:
|
|
1391
|
-
let i3 = tt({ autoScroll:
|
|
1392
|
-
q.current !==
|
|
1403
|
+
function nt({ autoScroll: e62 = false, defaultScrollPosition: t14 = "end", scrollEdgeThreshold: r42 = xe, scrollPreviousItemPeek: n2 = Ve, scrollMargin: o54 = _e }) {
|
|
1404
|
+
let i3 = tt({ autoScroll: e62, scrollEdgeThreshold: r42, scrollMargin: o54, scrollPreviousItemPeek: n2 }), { streamingTurnRef: S2, autoScrollRef: l5, autoscrollingRef: d2, autoscrollingTimeoutRef: E, contentRef: b2, defaultScrollPositionAppliedRef: C, firstItemRef: p3, itemCountRef: m5, lastScrollTopRef: L, messageElementsRef: y, modeRef: u, pendingScrollFrameRef: x, pendingScrollToMessageRef: Y, prependRestoreRef: k, preserveScrollOnPrependRef: _, rootRef: G, scrollEdgeThresholdRef: v, scrollMarginRef: H, scrollPreviousItemPeekRef: N, spacerGapRef: ne, spacerHeightRef: A, spacerRef: B, stateFrameRef: D, stateStore: U, viewportRef: c8, visibilityFrameRef: f9, visibilityObserverRef: h, visibilityStore: P, visibleMessageIdsRef: V, handledScrollAnchorsRef: z } = i3, q = g.useRef(t14);
|
|
1405
|
+
q.current !== t14 && (q.current = t14, C.current = false);
|
|
1393
1406
|
let K = g.useCallback((s4) => {
|
|
1394
|
-
let
|
|
1395
|
-
for (let W of [
|
|
1407
|
+
let a30 = G.current, T = c8.current, O = [s4.start && "start", s4.end && "end"].filter(Boolean).join(" "), ue = d2.current;
|
|
1408
|
+
for (let W of [a30, T]) W && (O ? W.setAttribute("data-scrollable", O) : W.removeAttribute("data-scrollable"), W.toggleAttribute("data-autoscrolling", ue));
|
|
1396
1409
|
}, []), se = g.useCallback((s4) => {
|
|
1397
|
-
let
|
|
1398
|
-
L.current =
|
|
1410
|
+
let a30 = c8.current?.scrollTop ?? 0, T = a30 < L.current - J;
|
|
1411
|
+
L.current = a30, l5.current && !s4.end && u.current !== "settling-jump" && u.current !== "anchored-to-message" ? u.current = "following-bottom" : u.current === "following-bottom" && s4.end && T && !d2.current && (u.current = "free-scrolling");
|
|
1399
1412
|
}, []), F = g.useCallback(() => {
|
|
1400
1413
|
let s4 = De({ content: b2.current, scrollEdgeThreshold: v.current, spacer: B.current, viewport: c8.current });
|
|
1401
1414
|
se(s4);
|
|
1402
|
-
let
|
|
1403
|
-
K(
|
|
1415
|
+
let a30 = u.current === "following-bottom" ? { ...s4, end: false } : s4;
|
|
1416
|
+
K(a30), U.setSnapshot(a30);
|
|
1404
1417
|
}, [se, U, K]), oe = g.useCallback(() => {
|
|
1405
1418
|
D.current === null && (D.current = window.requestAnimationFrame(() => {
|
|
1406
1419
|
D.current = null, F();
|
|
@@ -1410,54 +1423,54 @@ function nt({ autoScroll: e55 = false, defaultScrollPosition: t10 = "end", scrol
|
|
|
1410
1423
|
f9.current = null, P.hasListeners() && P.setSnapshot(Fe({ content: b2.current, scrollMargin: H.current, scrollPreviousItemPeek: N.current, spacer: B.current, viewport: c8.current, visibleMessageIds: V.current }));
|
|
1411
1424
|
}));
|
|
1412
1425
|
}, [P]), { flushPendingScrollToMessage: ce, reanchorToAnchoredMessage: me, scrollToElement: le, scrollToEnd: I2, scrollToMessage: Me, scrollToStart: ae } = Je({ refs: i3, commitScrollState: F, scheduleStateCommit: oe, scheduleVisibilitySync: w2 }), de = g.useCallback(() => {
|
|
1413
|
-
let s4 = k.current,
|
|
1414
|
-
if (!s4 || !
|
|
1415
|
-
let O = te(s4.element,
|
|
1416
|
-
return Math.abs(O) <= J ? false : (
|
|
1426
|
+
let s4 = k.current, a30 = c8.current;
|
|
1427
|
+
if (!s4 || !a30 || !s4.element.isConnected) return false;
|
|
1428
|
+
let O = te(s4.element, a30) - s4.viewportTop;
|
|
1429
|
+
return Math.abs(O) <= J ? false : (a30.scrollTop += O, s4.viewportTop = te(s4.element, a30), oe(), w2(), true);
|
|
1417
1430
|
}, [oe, w2]), Z = g.useCallback(() => {
|
|
1418
|
-
let s4 = b2.current,
|
|
1419
|
-
if (!s4 || !
|
|
1431
|
+
let s4 = b2.current, a30 = c8.current;
|
|
1432
|
+
if (!s4 || !a30) {
|
|
1420
1433
|
k.current = null;
|
|
1421
1434
|
return;
|
|
1422
1435
|
}
|
|
1423
|
-
let T = Ye({ content: s4, spacer: B.current, viewport:
|
|
1424
|
-
k.current = T ? { element: T, viewportTop: te(T,
|
|
1436
|
+
let T = Ye({ content: s4, spacer: B.current, viewport: a30 });
|
|
1437
|
+
k.current = T ? { element: T, viewportTop: te(T, a30) } : null;
|
|
1425
1438
|
}, []), be = g.useCallback(() => {
|
|
1426
1439
|
x.current === null && (x.current = window.requestAnimationFrame(() => {
|
|
1427
1440
|
x.current = null, ce() && Z();
|
|
1428
1441
|
}));
|
|
1429
1442
|
}, [Z, ce]), ie = g.useCallback(() => {
|
|
1430
|
-
if (!
|
|
1443
|
+
if (!t14 || C.current || m5.current === 0) return false;
|
|
1431
1444
|
let s4 = false;
|
|
1432
|
-
if (
|
|
1433
|
-
let
|
|
1434
|
-
if (!
|
|
1445
|
+
if (t14 === "last-anchor") {
|
|
1446
|
+
let a30 = b2.current, T = c8.current, O = a30 && T ? Ue(ee(a30, B.current)) : null;
|
|
1447
|
+
if (!a30 || !T || !O) s4 = I2({ behavior: "auto" });
|
|
1435
1448
|
else {
|
|
1436
1449
|
let ue = pe(O, T);
|
|
1437
|
-
s4 = Se({ content:
|
|
1450
|
+
s4 = Se({ content: a30, spacer: B.current, viewport: T }) - ue <= T.clientHeight ? I2({ behavior: "auto" }) : le(O, { align: "start" }, { keepPreviousPeek: true });
|
|
1438
1451
|
}
|
|
1439
|
-
} else s4 =
|
|
1452
|
+
} else s4 = t14 === "end" ? I2({ behavior: "auto" }) : ae({ behavior: "auto" });
|
|
1440
1453
|
return s4 ? (C.current = true, true) : false;
|
|
1441
|
-
}, [
|
|
1454
|
+
}, [t14, le, I2, ae]), Te = g.useCallback(() => {
|
|
1442
1455
|
let s4 = b2.current;
|
|
1443
1456
|
if (!s4) return;
|
|
1444
|
-
let
|
|
1445
|
-
m5.current =
|
|
1457
|
+
let a30 = ee(s4, B.current), T = m5.current, O = p3.current;
|
|
1458
|
+
m5.current = a30.length, p3.current = a30[0] ?? null, (() => {
|
|
1446
1459
|
if (ce()) return;
|
|
1447
1460
|
if (T === 0) {
|
|
1448
|
-
if (ie() ||
|
|
1461
|
+
if (ie() || a30.length > 0 && l5.current && I2({ behavior: "auto" })) return;
|
|
1449
1462
|
F(), w2();
|
|
1450
1463
|
return;
|
|
1451
1464
|
}
|
|
1452
|
-
let W = O ?
|
|
1465
|
+
let W = O ? a30.indexOf(O) : -1;
|
|
1453
1466
|
if (_.current && W > 0) {
|
|
1454
1467
|
de();
|
|
1455
1468
|
return;
|
|
1456
1469
|
}
|
|
1457
|
-
if (
|
|
1458
|
-
let $ = je(
|
|
1470
|
+
if (a30.length > T) {
|
|
1471
|
+
let $ = je(a30, T);
|
|
1459
1472
|
if ($) {
|
|
1460
|
-
if (l5.current && u.current === "following-bottom" && Ne(
|
|
1473
|
+
if (l5.current && u.current === "following-bottom" && Ne(a30, T)) {
|
|
1461
1474
|
I2({ behavior: "auto" });
|
|
1462
1475
|
return;
|
|
1463
1476
|
}
|
|
@@ -1465,8 +1478,8 @@ function nt({ autoScroll: e55 = false, defaultScrollPosition: t10 = "end", scrol
|
|
|
1465
1478
|
return;
|
|
1466
1479
|
}
|
|
1467
1480
|
}
|
|
1468
|
-
if (
|
|
1469
|
-
let $ = Ge(
|
|
1481
|
+
if (a30.length === T) {
|
|
1482
|
+
let $ = Ge(a30, z.current);
|
|
1470
1483
|
if ($) {
|
|
1471
1484
|
le($, { align: "start" }, { keepPreviousPeek: true }), z.current.add($);
|
|
1472
1485
|
return;
|
|
@@ -1492,21 +1505,21 @@ function nt({ autoScroll: e55 = false, defaultScrollPosition: t10 = "end", scrol
|
|
|
1492
1505
|
w2();
|
|
1493
1506
|
return;
|
|
1494
1507
|
}
|
|
1495
|
-
h.current || (h.current = new IntersectionObserver((
|
|
1496
|
-
for (let T of
|
|
1508
|
+
h.current || (h.current = new IntersectionObserver((a30) => {
|
|
1509
|
+
for (let T of a30) {
|
|
1497
1510
|
let O = T.target.dataset.messageId;
|
|
1498
1511
|
O && (T.isIntersecting ? V.current.add(O) : V.current.delete(O));
|
|
1499
1512
|
}
|
|
1500
1513
|
w2();
|
|
1501
|
-
}, { root: s4, rootMargin: `${-(H.current + N.current)}px 0px 0px 0px`, threshold: [0, 0.01, 0.5, 1] })), y.current.forEach((
|
|
1502
|
-
h.current?.observe(
|
|
1514
|
+
}, { root: s4, rootMargin: `${-(H.current + N.current)}px 0px 0px 0px`, threshold: [0, 0.01, 0.5, 1] })), y.current.forEach((a30) => {
|
|
1515
|
+
h.current?.observe(a30);
|
|
1503
1516
|
}), w2();
|
|
1504
1517
|
}
|
|
1505
1518
|
}, [w2, P]), he = g.useCallback(() => {
|
|
1506
1519
|
f9.current !== null && (window.cancelAnimationFrame(f9.current), f9.current = null), h.current?.disconnect(), h.current = null, V.current.clear(), P.setSnapshot(Q);
|
|
1507
|
-
}, [P]), pt = g.useCallback((s4,
|
|
1508
|
-
if (
|
|
1509
|
-
y.current.set(s4,
|
|
1520
|
+
}, [P]), pt = g.useCallback((s4, a30, T) => {
|
|
1521
|
+
if (a30) {
|
|
1522
|
+
y.current.set(s4, a30), h.current?.observe(a30), w2(), Y.current?.messageId === s4 && be();
|
|
1510
1523
|
return;
|
|
1511
1524
|
}
|
|
1512
1525
|
T && y.current.get(s4) === T && (y.current.delete(s4), V.current.delete(s4), h.current?.unobserve(T), w2());
|
|
@@ -1524,54 +1537,54 @@ function nt({ autoScroll: e55 = false, defaultScrollPosition: t10 = "end", scrol
|
|
|
1524
1537
|
}, [ie]), g.useEffect(() => () => {
|
|
1525
1538
|
D.current !== null && (window.cancelAnimationFrame(D.current), D.current = null), f9.current !== null && (window.cancelAnimationFrame(f9.current), f9.current = null), E.current !== null && (window.clearTimeout(E.current), E.current = null), x.current !== null && (window.cancelAnimationFrame(x.current), x.current = null), h.current?.disconnect(), h.current = null;
|
|
1526
1539
|
}, []), g.useLayoutEffect(() => {
|
|
1527
|
-
if (
|
|
1540
|
+
if (e62 && u.current === "following-bottom" && m5.current > 0) {
|
|
1528
1541
|
I2({ behavior: "auto" });
|
|
1529
1542
|
return;
|
|
1530
1543
|
}
|
|
1531
1544
|
F();
|
|
1532
|
-
}, [
|
|
1545
|
+
}, [e62, F, I2]), { context: mt, registerMessage: pt };
|
|
1533
1546
|
}
|
|
1534
|
-
function lt(
|
|
1535
|
-
let
|
|
1536
|
-
return
|
|
1547
|
+
function lt(e62) {
|
|
1548
|
+
let t14 = g.useRef(e62);
|
|
1549
|
+
return t14.current = e62, t14;
|
|
1537
1550
|
}
|
|
1538
1551
|
var st = g.createContext(null);
|
|
1539
1552
|
var ct = g.createContext(null);
|
|
1540
1553
|
function X2() {
|
|
1541
|
-
let
|
|
1542
|
-
if (!
|
|
1543
|
-
return
|
|
1554
|
+
let e62 = g.useContext(st);
|
|
1555
|
+
if (!e62) throw new Error("useMessageScroller must be used within a MessageScroller.");
|
|
1556
|
+
return e62;
|
|
1544
1557
|
}
|
|
1545
1558
|
function Et() {
|
|
1546
|
-
let
|
|
1547
|
-
if (!
|
|
1548
|
-
return
|
|
1559
|
+
let e62 = g.useContext(ct);
|
|
1560
|
+
if (!e62) throw new Error("MessageScrollerItem must be used within a MessageScroller.");
|
|
1561
|
+
return e62;
|
|
1549
1562
|
}
|
|
1550
|
-
function at({ autoScroll:
|
|
1551
|
-
let { context: S2, registerMessage: l5 } = nt({ autoScroll:
|
|
1552
|
-
return jsx3(st.Provider, { value: S2, children: jsx3(ct.Provider, { value: l5, children:
|
|
1563
|
+
function at({ autoScroll: e62 = false, children: t14, defaultScrollPosition: r42 = "end", scrollEdgeThreshold: n2, scrollPreviousItemPeek: o54, scrollMargin: i3 }) {
|
|
1564
|
+
let { context: S2, registerMessage: l5 } = nt({ autoScroll: e62, defaultScrollPosition: r42, scrollEdgeThreshold: n2, scrollPreviousItemPeek: o54, scrollMargin: i3 });
|
|
1565
|
+
return jsx3(st.Provider, { value: S2, children: jsx3(ct.Provider, { value: l5, children: t14 }) });
|
|
1553
1566
|
}
|
|
1554
|
-
function it({ children:
|
|
1555
|
-
let { setRootElement:
|
|
1556
|
-
return jsx3("div", { ref:
|
|
1567
|
+
function it({ children: e62, ...t14 }) {
|
|
1568
|
+
let { setRootElement: r42 } = X2();
|
|
1569
|
+
return jsx3("div", { ref: r42, ...t14, children: e62 });
|
|
1557
1570
|
}
|
|
1558
|
-
function ut({ "aria-label":
|
|
1571
|
+
function ut({ "aria-label": e62, children: t14, onKeyDown: r42, onScroll: n2, onTouchMove: o54, onWheel: i3, preserveScrollOnPrepend: S2 = true, ref: l5, role: d2, tabIndex: E, ...b2 }) {
|
|
1559
1572
|
let { handleResize: C, preserveScrollOnPrependRef: p3, setViewportElement: m5, syncAfterScroll: L, userScrollIntent: y, viewportRef: u } = X2();
|
|
1560
1573
|
p3.current = S2;
|
|
1561
1574
|
let x = g.useCallback((v) => {
|
|
1562
1575
|
m5(v), f8(l5)?.(v);
|
|
1563
1576
|
}, [l5, m5]);
|
|
1564
1577
|
function Y(v) {
|
|
1565
|
-
L(),
|
|
1578
|
+
L(), n2?.(v);
|
|
1566
1579
|
}
|
|
1567
1580
|
function k(v) {
|
|
1568
1581
|
y(), i3?.(v);
|
|
1569
1582
|
}
|
|
1570
1583
|
function _(v) {
|
|
1571
|
-
y(),
|
|
1584
|
+
y(), o54?.(v);
|
|
1572
1585
|
}
|
|
1573
1586
|
function G(v) {
|
|
1574
|
-
Be.has(v.key) && y(),
|
|
1587
|
+
Be.has(v.key) && y(), r42?.(v);
|
|
1575
1588
|
}
|
|
1576
1589
|
return g.useEffect(() => {
|
|
1577
1590
|
let v = u.current;
|
|
@@ -1582,12 +1595,12 @@ function ut({ "aria-label": e55, children: t10, onKeyDown: r32, onScroll: n, onT
|
|
|
1582
1595
|
return N.observe(v), () => {
|
|
1583
1596
|
window.cancelAnimationFrame(H), N.disconnect();
|
|
1584
1597
|
};
|
|
1585
|
-
}, [C, u]), jsx3("div", { ref: x, role: d2 ?? "region", "aria-label":
|
|
1598
|
+
}, [C, u]), jsx3("div", { ref: x, role: d2 ?? "region", "aria-label": e62 ?? "Messages", tabIndex: E ?? 0, onKeyDown: G, onScroll: Y, onTouchMove: _, onWheel: k, ...b2, children: t14 });
|
|
1586
1599
|
}
|
|
1587
|
-
function ft({ "aria-relevant":
|
|
1600
|
+
function ft({ "aria-relevant": e62, children: t14, ref: r42, role: n2, spacerClassName: o54, ...i3 }) {
|
|
1588
1601
|
let { handleContentChange: S2, handleResize: l5, setContentElement: d2, setSpacerElement: E } = X2(), b2 = g.useRef(null), C = g.useCallback((p3) => {
|
|
1589
|
-
b2.current = p3, d2(p3), f8(
|
|
1590
|
-
}, [
|
|
1602
|
+
b2.current = p3, d2(p3), f8(r42)?.(p3);
|
|
1603
|
+
}, [r42, d2]);
|
|
1591
1604
|
return g.useLayoutEffect(() => {
|
|
1592
1605
|
let p3 = b2.current;
|
|
1593
1606
|
if (!p3 || (S2(), typeof MutationObserver > "u")) return;
|
|
@@ -1604,23 +1617,23 @@ function ft({ "aria-relevant": e55, children: t10, ref: r32, role: n, spacerClas
|
|
|
1604
1617
|
return L.observe(p3), () => {
|
|
1605
1618
|
window.cancelAnimationFrame(m5), L.disconnect();
|
|
1606
1619
|
};
|
|
1607
|
-
}, [l5]), jsxs("div", { ref: C, role:
|
|
1620
|
+
}, [l5]), jsxs("div", { ref: C, role: n2 ?? "log", "aria-relevant": e62 ?? "additions", ...i3, children: [t14, jsx3("div", { ref: E, "aria-hidden": "true", "data-message-scroller-spacer": "", hidden: true, className: o54 })] });
|
|
1608
1621
|
}
|
|
1609
|
-
function gt({ messageId:
|
|
1610
|
-
let
|
|
1622
|
+
function gt({ messageId: e62, ref: t14, scrollAnchor: r42 = false, ...n2 }) {
|
|
1623
|
+
let o54 = Et(), i3 = g.useRef(null), S2 = g.useCallback((l5) => {
|
|
1611
1624
|
let d2 = i3.current;
|
|
1612
|
-
i3.current = l5,
|
|
1613
|
-
}, [
|
|
1614
|
-
return jsx3("div", { ref: S2, "data-message-id":
|
|
1625
|
+
i3.current = l5, e62 && o54(e62, l5, d2), f8(t14)?.(l5);
|
|
1626
|
+
}, [e62, t14, o54]);
|
|
1627
|
+
return jsx3("div", { ref: S2, "data-message-id": e62, "data-scroll-anchor": r42 ? "true" : "false", ...n2 });
|
|
1615
1628
|
}
|
|
1616
|
-
function St({ behavior:
|
|
1617
|
-
let { scrollToEnd: d2, scrollToStart: E, stateStore: b$1 } = X2(), C = lt(
|
|
1629
|
+
function St({ behavior: e62 = "smooth", children: t14, direction: r42 = "end", onClick: n2, render: o54, tabIndex: i3, type: S2 = "button", ...l5 }) {
|
|
1630
|
+
let { scrollToEnd: d2, scrollToStart: E, stateStore: b$1 } = X2(), C = lt(n2), p3 = g.useCallback((u) => b$1.subscribe(u), [b$1]), m5 = g.useCallback(() => {
|
|
1618
1631
|
let u = b$1.getSnapshot();
|
|
1619
|
-
return
|
|
1620
|
-
}, [
|
|
1621
|
-
L && (C.current?.(u), u.defaultPrevented || (u.currentTarget.blur(),
|
|
1622
|
-
}, [
|
|
1623
|
-
return S({ defaultTagName: "button", props: d({ type: S2, inert: !L, tabIndex: L ? i3 : -1, children:
|
|
1632
|
+
return r42 === "start" ? u.start : u.end;
|
|
1633
|
+
}, [r42, b$1]), L = g.useSyncExternalStore(p3, m5, m5), y = g.useCallback((u) => {
|
|
1634
|
+
L && (C.current?.(u), u.defaultPrevented || (u.currentTarget.blur(), r42 === "start" ? E({ behavior: e62 }) : d2({ behavior: e62 })));
|
|
1635
|
+
}, [e62, r42, L, C, d2, E]);
|
|
1636
|
+
return S({ defaultTagName: "button", props: d({ type: S2, inert: !L, tabIndex: L ? i3 : -1, children: t14 ?? jsxs("span", { children: ["Scroll to ", r42] }), onClick: y }, l5), render: o54, state: { active: L, direction: r42 }, stateAttributesMapping: { active: (u) => ({ "data-active": u ? "true" : "false" }) } });
|
|
1624
1637
|
}
|
|
1625
1638
|
var $t = { Provider: at, Root: it, Viewport: ut, Content: ft, Item: gt, Button: St };
|
|
1626
1639
|
|
|
@@ -1859,14 +1872,14 @@ var use = React2[" use ".trim().toString()];
|
|
|
1859
1872
|
// ../../apps/web/src/components/ui/button.tsx
|
|
1860
1873
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1861
1874
|
var buttonVariants = cva(
|
|
1862
|
-
"group/button inline-flex shrink-0 items-center justify-center rounded-
|
|
1875
|
+
"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-[background-color,border-color,color,box-shadow,translate] duration-(--duration-quick) ease-(--ease-smooth-out) motion-reduce:transition-none outline-none select-none touch-manipulation focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/25 motion-safe:active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1863
1876
|
{
|
|
1864
1877
|
variants: {
|
|
1865
1878
|
variant: {
|
|
1866
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/
|
|
1867
|
-
outline: "border-
|
|
1868
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-
|
|
1869
|
-
ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground
|
|
1879
|
+
default: "surface-primary bg-primary bg-clip-border text-primary-foreground hover:bg-primary/90 active:shadow-field",
|
|
1880
|
+
outline: "surface-control border-input/80 bg-card text-foreground hover:border-input hover:bg-muted/60 aria-expanded:bg-muted aria-expanded:text-foreground active:shadow-field",
|
|
1881
|
+
secondary: "surface-control border-border bg-secondary text-secondary-foreground hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground active:shadow-field",
|
|
1882
|
+
ghost: "text-muted-foreground hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
1870
1883
|
destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
|
|
1871
1884
|
link: "text-primary underline-offset-4 hover:underline"
|
|
1872
1885
|
},
|
|
@@ -1907,34 +1920,6 @@ function Button({
|
|
|
1907
1920
|
);
|
|
1908
1921
|
}
|
|
1909
1922
|
|
|
1910
|
-
// ../../apps/web/src/hooks/use-is-resizing.ts
|
|
1911
|
-
import { useEffect as useEffect2, useState } from "react";
|
|
1912
|
-
var SETTLE_MS = 120;
|
|
1913
|
-
function useIsResizing(target) {
|
|
1914
|
-
const [isResizing, setIsResizing] = useState(false);
|
|
1915
|
-
useEffect2(() => {
|
|
1916
|
-
const node = target.current;
|
|
1917
|
-
if (!node || typeof ResizeObserver === "undefined") return;
|
|
1918
|
-
let settle = 0;
|
|
1919
|
-
let isOpeningReport = true;
|
|
1920
|
-
const observer = new ResizeObserver(() => {
|
|
1921
|
-
if (isOpeningReport) {
|
|
1922
|
-
isOpeningReport = false;
|
|
1923
|
-
return;
|
|
1924
|
-
}
|
|
1925
|
-
setIsResizing(true);
|
|
1926
|
-
window.clearTimeout(settle);
|
|
1927
|
-
settle = window.setTimeout(() => setIsResizing(false), SETTLE_MS);
|
|
1928
|
-
});
|
|
1929
|
-
observer.observe(node);
|
|
1930
|
-
return () => {
|
|
1931
|
-
window.clearTimeout(settle);
|
|
1932
|
-
observer.disconnect();
|
|
1933
|
-
};
|
|
1934
|
-
}, [target]);
|
|
1935
|
-
return isResizing;
|
|
1936
|
-
}
|
|
1937
|
-
|
|
1938
1923
|
// ../../apps/web/src/components/ui/message-scroller.tsx
|
|
1939
1924
|
import { Fragment as Fragment25, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1940
1925
|
function MessageScrollerProvider({
|
|
@@ -1969,9 +1954,12 @@ function usePinnedToEnd(viewport) {
|
|
|
1969
1954
|
const remember = () => {
|
|
1970
1955
|
wasAtEnd = node.scrollHeight - node.scrollTop - node.clientHeight <= AT_END_PX;
|
|
1971
1956
|
};
|
|
1957
|
+
let height = node.clientHeight;
|
|
1972
1958
|
const observer = new ResizeObserver(() => {
|
|
1973
1959
|
const drift = node.scrollHeight - node.scrollTop - node.clientHeight;
|
|
1974
|
-
|
|
1960
|
+
const shrank = node.clientHeight < height;
|
|
1961
|
+
height = node.clientHeight;
|
|
1962
|
+
if (wasAtEnd && shrank && drift > DRIFT_PX) {
|
|
1975
1963
|
node.scrollTo({
|
|
1976
1964
|
top: node.scrollHeight - node.clientHeight,
|
|
1977
1965
|
behavior: "instant"
|
|
@@ -1992,11 +1980,11 @@ var MAX_STEP_MS = 64;
|
|
|
1992
1980
|
function prefersReducedMotion() {
|
|
1993
1981
|
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1994
1982
|
}
|
|
1995
|
-
function useGlidingScroll(viewport,
|
|
1996
|
-
const
|
|
1983
|
+
function useGlidingScroll(viewport, hasLanded) {
|
|
1984
|
+
const landed = React3.useRef(hasLanded);
|
|
1997
1985
|
React3.useLayoutEffect(() => {
|
|
1998
|
-
|
|
1999
|
-
}, [
|
|
1986
|
+
landed.current = hasLanded;
|
|
1987
|
+
}, [hasLanded]);
|
|
2000
1988
|
React3.useEffect(() => {
|
|
2001
1989
|
const node = viewport.current;
|
|
2002
1990
|
if (!node) return;
|
|
@@ -2004,6 +1992,7 @@ function useGlidingScroll(viewport, isSettled) {
|
|
|
2004
1992
|
let target = null;
|
|
2005
1993
|
let frame = 0;
|
|
2006
1994
|
let last = 0;
|
|
1995
|
+
let box = { width: node.clientWidth, height: node.clientHeight };
|
|
2007
1996
|
const stop = () => {
|
|
2008
1997
|
if (frame !== 0) cancelAnimationFrame(frame);
|
|
2009
1998
|
frame = 0;
|
|
@@ -2012,11 +2001,12 @@ function useGlidingScroll(viewport, isSettled) {
|
|
|
2012
2001
|
const step = (now) => {
|
|
2013
2002
|
frame = 0;
|
|
2014
2003
|
if (target === null) return;
|
|
2015
|
-
const elapsed = Math.min(now - last, MAX_STEP_MS);
|
|
2004
|
+
const elapsed = Math.max(0, Math.min(now - last, MAX_STEP_MS));
|
|
2016
2005
|
last = now;
|
|
2017
|
-
const
|
|
2006
|
+
const goal = Math.min(target, node.scrollHeight - node.clientHeight);
|
|
2007
|
+
const left = goal - node.scrollTop;
|
|
2018
2008
|
if (Math.abs(left) < 0.5) {
|
|
2019
|
-
node.scrollTop =
|
|
2009
|
+
node.scrollTop = goal;
|
|
2020
2010
|
target = null;
|
|
2021
2011
|
return;
|
|
2022
2012
|
}
|
|
@@ -2025,7 +2015,10 @@ function useGlidingScroll(viewport, isSettled) {
|
|
|
2025
2015
|
};
|
|
2026
2016
|
const glide = (options, y) => {
|
|
2027
2017
|
const asked = typeof options === "number" ? { left: options, top: y } : options;
|
|
2028
|
-
const
|
|
2018
|
+
const size = { width: node.clientWidth, height: node.clientHeight };
|
|
2019
|
+
const shrank = size.width !== box.width || size.height < box.height;
|
|
2020
|
+
box = size;
|
|
2021
|
+
const glides = asked !== void 0 && typeof asked.top === "number" && asked.behavior !== "instant" && landed.current && !shrank && !prefersReducedMotion();
|
|
2029
2022
|
if (!glides) {
|
|
2030
2023
|
stop();
|
|
2031
2024
|
scrollNatively.call(node, asked);
|
|
@@ -2070,10 +2063,8 @@ function MessageScrollerViewport({
|
|
|
2070
2063
|
}) {
|
|
2071
2064
|
const viewport = React3.useRef(null);
|
|
2072
2065
|
const hasLanded = useHasLanded();
|
|
2073
|
-
const isResizing = useIsResizing(viewport);
|
|
2074
|
-
const isSettled = hasLanded && !isResizing;
|
|
2075
2066
|
usePinnedToEnd(viewport);
|
|
2076
|
-
useGlidingScroll(viewport,
|
|
2067
|
+
useGlidingScroll(viewport, hasLanded);
|
|
2077
2068
|
const holdViewport = React3.useCallback(
|
|
2078
2069
|
(node) => {
|
|
2079
2070
|
viewport.current = node;
|
|
@@ -2087,7 +2078,6 @@ function MessageScrollerViewport({
|
|
|
2087
2078
|
{
|
|
2088
2079
|
ref: holdViewport,
|
|
2089
2080
|
"data-slot": "message-scroller-viewport",
|
|
2090
|
-
"data-settled": isSettled ? "" : void 0,
|
|
2091
2081
|
className: cn(
|
|
2092
2082
|
"size-full min-h-0 min-w-0 overflow-y-auto overscroll-contain contain-content [scrollbar-gutter:stable] [scrollbar-width:thin]",
|
|
2093
2083
|
// The fade says "there is more below", so it only belongs to a
|
|
@@ -2266,9 +2256,9 @@ var SETTLE_BODY = cn(
|
|
|
2266
2256
|
|
|
2267
2257
|
// ../../apps/web/src/components/support-widget/widget-composer.tsx
|
|
2268
2258
|
import {
|
|
2269
|
-
useEffect as
|
|
2270
|
-
useRef as
|
|
2271
|
-
useState as
|
|
2259
|
+
useEffect as useEffect5,
|
|
2260
|
+
useRef as useRef8,
|
|
2261
|
+
useState as useState4
|
|
2272
2262
|
} from "react";
|
|
2273
2263
|
|
|
2274
2264
|
// src/next-image-shim.tsx
|
|
@@ -2296,7 +2286,7 @@ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
|
2296
2286
|
var KIND_ICONS = {
|
|
2297
2287
|
image: ImageSquare,
|
|
2298
2288
|
video: Play,
|
|
2299
|
-
file:
|
|
2289
|
+
file: File2
|
|
2300
2290
|
};
|
|
2301
2291
|
function AttachmentDraftChip({
|
|
2302
2292
|
draft,
|
|
@@ -2369,7 +2359,7 @@ function AttachmentDraftChip({
|
|
|
2369
2359
|
}
|
|
2370
2360
|
|
|
2371
2361
|
// ../../apps/web/src/components/attachments/use-attachment-drafts.ts
|
|
2372
|
-
import { useEffect as
|
|
2362
|
+
import { useEffect as useEffect3, useRef as useRef4, useState as useState2 } from "react";
|
|
2373
2363
|
var MAX_BYTES = 25 * 1024 * 1024;
|
|
2374
2364
|
var UNSAFE_TYPES = [
|
|
2375
2365
|
"text/html",
|
|
@@ -2410,12 +2400,12 @@ function useAttachmentDrafts({
|
|
|
2410
2400
|
accept,
|
|
2411
2401
|
max
|
|
2412
2402
|
} = {}) {
|
|
2413
|
-
const [drafts, setDrafts] =
|
|
2403
|
+
const [drafts, setDrafts] = useState2([]);
|
|
2414
2404
|
const draftsRef = useRef4(drafts);
|
|
2415
|
-
|
|
2405
|
+
useEffect3(() => {
|
|
2416
2406
|
draftsRef.current = drafts;
|
|
2417
2407
|
}, [drafts]);
|
|
2418
|
-
|
|
2408
|
+
useEffect3(() => () => draftsRef.current.forEach(release), []);
|
|
2419
2409
|
function add(files) {
|
|
2420
2410
|
const picked = Array.from(files).map((file, index) => {
|
|
2421
2411
|
const isTooBig = file.size > MAX_BYTES;
|
|
@@ -2460,12 +2450,12 @@ function useAttachmentDrafts({
|
|
|
2460
2450
|
}
|
|
2461
2451
|
|
|
2462
2452
|
// ../../apps/web/src/components/attachments/use-attachment-target.ts
|
|
2463
|
-
import { useRef as useRef5, useState as
|
|
2453
|
+
import { useRef as useRef5, useState as useState3 } from "react";
|
|
2464
2454
|
function useAttachmentTarget({
|
|
2465
2455
|
onFiles,
|
|
2466
2456
|
disabled = false
|
|
2467
2457
|
}) {
|
|
2468
|
-
const [isDropTarget, setIsDropTarget] =
|
|
2458
|
+
const [isDropTarget, setIsDropTarget] = useState3(false);
|
|
2469
2459
|
const depth = useRef5(0);
|
|
2470
2460
|
function handleDragEnter(event) {
|
|
2471
2461
|
if (disabled || !event.dataTransfer.types.includes("Files")) return;
|
|
@@ -2516,7 +2506,7 @@ var widgetButtonVariants = cva(
|
|
|
2516
2506
|
variant: {
|
|
2517
2507
|
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
2518
2508
|
outline: "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
2519
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
2509
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary,oklch(0.97_0_0)),var(--foreground,oklch(0.145_0_0))_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
2520
2510
|
ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
|
|
2521
2511
|
destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
|
|
2522
2512
|
link: "text-primary underline-offset-4 hover:underline"
|
|
@@ -2561,12 +2551,10 @@ function WidgetButton({
|
|
|
2561
2551
|
);
|
|
2562
2552
|
}
|
|
2563
2553
|
|
|
2564
|
-
// ../../apps/web/src/components/
|
|
2565
|
-
var
|
|
2554
|
+
// ../../apps/web/src/components/support-widget/widget-field.ts
|
|
2555
|
+
var WIDGET_TEXT_FIELD_SHELL = [
|
|
2566
2556
|
"rounded-lg border border-input bg-transparent text-sm max-sm:text-base transition-[color,box-shadow] outline-none dark:bg-input/30",
|
|
2567
2557
|
"placeholder:text-muted-foreground",
|
|
2568
|
-
// Focus recolours the hairline rather than adding a ring on top of it, so
|
|
2569
|
-
// the outline stays exactly 1px and nothing swells on click.
|
|
2570
2558
|
"focus-within:border-ring",
|
|
2571
2559
|
"aria-invalid:border-destructive",
|
|
2572
2560
|
"disabled:pointer-events-none disabled:opacity-50"
|
|
@@ -2591,12 +2579,12 @@ function Textarea({ className, ...props }) {
|
|
|
2591
2579
|
}
|
|
2592
2580
|
|
|
2593
2581
|
// ../../apps/web/src/hooks/use-typing-signal.ts
|
|
2594
|
-
import { useCallback as useCallback5, useEffect as
|
|
2582
|
+
import { useCallback as useCallback5, useEffect as useEffect4, useRef as useRef6 } from "react";
|
|
2595
2583
|
var REFRESH_MS = 2500;
|
|
2596
2584
|
var IDLE_MS = 8e3;
|
|
2597
2585
|
function useTypingSignal(onChange) {
|
|
2598
2586
|
const onChangeRef = useRef6(onChange);
|
|
2599
|
-
|
|
2587
|
+
useEffect4(() => {
|
|
2600
2588
|
onChangeRef.current = onChange;
|
|
2601
2589
|
}, [onChange]);
|
|
2602
2590
|
const isTypingRef = useRef6(false);
|
|
@@ -2630,10 +2618,33 @@ function useTypingSignal(onChange) {
|
|
|
2630
2618
|
send(true);
|
|
2631
2619
|
}
|
|
2632
2620
|
}, [send, stop]);
|
|
2633
|
-
|
|
2621
|
+
useEffect4(() => () => stop(), [stop]);
|
|
2634
2622
|
return { ping, stop, settle };
|
|
2635
2623
|
}
|
|
2636
2624
|
|
|
2625
|
+
// ../../apps/web/src/components/support-widget/use-eased-height.ts
|
|
2626
|
+
import { useLayoutEffect as useLayoutEffect4, useRef as useRef7 } from "react";
|
|
2627
|
+
function useEasedHeight(field) {
|
|
2628
|
+
const box = useRef7(null);
|
|
2629
|
+
useLayoutEffect4(() => {
|
|
2630
|
+
const outer = box.current;
|
|
2631
|
+
const inner = field.current;
|
|
2632
|
+
if (!outer || !inner) return;
|
|
2633
|
+
const follow = () => {
|
|
2634
|
+
outer.style.height = `${inner.offsetHeight}px`;
|
|
2635
|
+
};
|
|
2636
|
+
follow();
|
|
2637
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
2638
|
+
const observer = new ResizeObserver(follow);
|
|
2639
|
+
observer.observe(inner);
|
|
2640
|
+
return () => {
|
|
2641
|
+
observer.disconnect();
|
|
2642
|
+
outer.style.height = "";
|
|
2643
|
+
};
|
|
2644
|
+
}, [field]);
|
|
2645
|
+
return box;
|
|
2646
|
+
}
|
|
2647
|
+
|
|
2637
2648
|
// ../../apps/web/src/components/brand-art.ts
|
|
2638
2649
|
var BRAND_INK = "#191919";
|
|
2639
2650
|
var LOGO = {
|
|
@@ -2661,7 +2672,7 @@ var LOGO_MASK_URL = `url("data:image/svg+xml,${encodeURIComponent(
|
|
|
2661
2672
|
)}")`;
|
|
2662
2673
|
|
|
2663
2674
|
// ../../apps/web/src/components/brand.tsx
|
|
2664
|
-
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2675
|
+
import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2665
2676
|
var INVERT_IN_DARK = "dark:invert";
|
|
2666
2677
|
function Wordmark({
|
|
2667
2678
|
width = 132,
|
|
@@ -2714,7 +2725,11 @@ function ShimmerLogo({
|
|
|
2714
2725
|
WebkitMaskSize: "contain",
|
|
2715
2726
|
WebkitMaskRepeat: "no-repeat",
|
|
2716
2727
|
WebkitMaskPosition: "center",
|
|
2717
|
-
backgroundImage:
|
|
2728
|
+
backgroundImage: (
|
|
2729
|
+
// With the widget's own light values behind the host's, since this
|
|
2730
|
+
// mark also draws on pages that define neither.
|
|
2731
|
+
"linear-gradient(115deg, var(--muted, oklch(0.955 0 0)) 34%, var(--muted-foreground, oklch(0.556 0 0)) 50%, var(--muted, oklch(0.955 0 0)) 66%)"
|
|
2732
|
+
),
|
|
2718
2733
|
backgroundSize: "300% 100%"
|
|
2719
2734
|
},
|
|
2720
2735
|
className: cn(
|
|
@@ -2726,10 +2741,10 @@ function ShimmerLogo({
|
|
|
2726
2741
|
}
|
|
2727
2742
|
|
|
2728
2743
|
// ../../apps/web/src/components/support-widget/widget-badge.tsx
|
|
2729
|
-
import { jsx as jsx12, jsxs as
|
|
2744
|
+
import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2730
2745
|
var MEDIAN_URL = "https://median.sh";
|
|
2731
2746
|
function PoweredByMedian({ className }) {
|
|
2732
|
-
return /* @__PURE__ */
|
|
2747
|
+
return /* @__PURE__ */ jsxs5(
|
|
2733
2748
|
"a",
|
|
2734
2749
|
{
|
|
2735
2750
|
href: MEDIAN_URL,
|
|
@@ -2754,12 +2769,13 @@ function PoweredByMedian({ className }) {
|
|
|
2754
2769
|
}
|
|
2755
2770
|
|
|
2756
2771
|
// ../../apps/web/src/components/support-widget/widget-composer.tsx
|
|
2757
|
-
import { Fragment as Fragment26, jsx as jsx13, jsxs as
|
|
2772
|
+
import { Fragment as Fragment26, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2758
2773
|
var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2759
2774
|
var SWAP = "transition-[opacity,translate] duration-300 ease-out motion-reduce:transition-none";
|
|
2760
2775
|
var RISE = "transition-transform duration-450 ease-spring motion-reduce:transition-none";
|
|
2761
2776
|
var SINK = "transition-transform duration-250 ease-in motion-reduce:transition-none";
|
|
2762
2777
|
var ROLL = "transition-transform duration-350 ease-out-quint motion-reduce:transition-none";
|
|
2778
|
+
var GROW = "transition-[height] duration-200 ease-out-quint motion-reduce:transition-none";
|
|
2763
2779
|
var SAVED_MS = 1200;
|
|
2764
2780
|
function WidgetComposer({
|
|
2765
2781
|
onSend,
|
|
@@ -2773,11 +2789,12 @@ function WidgetComposer({
|
|
|
2773
2789
|
compact = false
|
|
2774
2790
|
}) {
|
|
2775
2791
|
const isStacked = variant === "stacked";
|
|
2776
|
-
const [draft, setDraft] =
|
|
2777
|
-
const [email, setEmail] =
|
|
2778
|
-
const [answer, setAnswer] =
|
|
2779
|
-
const fileInputRef =
|
|
2780
|
-
const draftRef =
|
|
2792
|
+
const [draft, setDraft] = useState4("");
|
|
2793
|
+
const [email, setEmail] = useState4("");
|
|
2794
|
+
const [answer, setAnswer] = useState4("none");
|
|
2795
|
+
const fileInputRef = useRef8(null);
|
|
2796
|
+
const draftRef = useRef8(null);
|
|
2797
|
+
const draftBoxRef = useEasedHeight(draftRef);
|
|
2781
2798
|
const attachments = useAttachmentDrafts();
|
|
2782
2799
|
const target = useAttachmentTarget({ onFiles: attachments.add });
|
|
2783
2800
|
const typing = useTypingSignal(onTypingChange);
|
|
@@ -2793,12 +2810,12 @@ function WidgetComposer({
|
|
|
2793
2810
|
setAnswer("saved");
|
|
2794
2811
|
onSubmitEmail(email.trim());
|
|
2795
2812
|
}
|
|
2796
|
-
|
|
2813
|
+
useEffect5(() => {
|
|
2797
2814
|
if (answer !== "saved") return;
|
|
2798
2815
|
const timer = setTimeout(() => setAnswer("settled"), SAVED_MS);
|
|
2799
2816
|
return () => clearTimeout(timer);
|
|
2800
2817
|
}, [answer]);
|
|
2801
|
-
|
|
2818
|
+
useEffect5(() => {
|
|
2802
2819
|
if (answer !== "saved" || askForEmail) return;
|
|
2803
2820
|
draftRef.current?.focus({ preventScroll: true });
|
|
2804
2821
|
}, [answer, askForEmail]);
|
|
@@ -2848,24 +2865,42 @@ function WidgetComposer({
|
|
|
2848
2865
|
children: /* @__PURE__ */ jsx13(Plus, { className: isStacked ? "size-5" : void 0 })
|
|
2849
2866
|
}
|
|
2850
2867
|
);
|
|
2851
|
-
const draftBox =
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2868
|
+
const draftBox = (
|
|
2869
|
+
// The field sizes itself to its words and sits at the foot of the box,
|
|
2870
|
+
// so a line that wraps stays where it was typed and the box's top edge
|
|
2871
|
+
// rises to take the first line in: the composer grows upward, and the
|
|
2872
|
+
// words hold still under the caret. The box follows the field on a
|
|
2873
|
+
// curve and clips whatever it is behind by.
|
|
2874
|
+
/* @__PURE__ */ jsx13(
|
|
2875
|
+
"div",
|
|
2876
|
+
{
|
|
2877
|
+
ref: draftBoxRef,
|
|
2878
|
+
className: cn(
|
|
2879
|
+
"flex flex-col justify-end overflow-clip",
|
|
2880
|
+
isStacked ? "w-full" : "min-w-0 flex-1",
|
|
2881
|
+
draft.length > 0 && GROW
|
|
2882
|
+
),
|
|
2883
|
+
children: /* @__PURE__ */ jsx13(
|
|
2884
|
+
Textarea,
|
|
2885
|
+
{
|
|
2886
|
+
ref: draftRef,
|
|
2887
|
+
rows: 1,
|
|
2888
|
+
value: draft,
|
|
2889
|
+
onChange: (event) => {
|
|
2890
|
+
setDraft(event.target.value);
|
|
2891
|
+
typing.ping();
|
|
2892
|
+
},
|
|
2893
|
+
onKeyDown: handleKeyDown,
|
|
2894
|
+
placeholder: target.isDropTarget ? "Drop to attach" : placeholder,
|
|
2895
|
+
"aria-label": "Message",
|
|
2896
|
+
className: cn(
|
|
2897
|
+
"max-h-40 shrink-0 max-sm:text-[16px]",
|
|
2898
|
+
isStacked ? "min-h-9 px-2 pt-1.5 pb-1 text-sm" : "min-h-10 px-2 py-2 text-base"
|
|
2899
|
+
)
|
|
2900
|
+
}
|
|
2901
|
+
)
|
|
2902
|
+
}
|
|
2903
|
+
)
|
|
2869
2904
|
);
|
|
2870
2905
|
const sendButton = /* @__PURE__ */ jsx13(
|
|
2871
2906
|
WidgetButton,
|
|
@@ -2925,7 +2960,7 @@ function WidgetComposer({
|
|
|
2925
2960
|
// anyway. Paste rides on the same element, so it is caught wherever the
|
|
2926
2961
|
// caret happens to be inside the composer. None of that while the email
|
|
2927
2962
|
// is asked for: there is no message yet to attach anything to.
|
|
2928
|
-
/* @__PURE__ */
|
|
2963
|
+
/* @__PURE__ */ jsxs6(
|
|
2929
2964
|
"div",
|
|
2930
2965
|
{
|
|
2931
2966
|
className: cn(
|
|
@@ -2941,7 +2976,7 @@ function WidgetComposer({
|
|
|
2941
2976
|
onRemove: () => attachments.remove(item.id)
|
|
2942
2977
|
}
|
|
2943
2978
|
) }, item.id)) }),
|
|
2944
|
-
/* @__PURE__ */
|
|
2979
|
+
/* @__PURE__ */ jsxs6("div", { className: "relative", children: [
|
|
2945
2980
|
/* @__PURE__ */ jsx13(
|
|
2946
2981
|
"div",
|
|
2947
2982
|
{
|
|
@@ -2958,8 +2993,8 @@ function WidgetComposer({
|
|
|
2958
2993
|
showTab ? RISE : SINK,
|
|
2959
2994
|
!showTab && "translate-y-full"
|
|
2960
2995
|
),
|
|
2961
|
-
children: /* @__PURE__ */
|
|
2962
|
-
/* @__PURE__ */
|
|
2996
|
+
children: /* @__PURE__ */ jsxs6("span", { className: "grid overflow-hidden", children: [
|
|
2997
|
+
/* @__PURE__ */ jsxs6(
|
|
2963
2998
|
"span",
|
|
2964
2999
|
{
|
|
2965
3000
|
"aria-hidden": isSaved,
|
|
@@ -2974,7 +3009,7 @@ function WidgetComposer({
|
|
|
2974
3009
|
]
|
|
2975
3010
|
}
|
|
2976
3011
|
),
|
|
2977
|
-
/* @__PURE__ */
|
|
3012
|
+
/* @__PURE__ */ jsxs6(
|
|
2978
3013
|
"span",
|
|
2979
3014
|
{
|
|
2980
3015
|
"aria-hidden": !isSaved,
|
|
@@ -2994,11 +3029,11 @@ function WidgetComposer({
|
|
|
2994
3029
|
)
|
|
2995
3030
|
}
|
|
2996
3031
|
),
|
|
2997
|
-
/* @__PURE__ */
|
|
3032
|
+
/* @__PURE__ */ jsxs6(
|
|
2998
3033
|
"div",
|
|
2999
3034
|
{
|
|
3000
3035
|
className: cn(
|
|
3001
|
-
|
|
3036
|
+
WIDGET_TEXT_FIELD_SHELL,
|
|
3002
3037
|
"relative z-10 grid bg-card p-2 transition-colors dark:bg-card",
|
|
3003
3038
|
// Half the pill's one line height, so it is a full pill at one
|
|
3004
3039
|
// line and keeps those corners as it grows. The box keeps a
|
|
@@ -3020,17 +3055,17 @@ function WidgetComposer({
|
|
|
3020
3055
|
SWAP,
|
|
3021
3056
|
isAsking && "-translate-y-1 opacity-0 pointer-events-none"
|
|
3022
3057
|
),
|
|
3023
|
-
children: isStacked ? /* @__PURE__ */
|
|
3058
|
+
children: isStacked ? /* @__PURE__ */ jsxs6(Fragment26, { children: [
|
|
3024
3059
|
draftBox,
|
|
3025
|
-
/* @__PURE__ */
|
|
3060
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5", children: [
|
|
3026
3061
|
fileInput,
|
|
3027
3062
|
addButton,
|
|
3028
|
-
/* @__PURE__ */
|
|
3063
|
+
/* @__PURE__ */ jsxs6("div", { className: "ml-auto flex items-center gap-2", children: [
|
|
3029
3064
|
badge,
|
|
3030
3065
|
sendButton
|
|
3031
3066
|
] })
|
|
3032
3067
|
] })
|
|
3033
|
-
] }) : /* @__PURE__ */
|
|
3068
|
+
] }) : /* @__PURE__ */ jsxs6(Fragment26, { children: [
|
|
3034
3069
|
fileInput,
|
|
3035
3070
|
addButton,
|
|
3036
3071
|
draftBox,
|
|
@@ -3049,13 +3084,13 @@ function WidgetComposer({
|
|
|
3049
3084
|
SWAP,
|
|
3050
3085
|
!isAsking && "pointer-events-none translate-y-1 opacity-0"
|
|
3051
3086
|
),
|
|
3052
|
-
children: isStacked ? /* @__PURE__ */
|
|
3087
|
+
children: isStacked ? /* @__PURE__ */ jsxs6(Fragment26, { children: [
|
|
3053
3088
|
emailBox,
|
|
3054
|
-
/* @__PURE__ */
|
|
3089
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-end gap-2", children: [
|
|
3055
3090
|
badge,
|
|
3056
3091
|
emailButton
|
|
3057
3092
|
] })
|
|
3058
|
-
] }) : /* @__PURE__ */
|
|
3093
|
+
] }) : /* @__PURE__ */ jsxs6(Fragment26, { children: [
|
|
3059
3094
|
emailBox,
|
|
3060
3095
|
emailButton
|
|
3061
3096
|
] })
|
|
@@ -3072,13 +3107,17 @@ function WidgetComposer({
|
|
|
3072
3107
|
);
|
|
3073
3108
|
}
|
|
3074
3109
|
|
|
3110
|
+
// ../../apps/web/src/components/support-widget/widget-corner.ts
|
|
3111
|
+
var WIDGET_RADIUS = "0.875rem";
|
|
3112
|
+
var WIDGET_CORNER = "rounded-[0.875rem]";
|
|
3113
|
+
|
|
3075
3114
|
// ../../apps/web/src/components/support-widget/widget-destination.tsx
|
|
3076
|
-
import { jsx as jsx14, jsxs as
|
|
3115
|
+
import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3077
3116
|
function WidgetDestination({
|
|
3078
3117
|
destination,
|
|
3079
3118
|
onFollow
|
|
3080
3119
|
}) {
|
|
3081
|
-
return /* @__PURE__ */
|
|
3120
|
+
return /* @__PURE__ */ jsxs7(
|
|
3082
3121
|
WidgetButton,
|
|
3083
3122
|
{
|
|
3084
3123
|
type: "button",
|
|
@@ -3100,10 +3139,24 @@ function WidgetDestination({
|
|
|
3100
3139
|
}
|
|
3101
3140
|
|
|
3102
3141
|
// ../../apps/web/src/components/avatar.tsx
|
|
3103
|
-
import { useState as
|
|
3142
|
+
import { useState as useState5 } from "react";
|
|
3104
3143
|
|
|
3105
3144
|
// ../../apps/web/src/components/initial-badge.tsx
|
|
3106
3145
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
3146
|
+
var TONES = [
|
|
3147
|
+
"bg-[var(--avatar-blue,#e0edfa)] text-[var(--avatar-blue-foreground,#37628c)]",
|
|
3148
|
+
"bg-[var(--avatar-violet,#eae4f7)] text-[var(--avatar-violet-foreground,#705894)]",
|
|
3149
|
+
"bg-[var(--avatar-amber,#f8ead6)] text-[var(--avatar-amber-foreground,#8b6434)]",
|
|
3150
|
+
"bg-[var(--avatar-teal,#dbefea)] text-[var(--avatar-teal-foreground,#3c766d)]",
|
|
3151
|
+
"bg-[var(--avatar-rose,#f5e2e8)] text-[var(--avatar-rose-foreground,#92586c)]"
|
|
3152
|
+
];
|
|
3153
|
+
function toneFor(value) {
|
|
3154
|
+
let hash = 0;
|
|
3155
|
+
for (const character of value.trim().toLowerCase()) {
|
|
3156
|
+
hash = hash * 31 + character.charCodeAt(0) >>> 0;
|
|
3157
|
+
}
|
|
3158
|
+
return TONES[hash % TONES.length];
|
|
3159
|
+
}
|
|
3107
3160
|
function InitialBadge({
|
|
3108
3161
|
value,
|
|
3109
3162
|
className
|
|
@@ -3114,7 +3167,8 @@ function InitialBadge({
|
|
|
3114
3167
|
"aria-hidden": true,
|
|
3115
3168
|
className: cn(
|
|
3116
3169
|
// Sized to match UserAvatar, since the two sit side by side in the nav.
|
|
3117
|
-
"grid size-4.5 shrink-0 place-items-center rounded border text-[10px] font-
|
|
3170
|
+
"surface-control grid size-4.5 shrink-0 place-items-center rounded border border-foreground/5 text-[10px] font-medium",
|
|
3171
|
+
toneFor(value),
|
|
3118
3172
|
className
|
|
3119
3173
|
),
|
|
3120
3174
|
children: value.trim().charAt(0).toUpperCase() || "?"
|
|
@@ -3131,7 +3185,7 @@ function Avatar({
|
|
|
3131
3185
|
unoptimized = false,
|
|
3132
3186
|
className
|
|
3133
3187
|
}) {
|
|
3134
|
-
const [failedSrc, setFailedSrc] =
|
|
3188
|
+
const [failedSrc, setFailedSrc] = useState5(null);
|
|
3135
3189
|
const hasFailed = failedSrc !== null && failedSrc === src;
|
|
3136
3190
|
const shape2 = "size-4.5 shrink-0 rounded-full";
|
|
3137
3191
|
if (!src || hasFailed) {
|
|
@@ -3139,7 +3193,7 @@ function Avatar({
|
|
|
3139
3193
|
InitialBadge,
|
|
3140
3194
|
{
|
|
3141
3195
|
value: name,
|
|
3142
|
-
className: cn(shape2, "border-none
|
|
3196
|
+
className: cn(shape2, "border-none text-[10px]", className)
|
|
3143
3197
|
}
|
|
3144
3198
|
);
|
|
3145
3199
|
}
|
|
@@ -3153,7 +3207,7 @@ function Avatar({
|
|
|
3153
3207
|
unoptimized,
|
|
3154
3208
|
onError: () => setFailedSrc(src),
|
|
3155
3209
|
draggable: false,
|
|
3156
|
-
className: cn(shape2, "bg-muted object-cover", className)
|
|
3210
|
+
className: cn(shape2, "bg-muted object-cover ring-1 ring-foreground/5", className)
|
|
3157
3211
|
}
|
|
3158
3212
|
);
|
|
3159
3213
|
}
|
|
@@ -3192,7 +3246,7 @@ function WidgetAvatar({
|
|
|
3192
3246
|
{
|
|
3193
3247
|
src: agent.avatarUrl,
|
|
3194
3248
|
name: agent.name,
|
|
3195
|
-
className: "size-full rounded-[inherit]"
|
|
3249
|
+
className: "size-full rounded-[inherit] bg-muted bg-none font-semibold text-muted-foreground shadow-none ring-0"
|
|
3196
3250
|
}
|
|
3197
3251
|
)
|
|
3198
3252
|
}
|
|
@@ -3215,7 +3269,7 @@ function WidgetAvatarStack({
|
|
|
3215
3269
|
}
|
|
3216
3270
|
|
|
3217
3271
|
// ../../apps/web/src/components/support-widget/widget-empty.tsx
|
|
3218
|
-
import { jsx as jsx18, jsxs as
|
|
3272
|
+
import { jsx as jsx18, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3219
3273
|
var STARTERS = [
|
|
3220
3274
|
{
|
|
3221
3275
|
label: "Ask a question",
|
|
@@ -3242,7 +3296,7 @@ function WidgetEmpty({
|
|
|
3242
3296
|
compact = false
|
|
3243
3297
|
}) {
|
|
3244
3298
|
const agent = team.find((member) => member.kind === "ai") ?? team[0];
|
|
3245
|
-
return /* @__PURE__ */
|
|
3299
|
+
return /* @__PURE__ */ jsxs8("div", { className: "flex min-h-0 flex-1 flex-col items-center justify-center gap-5 px-6 pb-2 text-center", children: [
|
|
3246
3300
|
agent && /* @__PURE__ */ jsx18(
|
|
3247
3301
|
WidgetAvatar,
|
|
3248
3302
|
{
|
|
@@ -3253,7 +3307,7 @@ function WidgetEmpty({
|
|
|
3253
3307
|
)
|
|
3254
3308
|
}
|
|
3255
3309
|
),
|
|
3256
|
-
/* @__PURE__ */
|
|
3310
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex max-w-72 animate-in flex-col gap-1 delay-150 duration-500 ease-out fade-in-0 slide-in-from-bottom-2 fill-mode-backwards motion-reduce:animate-none", children: [
|
|
3257
3311
|
agent && /* @__PURE__ */ jsx18(
|
|
3258
3312
|
"p",
|
|
3259
3313
|
{
|
|
@@ -3275,7 +3329,7 @@ function WidgetEmpty({
|
|
|
3275
3329
|
}
|
|
3276
3330
|
)
|
|
3277
3331
|
] }),
|
|
3278
|
-
onPick && /* @__PURE__ */ jsx18("div", { className: "flex w-full max-w-md flex-col gap-2 pt-1", children: STARTERS.map((starter, index) => /* @__PURE__ */
|
|
3332
|
+
onPick && /* @__PURE__ */ jsx18("div", { className: "flex w-full max-w-md flex-col gap-2 pt-1", children: STARTERS.map((starter, index) => /* @__PURE__ */ jsxs8(
|
|
3279
3333
|
WidgetButton,
|
|
3280
3334
|
{
|
|
3281
3335
|
type: "button",
|
|
@@ -3316,7 +3370,7 @@ function WidgetEmpty({
|
|
|
3316
3370
|
}
|
|
3317
3371
|
|
|
3318
3372
|
// ../../apps/web/src/components/support-widget/widget-header.tsx
|
|
3319
|
-
import { jsx as jsx19, jsxs as
|
|
3373
|
+
import { jsx as jsx19, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3320
3374
|
function WidgetHeader({
|
|
3321
3375
|
presence,
|
|
3322
3376
|
onClose,
|
|
@@ -3327,7 +3381,7 @@ function WidgetHeader({
|
|
|
3327
3381
|
compact = false,
|
|
3328
3382
|
className
|
|
3329
3383
|
}) {
|
|
3330
|
-
return /* @__PURE__ */
|
|
3384
|
+
return /* @__PURE__ */ jsxs9(
|
|
3331
3385
|
"header",
|
|
3332
3386
|
{
|
|
3333
3387
|
...grabHandlers,
|
|
@@ -3344,7 +3398,7 @@ function WidgetHeader({
|
|
|
3344
3398
|
]
|
|
3345
3399
|
),
|
|
3346
3400
|
children: [
|
|
3347
|
-
/* @__PURE__ */
|
|
3401
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex min-w-0 flex-1 flex-col pt-0.5", children: [
|
|
3348
3402
|
/* @__PURE__ */ jsx19(
|
|
3349
3403
|
"h2",
|
|
3350
3404
|
{
|
|
@@ -3366,7 +3420,7 @@ function WidgetHeader({
|
|
|
3366
3420
|
}
|
|
3367
3421
|
)
|
|
3368
3422
|
] }),
|
|
3369
|
-
/* @__PURE__ */
|
|
3423
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex shrink-0 items-center gap-3", children: [
|
|
3370
3424
|
/* @__PURE__ */ jsx19(
|
|
3371
3425
|
WidgetAvatarStack,
|
|
3372
3426
|
{
|
|
@@ -3374,7 +3428,7 @@ function WidgetHeader({
|
|
|
3374
3428
|
avatarClassName: compact ? "size-8" : void 0
|
|
3375
3429
|
}
|
|
3376
3430
|
),
|
|
3377
|
-
/* @__PURE__ */
|
|
3431
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-0.5", children: [
|
|
3378
3432
|
onToggleExpanded && /* @__PURE__ */ jsx19(
|
|
3379
3433
|
WidgetButton,
|
|
3380
3434
|
{
|
|
@@ -3412,16 +3466,16 @@ function WidgetLoading() {
|
|
|
3412
3466
|
}
|
|
3413
3467
|
|
|
3414
3468
|
// ../../apps/web/src/components/support-widget/widget-locked.tsx
|
|
3415
|
-
import { jsx as jsx21, jsxs as
|
|
3469
|
+
import { jsx as jsx21, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3416
3470
|
function WidgetLocked({
|
|
3417
3471
|
orgName,
|
|
3418
3472
|
onSignIn,
|
|
3419
3473
|
showBadge = true
|
|
3420
3474
|
}) {
|
|
3421
|
-
return /* @__PURE__ */
|
|
3422
|
-
/* @__PURE__ */
|
|
3475
|
+
return /* @__PURE__ */ jsxs10("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
3476
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex min-h-0 flex-1 flex-col items-center justify-center gap-5 px-8 text-center", children: [
|
|
3423
3477
|
/* @__PURE__ */ jsx21("span", { className: "grid size-16 animate-in place-items-center rounded-2xl bg-muted duration-500 ease-out fade-in-0 zoom-in-95 motion-reduce:animate-none", children: /* @__PURE__ */ jsx21(LockSimple, { className: "size-7 text-muted-foreground" }) }),
|
|
3424
|
-
/* @__PURE__ */
|
|
3478
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex max-w-72 animate-in flex-col gap-1 delay-150 duration-500 ease-out fade-in-0 slide-in-from-bottom-2 fill-mode-backwards motion-reduce:animate-none", children: [
|
|
3425
3479
|
/* @__PURE__ */ jsx21("p", { className: "text-xl font-semibold tracking-tight", children: "Sign in to chat" }),
|
|
3426
3480
|
/* @__PURE__ */ jsx21("p", { className: "text-base text-balance text-muted-foreground", children: orgName ? `Ask ${orgName} anything once you are signed in.` : "Sign in to contact our support team." })
|
|
3427
3481
|
] }),
|
|
@@ -3440,7 +3494,7 @@ function WidgetLocked({
|
|
|
3440
3494
|
}
|
|
3441
3495
|
|
|
3442
3496
|
// ../../apps/web/src/components/support-widget/widget-message.tsx
|
|
3443
|
-
import { useState as
|
|
3497
|
+
import { useState as useState8 } from "react";
|
|
3444
3498
|
|
|
3445
3499
|
// ../../apps/web/src/components/ui/badge.tsx
|
|
3446
3500
|
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
@@ -3449,10 +3503,10 @@ var badgeVariants = cva(
|
|
|
3449
3503
|
{
|
|
3450
3504
|
variants: {
|
|
3451
3505
|
variant: {
|
|
3452
|
-
default: "bg-secondary text-secondary-foreground",
|
|
3453
|
-
muted: "bg-muted text-muted-foreground",
|
|
3506
|
+
default: "bg-secondary text-secondary-foreground inset-ring-1 inset-ring-foreground/5",
|
|
3507
|
+
muted: "bg-muted/70 text-muted-foreground inset-ring-1 inset-ring-foreground/5",
|
|
3454
3508
|
outline: "border border-border text-muted-foreground",
|
|
3455
|
-
solid: "bg-primary text-primary-foreground"
|
|
3509
|
+
solid: "surface-primary bg-primary text-primary-foreground"
|
|
3456
3510
|
}
|
|
3457
3511
|
},
|
|
3458
3512
|
defaultVariants: {
|
|
@@ -3479,7 +3533,7 @@ function Badge({
|
|
|
3479
3533
|
}
|
|
3480
3534
|
|
|
3481
3535
|
// ../../apps/web/src/components/ui/morph-bubble.tsx
|
|
3482
|
-
import { useLayoutEffect as
|
|
3536
|
+
import { useLayoutEffect as useLayoutEffect5, useRef as useRef9 } from "react";
|
|
3483
3537
|
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
3484
3538
|
var MORPH_MS = 350;
|
|
3485
3539
|
var MORPH_EASING = "ease-in-out";
|
|
@@ -3507,11 +3561,11 @@ function MorphBubble({
|
|
|
3507
3561
|
contentClassName,
|
|
3508
3562
|
children
|
|
3509
3563
|
}) {
|
|
3510
|
-
const box =
|
|
3511
|
-
const content =
|
|
3512
|
-
const previous =
|
|
3513
|
-
const running =
|
|
3514
|
-
|
|
3564
|
+
const box = useRef9(null);
|
|
3565
|
+
const content = useRef9(null);
|
|
3566
|
+
const previous = useRef9(null);
|
|
3567
|
+
const running = useRef9([]);
|
|
3568
|
+
useLayoutEffect5(() => {
|
|
3515
3569
|
const outer = box.current;
|
|
3516
3570
|
const inner = content.current;
|
|
3517
3571
|
if (!outer || !inner) return;
|
|
@@ -3564,8 +3618,8 @@ function MorphBubble({
|
|
|
3564
3618
|
}
|
|
3565
3619
|
|
|
3566
3620
|
// ../../apps/web/src/components/support-widget/widget-attachments.tsx
|
|
3567
|
-
import { useState as
|
|
3568
|
-
import { Fragment as Fragment27, jsx as jsx24, jsxs as
|
|
3621
|
+
import { useState as useState6 } from "react";
|
|
3622
|
+
import { Fragment as Fragment27, jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3569
3623
|
var SURFACE = "rounded-xl border border-foreground/10 bg-card/70";
|
|
3570
3624
|
function OpenAttachment({
|
|
3571
3625
|
attachment,
|
|
@@ -3593,9 +3647,9 @@ function MediaTile({
|
|
|
3593
3647
|
attachment,
|
|
3594
3648
|
className
|
|
3595
3649
|
}) {
|
|
3596
|
-
const [hasFailed, setHasFailed] =
|
|
3650
|
+
const [hasFailed, setHasFailed] = useState6(false);
|
|
3597
3651
|
if (!attachment.previewUrl || hasFailed) {
|
|
3598
|
-
return /* @__PURE__ */
|
|
3652
|
+
return /* @__PURE__ */ jsxs11(
|
|
3599
3653
|
"div",
|
|
3600
3654
|
{
|
|
3601
3655
|
className: cn(
|
|
@@ -3610,7 +3664,7 @@ function MediaTile({
|
|
|
3610
3664
|
}
|
|
3611
3665
|
);
|
|
3612
3666
|
}
|
|
3613
|
-
return /* @__PURE__ */
|
|
3667
|
+
return /* @__PURE__ */ jsxs11("figure", { className: cn(SURFACE, "relative overflow-hidden", className), children: [
|
|
3614
3668
|
/* @__PURE__ */ jsx24(
|
|
3615
3669
|
"img",
|
|
3616
3670
|
{
|
|
@@ -3634,9 +3688,9 @@ function MediaTile({
|
|
|
3634
3688
|
] });
|
|
3635
3689
|
}
|
|
3636
3690
|
function FileRow({ attachment }) {
|
|
3637
|
-
return /* @__PURE__ */ jsx24(OpenAttachment, { attachment, children: /* @__PURE__ */
|
|
3638
|
-
/* @__PURE__ */ jsx24(
|
|
3639
|
-
/* @__PURE__ */
|
|
3691
|
+
return /* @__PURE__ */ jsx24(OpenAttachment, { attachment, children: /* @__PURE__ */ jsxs11("div", { className: cn(SURFACE, "flex items-center gap-2.5 px-2.5 py-2"), children: [
|
|
3692
|
+
/* @__PURE__ */ jsx24(File2, { className: "size-5 shrink-0 text-muted-foreground" }),
|
|
3693
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 flex-1 flex-col text-left", children: [
|
|
3640
3694
|
/* @__PURE__ */ jsx24("p", { className: "truncate text-sm font-medium", children: attachment.name }),
|
|
3641
3695
|
/* @__PURE__ */ jsx24("p", { className: "truncate text-sm text-muted-foreground", children: attachment.size })
|
|
3642
3696
|
] })
|
|
@@ -3647,7 +3701,7 @@ function WidgetAttachments({
|
|
|
3647
3701
|
}) {
|
|
3648
3702
|
const media = attachments.filter((one) => one.kind !== "file");
|
|
3649
3703
|
const files = attachments.filter((one) => one.kind === "file");
|
|
3650
|
-
return /* @__PURE__ */
|
|
3704
|
+
return /* @__PURE__ */ jsxs11("div", { className: "flex w-64 max-w-full flex-col gap-2", children: [
|
|
3651
3705
|
media.length > 0 && /* @__PURE__ */ jsx24("div", { className: cn("grid gap-2", media.length > 1 && "grid-cols-2"), children: media.map((attachment) => /* @__PURE__ */ jsx24(
|
|
3652
3706
|
OpenAttachment,
|
|
3653
3707
|
{
|
|
@@ -3685,7 +3739,7 @@ function WidgetBubble({
|
|
|
3685
3739
|
import { Suspense } from "react";
|
|
3686
3740
|
|
|
3687
3741
|
// ../../apps/web/src/components/ui/line-reveal.tsx
|
|
3688
|
-
import { useLayoutEffect as
|
|
3742
|
+
import { useLayoutEffect as useLayoutEffect6, useRef as useRef10, useState as useState7 } from "react";
|
|
3689
3743
|
|
|
3690
3744
|
// ../../apps/web/src/hooks/use-media-query.ts
|
|
3691
3745
|
import { useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
@@ -3712,7 +3766,7 @@ function durationMs(token, fallback, from = document.documentElement) {
|
|
|
3712
3766
|
}
|
|
3713
3767
|
|
|
3714
3768
|
// ../../apps/web/src/components/ui/line-reveal.tsx
|
|
3715
|
-
import { jsx as jsx26, jsxs as
|
|
3769
|
+
import { jsx as jsx26, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3716
3770
|
var LAST_BEAT = 11;
|
|
3717
3771
|
function lineSlices(root) {
|
|
3718
3772
|
const host = root.getBoundingClientRect();
|
|
@@ -3748,7 +3802,7 @@ function lineSlices(root) {
|
|
|
3748
3802
|
return [{ top: 0, height: host.height }];
|
|
3749
3803
|
}
|
|
3750
3804
|
const unique = [...new Set(tops.map((top) => Math.round(top)))].sort(
|
|
3751
|
-
(
|
|
3805
|
+
(a30, b2) => a30 - b2
|
|
3752
3806
|
);
|
|
3753
3807
|
return unique.map((top, index) => {
|
|
3754
3808
|
const next = unique[index + 1] ?? Math.ceil(host.height);
|
|
@@ -3798,10 +3852,10 @@ function LineReveal({
|
|
|
3798
3852
|
children,
|
|
3799
3853
|
className
|
|
3800
3854
|
}) {
|
|
3801
|
-
const sourceRef =
|
|
3802
|
-
const stageRef =
|
|
3855
|
+
const sourceRef = useRef10(null);
|
|
3856
|
+
const stageRef = useRef10(null);
|
|
3803
3857
|
const reduce = useMediaQuery("(prefers-reduced-motion: reduce)");
|
|
3804
|
-
const [play2, setPlay] =
|
|
3858
|
+
const [play2, setPlay] = useState7({
|
|
3805
3859
|
key: contentKey,
|
|
3806
3860
|
delay,
|
|
3807
3861
|
isPlaying: !reduce
|
|
@@ -3810,19 +3864,20 @@ function LineReveal({
|
|
|
3810
3864
|
setPlay({ key: contentKey, delay, isPlaying: !reduce });
|
|
3811
3865
|
}
|
|
3812
3866
|
const { key: playKey, delay: hold, isPlaying } = play2;
|
|
3813
|
-
|
|
3867
|
+
useLayoutEffect6(() => {
|
|
3814
3868
|
if (reduce || !isPlaying) return;
|
|
3815
3869
|
const source = sourceRef.current;
|
|
3816
3870
|
const stage = stageRef.current;
|
|
3817
3871
|
if (source === null || stage === null) return;
|
|
3872
|
+
const wait = typeof hold === "number" ? hold : durationMs(hold, 0, stage);
|
|
3818
3873
|
let painted = false;
|
|
3819
3874
|
let timer = 0;
|
|
3820
3875
|
const end = () => setPlay((now) => ({ ...now, isPlaying: false }));
|
|
3821
3876
|
const paint = () => {
|
|
3822
3877
|
if (painted) return;
|
|
3823
|
-
if (!paintSlices(source, stage,
|
|
3878
|
+
if (!paintSlices(source, stage, wait)) return;
|
|
3824
3879
|
painted = true;
|
|
3825
|
-
timer = window.setTimeout(end, playMs(stage,
|
|
3880
|
+
timer = window.setTimeout(end, playMs(stage, wait));
|
|
3826
3881
|
observer.disconnect();
|
|
3827
3882
|
};
|
|
3828
3883
|
const observer = new ResizeObserver(paint);
|
|
@@ -3839,7 +3894,7 @@ function LineReveal({
|
|
|
3839
3894
|
};
|
|
3840
3895
|
}, [playKey, hold, isPlaying, reduce]);
|
|
3841
3896
|
const showSlices = isPlaying && !reduce;
|
|
3842
|
-
return /* @__PURE__ */
|
|
3897
|
+
return /* @__PURE__ */ jsxs12("div", { className: cn("relative", className), children: [
|
|
3843
3898
|
/* @__PURE__ */ jsx26("div", { className: showSlices ? "pointer-events-none opacity-0" : void 0, children: /* @__PURE__ */ jsx26("div", { ref: sourceRef, children }) }),
|
|
3844
3899
|
showSlices && /* @__PURE__ */ jsx26(
|
|
3845
3900
|
"div",
|
|
@@ -3868,10 +3923,10 @@ function WidgetMessageBody({
|
|
|
3868
3923
|
}
|
|
3869
3924
|
|
|
3870
3925
|
// ../../apps/web/src/components/support-widget/widget-typing.tsx
|
|
3871
|
-
import { jsx as jsx28, jsxs as
|
|
3926
|
+
import { jsx as jsx28, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3872
3927
|
var DOTS = [0, 160, 320];
|
|
3873
3928
|
function WidgetTyping({ label }) {
|
|
3874
|
-
return /* @__PURE__ */
|
|
3929
|
+
return /* @__PURE__ */ jsxs13("span", { className: "flex items-center gap-1.5 py-2", children: [
|
|
3875
3930
|
/* @__PURE__ */ jsx28("span", { className: "sr-only", children: label }),
|
|
3876
3931
|
DOTS.map((delay) => /* @__PURE__ */ jsx28(
|
|
3877
3932
|
"span",
|
|
@@ -3886,16 +3941,17 @@ function WidgetTyping({ label }) {
|
|
|
3886
3941
|
}
|
|
3887
3942
|
|
|
3888
3943
|
// ../../apps/web/src/components/support-widget/widget-message.tsx
|
|
3889
|
-
import { Fragment as Fragment28, jsx as jsx29, jsxs as
|
|
3944
|
+
import { Fragment as Fragment28, jsx as jsx29, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3890
3945
|
var BUBBLE = "max-w-[min(80%,36rem)] rounded-2xl px-4 py-2.5 text-base";
|
|
3891
3946
|
var COMPACT_BUBBLE = "max-w-[min(80%,36rem)] rounded-2xl px-3.5 py-2 text-sm";
|
|
3892
|
-
var VISITOR_BUBBLE = "bg-[color-mix(in_oklch,var(--muted),var(--foreground)_12%)]";
|
|
3947
|
+
var VISITOR_BUBBLE = "bg-[color-mix(in_oklch,var(--muted,oklch(0.955_0_0)),var(--foreground,oklch(0.145_0_0))_12%)]";
|
|
3893
3948
|
var ARRIVES = "animate-in fade-in-0 slide-in-from-bottom-1 duration-300 ease-out-quint motion-reduce:animate-none";
|
|
3949
|
+
var SENT = "animate-in fade-in-0 slide-in-from-bottom-3 zoom-in-95 origin-bottom-right duration-400 ease-out-quint motion-reduce:animate-none";
|
|
3894
3950
|
var LADDER_DELAY_MS = Math.round(MORPH_MS * 0.7);
|
|
3895
3951
|
function WidgetDivider({ message }) {
|
|
3896
3952
|
const label = message.startsConversation ? "New conversation" : message.dayLabel;
|
|
3897
3953
|
if (!label) return null;
|
|
3898
|
-
return /* @__PURE__ */
|
|
3954
|
+
return /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-3 py-1", children: [
|
|
3899
3955
|
/* @__PURE__ */ jsx29("span", { className: "h-px flex-1 bg-border" }),
|
|
3900
3956
|
/* @__PURE__ */ jsx29("span", { className: "text-sm text-muted-foreground", children: label }),
|
|
3901
3957
|
/* @__PURE__ */ jsx29("span", { className: "h-px flex-1 bg-border" })
|
|
@@ -3908,7 +3964,7 @@ function WidgetMessage({
|
|
|
3908
3964
|
compact = false,
|
|
3909
3965
|
isLive = false
|
|
3910
3966
|
}) {
|
|
3911
|
-
return message.sender === "visitor" ? /* @__PURE__ */ jsx29(VisitorMessage, { message, compact }) : /* @__PURE__ */ jsx29(
|
|
3967
|
+
return message.sender === "visitor" ? /* @__PURE__ */ jsx29(VisitorMessage, { message, compact, isLive }) : /* @__PURE__ */ jsx29(
|
|
3912
3968
|
AgentMessage,
|
|
3913
3969
|
{
|
|
3914
3970
|
message,
|
|
@@ -3932,7 +3988,7 @@ function BubbleContent({
|
|
|
3932
3988
|
}
|
|
3933
3989
|
);
|
|
3934
3990
|
}
|
|
3935
|
-
return /* @__PURE__ */
|
|
3991
|
+
return /* @__PURE__ */ jsxs14(Fragment28, { children: [
|
|
3936
3992
|
hasAttachments && /* @__PURE__ */ jsx29(WidgetAttachments, { attachments: message.attachments ?? [] }),
|
|
3937
3993
|
message.body && /* @__PURE__ */ jsx29(
|
|
3938
3994
|
WidgetMessageBody,
|
|
@@ -3946,9 +4002,10 @@ function BubbleContent({
|
|
|
3946
4002
|
}
|
|
3947
4003
|
function VisitorMessage({
|
|
3948
4004
|
message,
|
|
3949
|
-
compact
|
|
4005
|
+
compact,
|
|
4006
|
+
isLive
|
|
3950
4007
|
}) {
|
|
3951
|
-
return /* @__PURE__ */ jsx29("div", { className: cn("flex justify-end", ARRIVES), children: /* @__PURE__ */ jsx29(
|
|
4008
|
+
return /* @__PURE__ */ jsx29("div", { className: cn("flex justify-end", isLive ? SENT : ARRIVES), children: /* @__PURE__ */ jsx29(
|
|
3952
4009
|
WidgetBubble,
|
|
3953
4010
|
{
|
|
3954
4011
|
morphKey: "settled",
|
|
@@ -3965,7 +4022,7 @@ function AgentMessage({
|
|
|
3965
4022
|
isLive
|
|
3966
4023
|
}) {
|
|
3967
4024
|
const { agent } = message;
|
|
3968
|
-
const [sawDots, setSawDots] =
|
|
4025
|
+
const [sawDots, setSawDots] = useState8(message.pending === true);
|
|
3969
4026
|
if (message.pending && !sawDots) setSawDots(true);
|
|
3970
4027
|
const arrival = isLive && !message.pending && message.body.length > 0 ? { key: message.id, delay: sawDots ? LADDER_DELAY_MS : 0 } : null;
|
|
3971
4028
|
const destination = message.navigateTo === void 0 ? null : {
|
|
@@ -3979,8 +4036,8 @@ function AgentMessage({
|
|
|
3979
4036
|
// below, which spread four small things across three rows and pushed every
|
|
3980
4037
|
// bubble in off the edge. All of it is one line now, and the bubble gets
|
|
3981
4038
|
// the full width back.
|
|
3982
|
-
/* @__PURE__ */
|
|
3983
|
-
group.isFirst && /* @__PURE__ */
|
|
4039
|
+
/* @__PURE__ */ jsxs14("div", { className: cn("flex flex-col items-start gap-1", ARRIVES), children: [
|
|
4040
|
+
group.isFirst && /* @__PURE__ */ jsxs14(
|
|
3984
4041
|
"div",
|
|
3985
4042
|
{
|
|
3986
4043
|
className: cn(
|
|
@@ -3988,7 +4045,7 @@ function AgentMessage({
|
|
|
3988
4045
|
compact ? "text-xs" : "text-sm"
|
|
3989
4046
|
),
|
|
3990
4047
|
children: [
|
|
3991
|
-
agent && /* @__PURE__ */
|
|
4048
|
+
agent && /* @__PURE__ */ jsxs14(Fragment28, { children: [
|
|
3992
4049
|
/* @__PURE__ */ jsx29(
|
|
3993
4050
|
WidgetAvatar,
|
|
3994
4051
|
{
|
|
@@ -3997,7 +4054,7 @@ function AgentMessage({
|
|
|
3997
4054
|
}
|
|
3998
4055
|
),
|
|
3999
4056
|
/* @__PURE__ */ jsx29("span", { className: "truncate font-medium", children: agent.name }),
|
|
4000
|
-
agent.kind === "ai" && /* @__PURE__ */ jsx29(Badge, { variant: "muted", className: "shrink-0 rounded-md px-1", children: "AI" })
|
|
4057
|
+
agent.kind === "ai" && /* @__PURE__ */ jsx29(Badge, { variant: "muted", className: "shrink-0 rounded-md bg-muted px-1 inset-ring-0", children: "AI" })
|
|
4001
4058
|
] }),
|
|
4002
4059
|
!message.pending && /* @__PURE__ */ jsx29("span", { className: "shrink-0 text-muted-foreground tabular-nums", children: message.time })
|
|
4003
4060
|
]
|
|
@@ -4035,21 +4092,21 @@ var TYPING_TTL_MS = 12e3;
|
|
|
4035
4092
|
var SNOOZE_MAX_MS = 365 * 24 * 60 * 6e4;
|
|
4036
4093
|
|
|
4037
4094
|
// ../../apps/web/src/components/support-widget/widget-rating.tsx
|
|
4038
|
-
import { useEffect as
|
|
4039
|
-
import { jsx as jsx30, jsxs as
|
|
4095
|
+
import { useEffect as useEffect6, useRef as useRef11, useState as useState9 } from "react";
|
|
4096
|
+
import { jsx as jsx30, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4040
4097
|
var STARS = Array.from({ length: RATING_MAX_STARS }, (_, index) => index + 1);
|
|
4041
4098
|
var THANKS_MS = 1400;
|
|
4042
4099
|
var STAR_STAGGER_MS = 40;
|
|
4043
4100
|
function WidgetRating({ rating }) {
|
|
4044
|
-
const [isOpen, setIsOpen] =
|
|
4045
|
-
const [picked, setPicked] =
|
|
4046
|
-
const [hovered, setHovered] =
|
|
4047
|
-
const [feedback, setFeedback] =
|
|
4048
|
-
const [isSending, setIsSending] =
|
|
4049
|
-
const [error, setError] =
|
|
4050
|
-
const [isDone, setIsDone] =
|
|
4051
|
-
const timers =
|
|
4052
|
-
|
|
4101
|
+
const [isOpen, setIsOpen] = useState9(false);
|
|
4102
|
+
const [picked, setPicked] = useState9(rating.stars);
|
|
4103
|
+
const [hovered, setHovered] = useState9(null);
|
|
4104
|
+
const [feedback, setFeedback] = useState9("");
|
|
4105
|
+
const [isSending, setIsSending] = useState9(false);
|
|
4106
|
+
const [error, setError] = useState9(null);
|
|
4107
|
+
const [isDone, setIsDone] = useState9(false);
|
|
4108
|
+
const timers = useRef11([]);
|
|
4109
|
+
useEffect6(() => {
|
|
4053
4110
|
const frame = requestAnimationFrame(() => setIsOpen(true));
|
|
4054
4111
|
const pending = timers.current;
|
|
4055
4112
|
return () => {
|
|
@@ -4090,9 +4147,9 @@ function WidgetRating({ rating }) {
|
|
|
4090
4147
|
setIsDone(true);
|
|
4091
4148
|
later(THANKS_MS, leave);
|
|
4092
4149
|
}
|
|
4093
|
-
return /* @__PURE__ */ jsx30(Collapse, { isOpen, className: "shrink-0", children: /* @__PURE__ */
|
|
4094
|
-
/* @__PURE__ */ jsx30(Collapse, { isOpen: !isDone, children: /* @__PURE__ */
|
|
4095
|
-
/* @__PURE__ */
|
|
4150
|
+
return /* @__PURE__ */ jsx30(Collapse, { isOpen, className: "shrink-0", children: /* @__PURE__ */ jsxs15("div", { className: "mx-4 mb-3 rounded-xl border bg-muted/40 px-4 dark:bg-muted/20", children: [
|
|
4151
|
+
/* @__PURE__ */ jsx30(Collapse, { isOpen: !isDone, children: /* @__PURE__ */ jsxs15("div", { className: "py-3", children: [
|
|
4152
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-start justify-between gap-2", children: [
|
|
4096
4153
|
/* @__PURE__ */ jsx30("p", { className: "text-base font-medium", children: picked === null ? "How did we do?" : "Anything we could improve?" }),
|
|
4097
4154
|
/* @__PURE__ */ jsx30(
|
|
4098
4155
|
WidgetButton,
|
|
@@ -4149,7 +4206,7 @@ function WidgetRating({ rating }) {
|
|
|
4149
4206
|
))
|
|
4150
4207
|
}
|
|
4151
4208
|
),
|
|
4152
|
-
/* @__PURE__ */ jsx30(Collapse, { isOpen: picked !== null, children: /* @__PURE__ */
|
|
4209
|
+
/* @__PURE__ */ jsx30(Collapse, { isOpen: picked !== null, children: /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-2 pt-2", children: [
|
|
4153
4210
|
/* @__PURE__ */ jsx30(
|
|
4154
4211
|
Textarea,
|
|
4155
4212
|
{
|
|
@@ -4161,7 +4218,7 @@ function WidgetRating({ rating }) {
|
|
|
4161
4218
|
maxLength: RATING_FEEDBACK_MAX_LENGTH,
|
|
4162
4219
|
disabled: isSending,
|
|
4163
4220
|
className: cn(
|
|
4164
|
-
|
|
4221
|
+
WIDGET_TEXT_FIELD_SHELL,
|
|
4165
4222
|
"max-h-28 min-h-20 bg-card px-3 py-2.5 text-base"
|
|
4166
4223
|
)
|
|
4167
4224
|
}
|
|
@@ -4184,16 +4241,16 @@ function WidgetRating({ rating }) {
|
|
|
4184
4241
|
}
|
|
4185
4242
|
|
|
4186
4243
|
// ../../apps/web/src/components/support-widget/widget-status.tsx
|
|
4187
|
-
import { jsx as jsx31, jsxs as
|
|
4244
|
+
import { jsx as jsx31, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4188
4245
|
function WidgetAwaitingHuman() {
|
|
4189
|
-
return /* @__PURE__ */
|
|
4246
|
+
return /* @__PURE__ */ jsxs16("p", { className: "flex items-center justify-center gap-1.5 px-4 pb-1.5 text-sm text-muted-foreground", children: [
|
|
4190
4247
|
/* @__PURE__ */ jsx31(UserCircle, { "aria-hidden": true, className: "size-4" }),
|
|
4191
4248
|
"Waiting for the support team"
|
|
4192
4249
|
] });
|
|
4193
4250
|
}
|
|
4194
4251
|
|
|
4195
4252
|
// ../../apps/web/src/components/support-widget/support-widget.tsx
|
|
4196
|
-
import { jsx as jsx32, jsxs as
|
|
4253
|
+
import { jsx as jsx32, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
4197
4254
|
function joinsPreviousTurn(message, previous) {
|
|
4198
4255
|
return !message.dayLabel && !message.startsConversation && message.sender === previous.sender && message.agent?.id === previous.agent?.id && withinRun(previous.sentAt, message.sentAt);
|
|
4199
4256
|
}
|
|
@@ -4223,7 +4280,7 @@ function SupportWidget({
|
|
|
4223
4280
|
className
|
|
4224
4281
|
}) {
|
|
4225
4282
|
const stack = useStackShift(messages.length);
|
|
4226
|
-
return /* @__PURE__ */
|
|
4283
|
+
return /* @__PURE__ */ jsxs17(
|
|
4227
4284
|
"section",
|
|
4228
4285
|
{
|
|
4229
4286
|
"aria-label": `${presence.name} support`,
|
|
@@ -4231,7 +4288,7 @@ function SupportWidget({
|
|
|
4231
4288
|
// The widget keeps its own radius scale. The app's token can climb as
|
|
4232
4289
|
// the chrome gets rounder without the widget changing shape under the
|
|
4233
4290
|
// hosts embedding it.
|
|
4234
|
-
|
|
4291
|
+
`flex h-full w-full flex-col overflow-hidden ${WIDGET_CORNER} border bg-card text-card-foreground [--radius:0.625rem]`,
|
|
4235
4292
|
// And its own pace for a reply arriving a line at a time: a step
|
|
4236
4293
|
// quicker than the palette's ladder, since a support answer is a
|
|
4237
4294
|
// few short lines in a bubble rather than an essay in a column.
|
|
@@ -4305,14 +4362,14 @@ function Conversation({
|
|
|
4305
4362
|
stackRef
|
|
4306
4363
|
}) {
|
|
4307
4364
|
const groups = groupMessages(messages, joinsPreviousTurn);
|
|
4308
|
-
const [openedWith] =
|
|
4365
|
+
const [openedWith] = useState10(
|
|
4309
4366
|
() => new Set(messages.map((message) => message.id))
|
|
4310
4367
|
);
|
|
4311
|
-
const [heldOffer, setHeldOffer] =
|
|
4368
|
+
const [heldOffer, setHeldOffer] = useState10(offer);
|
|
4312
4369
|
if (offer !== null && offer.key !== heldOffer?.key) setHeldOffer(offer);
|
|
4313
|
-
const [heldNotice, setHeldNotice] =
|
|
4370
|
+
const [heldNotice, setHeldNotice] = useState10(notice ?? null);
|
|
4314
4371
|
if (notice && notice !== heldNotice) setHeldNotice(notice);
|
|
4315
|
-
return /* @__PURE__ */
|
|
4372
|
+
return /* @__PURE__ */ jsxs17(
|
|
4316
4373
|
"div",
|
|
4317
4374
|
{
|
|
4318
4375
|
className: cn(
|
|
@@ -4340,7 +4397,7 @@ function Conversation({
|
|
|
4340
4397
|
so a scroller left alone slides the newest message under the
|
|
4341
4398
|
composer and has to catch up afterwards. Following it is what the
|
|
4342
4399
|
scroller stops easing for, so this tracks frame by frame. */
|
|
4343
|
-
/* @__PURE__ */ jsx32(MessageScrollerProvider, { children: /* @__PURE__ */
|
|
4400
|
+
/* @__PURE__ */ jsx32(MessageScrollerProvider, { children: /* @__PURE__ */ jsxs17(MessageScroller, { className: "h-auto min-h-0 flex-1", children: [
|
|
4344
4401
|
/* @__PURE__ */ jsx32(
|
|
4345
4402
|
MessageScrollerViewport,
|
|
4346
4403
|
{
|
|
@@ -4354,7 +4411,7 @@ function Conversation({
|
|
|
4354
4411
|
{
|
|
4355
4412
|
ref: stackRef,
|
|
4356
4413
|
className: "justify-end gap-0",
|
|
4357
|
-
children: messages.map((message, index) => /* @__PURE__ */
|
|
4414
|
+
children: messages.map((message, index) => /* @__PURE__ */ jsxs17(
|
|
4358
4415
|
MessageScrollerItem,
|
|
4359
4416
|
{
|
|
4360
4417
|
messageId: message.id,
|
|
@@ -4417,10 +4474,10 @@ function Conversation({
|
|
|
4417
4474
|
// ../../apps/web/src/components/support-widget/use-launcher-drag.ts
|
|
4418
4475
|
import {
|
|
4419
4476
|
useCallback as useCallback6,
|
|
4420
|
-
useEffect as
|
|
4421
|
-
useLayoutEffect as
|
|
4422
|
-
useRef as
|
|
4423
|
-
useState as
|
|
4477
|
+
useEffect as useEffect7,
|
|
4478
|
+
useLayoutEffect as useLayoutEffect7,
|
|
4479
|
+
useRef as useRef12,
|
|
4480
|
+
useState as useState11,
|
|
4424
4481
|
useSyncExternalStore as useSyncExternalStore4
|
|
4425
4482
|
} from "react";
|
|
4426
4483
|
import { flushSync } from "react-dom";
|
|
@@ -4439,9 +4496,9 @@ function useLauncherDrag({
|
|
|
4439
4496
|
subject
|
|
4440
4497
|
}) {
|
|
4441
4498
|
const spot = useSyncExternalStore4(subscribeSpot, getSpot, getDefaultSpot);
|
|
4442
|
-
const [isMoving, setIsMoving] =
|
|
4443
|
-
const grip =
|
|
4444
|
-
const justDragged =
|
|
4499
|
+
const [isMoving, setIsMoving] = useState11(false);
|
|
4500
|
+
const grip = useRef12(null);
|
|
4501
|
+
const justDragged = useRef12(false);
|
|
4445
4502
|
const measure = useCallback6(() => {
|
|
4446
4503
|
const box = boxRef.current;
|
|
4447
4504
|
const button = buttonRef.current;
|
|
@@ -4492,12 +4549,12 @@ function useLauncherDrag({
|
|
|
4492
4549
|
box.style.top = `${metrics.boxTop - taken.bounds.top}px`;
|
|
4493
4550
|
box.style.setProperty(BUTTON_Y, `${metrics.buttonInBox}px`);
|
|
4494
4551
|
}, [boxRef, measure, spot]);
|
|
4495
|
-
|
|
4496
|
-
|
|
4552
|
+
useLayoutEffect7(place, [place]);
|
|
4553
|
+
useEffect7(() => {
|
|
4497
4554
|
window.addEventListener("resize", place);
|
|
4498
4555
|
return () => window.removeEventListener("resize", place);
|
|
4499
4556
|
}, [place]);
|
|
4500
|
-
|
|
4557
|
+
useEffect7(() => {
|
|
4501
4558
|
const box = boxRef.current;
|
|
4502
4559
|
if (!box || typeof ResizeObserver === "undefined") return;
|
|
4503
4560
|
const observer = new ResizeObserver(place);
|
|
@@ -4508,10 +4565,10 @@ function useLauncherDrag({
|
|
|
4508
4565
|
const box = boxRef.current;
|
|
4509
4566
|
if (box) box.style.transform = "";
|
|
4510
4567
|
}, [boxRef]);
|
|
4511
|
-
const holdPointer = useCallback6((
|
|
4512
|
-
document.body.style.userSelect =
|
|
4513
|
-
document.body.style.cursor =
|
|
4514
|
-
if (
|
|
4568
|
+
const holdPointer = useCallback6((held2) => {
|
|
4569
|
+
document.body.style.userSelect = held2 ? "none" : "";
|
|
4570
|
+
document.body.style.cursor = held2 ? "grabbing" : "";
|
|
4571
|
+
if (held2) window.getSelection()?.removeAllRanges();
|
|
4515
4572
|
}, []);
|
|
4516
4573
|
const handlePointerDown = useCallback6(
|
|
4517
4574
|
(event) => {
|
|
@@ -4548,57 +4605,57 @@ function useLauncherDrag({
|
|
|
4548
4605
|
);
|
|
4549
4606
|
const handlePointerMove = useCallback6(
|
|
4550
4607
|
(event) => {
|
|
4551
|
-
const
|
|
4608
|
+
const held2 = grip.current;
|
|
4552
4609
|
const box = boxRef.current;
|
|
4553
|
-
if (
|
|
4554
|
-
if (!
|
|
4610
|
+
if (held2 === null || box === null) return;
|
|
4611
|
+
if (!held2.moved) {
|
|
4555
4612
|
const travelled = Math.hypot(
|
|
4556
|
-
event.clientX -
|
|
4557
|
-
event.clientY -
|
|
4613
|
+
event.clientX - held2.startX,
|
|
4614
|
+
event.clientY - held2.startY
|
|
4558
4615
|
);
|
|
4559
4616
|
if (travelled < DRAG_THRESHOLD) return;
|
|
4560
|
-
|
|
4617
|
+
held2.moved = true;
|
|
4561
4618
|
holdPointer(true);
|
|
4562
4619
|
setIsMoving(true);
|
|
4563
4620
|
}
|
|
4564
|
-
|
|
4621
|
+
held2.at = {
|
|
4565
4622
|
x: clamp2(
|
|
4566
|
-
event.clientX -
|
|
4567
|
-
|
|
4568
|
-
|
|
4623
|
+
event.clientX - held2.grabX,
|
|
4624
|
+
held2.bounds.left + held2.margin,
|
|
4625
|
+
held2.bounds.left + held2.bounds.width - held2.margin - held2.dragged.width
|
|
4569
4626
|
),
|
|
4570
4627
|
y: clamp2(
|
|
4571
|
-
event.clientY -
|
|
4572
|
-
|
|
4573
|
-
|
|
4628
|
+
event.clientY - held2.grabY,
|
|
4629
|
+
held2.bounds.top + held2.margin,
|
|
4630
|
+
held2.bounds.top + held2.bounds.height - held2.margin - held2.dragged.height
|
|
4574
4631
|
)
|
|
4575
4632
|
};
|
|
4576
|
-
box.style.transform = `translate3d(${
|
|
4633
|
+
box.style.transform = `translate3d(${held2.at.x - held2.resting.x}px, ${held2.at.y - held2.resting.y}px, 0)`;
|
|
4577
4634
|
},
|
|
4578
4635
|
[boxRef, holdPointer]
|
|
4579
4636
|
);
|
|
4580
4637
|
const finishDrag = useCallback6(() => {
|
|
4581
|
-
const
|
|
4582
|
-
if (
|
|
4638
|
+
const held2 = grip.current;
|
|
4639
|
+
if (held2 === null) return;
|
|
4583
4640
|
grip.current = null;
|
|
4584
4641
|
holdPointer(false);
|
|
4585
4642
|
const box = boxRef.current;
|
|
4586
|
-
if (!
|
|
4643
|
+
if (!held2.moved || box === null) {
|
|
4587
4644
|
setIsMoving(false);
|
|
4588
4645
|
return;
|
|
4589
4646
|
}
|
|
4590
4647
|
justDragged.current = true;
|
|
4591
|
-
const target =
|
|
4648
|
+
const target = held2.subject === "panel" ? spotFromPanel(held2.at, held2.bounds, held2.size, held2.box, held2.margin) : spotFrom(held2.at, held2.bounds, held2.size, held2.margin);
|
|
4592
4649
|
const home = metricsFor(
|
|
4593
4650
|
target,
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4651
|
+
held2.bounds,
|
|
4652
|
+
held2.size,
|
|
4653
|
+
held2.box.height,
|
|
4654
|
+
held2.margin
|
|
4598
4655
|
);
|
|
4599
4656
|
const from = {
|
|
4600
|
-
x:
|
|
4601
|
-
y:
|
|
4657
|
+
x: held2.at.x - (target.side === "left" ? held2.bounds.left + held2.margin : held2.bounds.left + held2.bounds.width - held2.margin - held2.dragged.width),
|
|
4658
|
+
y: held2.at.y - (held2.subject === "panel" ? home.boxTop : home.buttonY)
|
|
4602
4659
|
};
|
|
4603
4660
|
flushSync(() => setSpot(target));
|
|
4604
4661
|
settle();
|
|
@@ -4625,7 +4682,7 @@ function useLauncherDrag({
|
|
|
4625
4682
|
},
|
|
4626
4683
|
[finishDrag]
|
|
4627
4684
|
);
|
|
4628
|
-
|
|
4685
|
+
useEffect7(() => {
|
|
4629
4686
|
if (!isMoving) return;
|
|
4630
4687
|
const end = () => finishDrag();
|
|
4631
4688
|
window.addEventListener("pointerup", end);
|
|
@@ -4643,7 +4700,7 @@ function useLauncherDrag({
|
|
|
4643
4700
|
onPointerUp: handlePointerUp,
|
|
4644
4701
|
onPointerCancel: handlePointerUp
|
|
4645
4702
|
};
|
|
4646
|
-
|
|
4703
|
+
useEffect7(() => {
|
|
4647
4704
|
function abandon() {
|
|
4648
4705
|
if (grip.current === null) return;
|
|
4649
4706
|
grip.current = null;
|
|
@@ -4682,15 +4739,15 @@ function clamp2(value, low, high) {
|
|
|
4682
4739
|
}
|
|
4683
4740
|
|
|
4684
4741
|
// ../../apps/web/src/components/support-widget/use-teaser-placement.ts
|
|
4685
|
-
import { useLayoutEffect as
|
|
4742
|
+
import { useLayoutEffect as useLayoutEffect8, useState as useState12 } from "react";
|
|
4686
4743
|
var ROOM_ABOVE_PX = 128;
|
|
4687
4744
|
function useTeaserPlacement({
|
|
4688
4745
|
buttonRef,
|
|
4689
4746
|
enabled: enabled2,
|
|
4690
4747
|
isMoving
|
|
4691
4748
|
}) {
|
|
4692
|
-
const [placement, setPlacement] =
|
|
4693
|
-
|
|
4749
|
+
const [placement, setPlacement] = useState12("above");
|
|
4750
|
+
useLayoutEffect8(() => {
|
|
4694
4751
|
if (!enabled2 || isMoving) return;
|
|
4695
4752
|
const measure = () => {
|
|
4696
4753
|
const button = buttonRef.current;
|
|
@@ -4706,18 +4763,18 @@ function useTeaserPlacement({
|
|
|
4706
4763
|
|
|
4707
4764
|
// ../../apps/web/src/components/support-widget/use-widget-sheet.ts
|
|
4708
4765
|
import {
|
|
4709
|
-
useLayoutEffect as
|
|
4710
|
-
useState as
|
|
4766
|
+
useLayoutEffect as useLayoutEffect9,
|
|
4767
|
+
useState as useState13,
|
|
4711
4768
|
useSyncExternalStore as useSyncExternalStore5
|
|
4712
4769
|
} from "react";
|
|
4713
4770
|
|
|
4714
4771
|
// ../../apps/web/src/components/support-widget/use-page-lock.ts
|
|
4715
|
-
import { useEffect as
|
|
4772
|
+
import { useEffect as useEffect8 } from "react";
|
|
4716
4773
|
function usePageLock(isLocked) {
|
|
4717
|
-
|
|
4774
|
+
useEffect8(() => {
|
|
4718
4775
|
if (!isLocked) return;
|
|
4719
4776
|
const { style } = document.body;
|
|
4720
|
-
const
|
|
4777
|
+
const held2 = {
|
|
4721
4778
|
position: style.position,
|
|
4722
4779
|
top: style.top,
|
|
4723
4780
|
left: style.left,
|
|
@@ -4731,11 +4788,11 @@ function usePageLock(isLocked) {
|
|
|
4731
4788
|
style.right = "0";
|
|
4732
4789
|
style.overflow = "hidden";
|
|
4733
4790
|
return () => {
|
|
4734
|
-
style.position =
|
|
4735
|
-
style.top =
|
|
4736
|
-
style.left =
|
|
4737
|
-
style.right =
|
|
4738
|
-
style.overflow =
|
|
4791
|
+
style.position = held2.position;
|
|
4792
|
+
style.top = held2.top;
|
|
4793
|
+
style.left = held2.left;
|
|
4794
|
+
style.right = held2.right;
|
|
4795
|
+
style.overflow = held2.overflow;
|
|
4739
4796
|
window.scrollTo({ top: scrollY, behavior: "instant" });
|
|
4740
4797
|
};
|
|
4741
4798
|
}, [isLocked]);
|
|
@@ -4743,7 +4800,7 @@ function usePageLock(isLocked) {
|
|
|
4743
4800
|
|
|
4744
4801
|
// ../../apps/web/src/components/support-widget/use-widget-sheet.ts
|
|
4745
4802
|
var PHONE = "(max-width: 40rem)";
|
|
4746
|
-
var
|
|
4803
|
+
var SETTLE_MS = 400;
|
|
4747
4804
|
var KEYBOARD_PX = 96;
|
|
4748
4805
|
function subscribePhone(onChange) {
|
|
4749
4806
|
const media = window.matchMedia(PHONE);
|
|
@@ -4762,13 +4819,13 @@ function useWidgetSheet({
|
|
|
4762
4819
|
isPhoneNow,
|
|
4763
4820
|
isPhoneOnServer
|
|
4764
4821
|
);
|
|
4765
|
-
const [isFramed, setIsFramed] =
|
|
4766
|
-
|
|
4822
|
+
const [isFramed, setIsFramed] = useState13(false);
|
|
4823
|
+
useLayoutEffect9(() => {
|
|
4767
4824
|
setIsFramed(boxRef.current?.offsetParent != null);
|
|
4768
4825
|
}, [boxRef, isPhone]);
|
|
4769
4826
|
const isSheet = isPhone && !isFramed;
|
|
4770
4827
|
const isUp = isSheet && isOpen;
|
|
4771
|
-
|
|
4828
|
+
useLayoutEffect9(() => {
|
|
4772
4829
|
if (!isUp) return;
|
|
4773
4830
|
const panel = panelRef.current;
|
|
4774
4831
|
const viewport = window.visualViewport;
|
|
@@ -4797,7 +4854,7 @@ function useWidgetSheet({
|
|
|
4797
4854
|
frame = performance.now() < until ? requestAnimationFrame(follow) : 0;
|
|
4798
4855
|
};
|
|
4799
4856
|
const track = () => {
|
|
4800
|
-
until = performance.now() +
|
|
4857
|
+
until = performance.now() + SETTLE_MS;
|
|
4801
4858
|
if (frame === 0) frame = requestAnimationFrame(follow);
|
|
4802
4859
|
};
|
|
4803
4860
|
fit();
|
|
@@ -4820,7 +4877,7 @@ function useWidgetSheet({
|
|
|
4820
4877
|
}
|
|
4821
4878
|
|
|
4822
4879
|
// ../../apps/web/src/components/support-widget/widget-modal.tsx
|
|
4823
|
-
import { useRef as
|
|
4880
|
+
import { useRef as useRef13 } from "react";
|
|
4824
4881
|
import { createPortal } from "react-dom";
|
|
4825
4882
|
|
|
4826
4883
|
// ../../apps/web/src/components/support-widget/use-hydrated.ts
|
|
@@ -4834,12 +4891,12 @@ function useHydrated() {
|
|
|
4834
4891
|
}
|
|
4835
4892
|
|
|
4836
4893
|
// ../../apps/web/src/components/support-widget/use-scroll-lock.ts
|
|
4837
|
-
import { useEffect as
|
|
4894
|
+
import { useEffect as useEffect9 } from "react";
|
|
4838
4895
|
function useScrollLock(isLocked) {
|
|
4839
|
-
|
|
4896
|
+
useEffect9(() => {
|
|
4840
4897
|
if (!isLocked) return;
|
|
4841
4898
|
const { body } = document;
|
|
4842
|
-
const
|
|
4899
|
+
const held2 = {
|
|
4843
4900
|
overflow: body.style.overflow,
|
|
4844
4901
|
paddingRight: body.style.paddingRight
|
|
4845
4902
|
};
|
|
@@ -4850,14 +4907,14 @@ function useScrollLock(isLocked) {
|
|
|
4850
4907
|
body.style.paddingRight = `${existing + gutter}px`;
|
|
4851
4908
|
}
|
|
4852
4909
|
return () => {
|
|
4853
|
-
body.style.overflow =
|
|
4854
|
-
body.style.paddingRight =
|
|
4910
|
+
body.style.overflow = held2.overflow;
|
|
4911
|
+
body.style.paddingRight = held2.paddingRight;
|
|
4855
4912
|
};
|
|
4856
4913
|
}, [isLocked]);
|
|
4857
4914
|
}
|
|
4858
4915
|
|
|
4859
4916
|
// ../../apps/web/src/components/support-widget/widget-modal.tsx
|
|
4860
|
-
import { jsx as jsx33, jsxs as
|
|
4917
|
+
import { jsx as jsx33, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
4861
4918
|
var LAYER = 2147483e3;
|
|
4862
4919
|
var WIDTH = "50rem";
|
|
4863
4920
|
var HEIGHT = "40rem";
|
|
@@ -4873,13 +4930,13 @@ function SupportModal({
|
|
|
4873
4930
|
label,
|
|
4874
4931
|
children
|
|
4875
4932
|
}) {
|
|
4876
|
-
const layerRef =
|
|
4933
|
+
const layerRef = useRef13(null);
|
|
4877
4934
|
const isHydrated = useHydrated();
|
|
4878
4935
|
const isSheet = useWidgetSheet({ boxRef: layerRef, panelRef, isOpen });
|
|
4879
4936
|
useScrollLock(isOpen && !isSheet);
|
|
4880
4937
|
if (!isHydrated) return null;
|
|
4881
4938
|
return createPortal(
|
|
4882
|
-
/* @__PURE__ */
|
|
4939
|
+
/* @__PURE__ */ jsxs18(
|
|
4883
4940
|
"div",
|
|
4884
4941
|
{
|
|
4885
4942
|
ref: layerRef,
|
|
@@ -4924,7 +4981,7 @@ function SupportModal({
|
|
|
4924
4981
|
isOpen ? "translate-y-0 opacity-100" : "translate-y-8 opacity-0"
|
|
4925
4982
|
] : [
|
|
4926
4983
|
// Never past the layer's padding, whatever the size says.
|
|
4927
|
-
|
|
4984
|
+
`relative max-h-full max-w-full ${WIDGET_CORNER} shadow-2xl`,
|
|
4928
4985
|
MOTION,
|
|
4929
4986
|
isOpen ? [OPEN, "scale-100 opacity-100 translate-y-0"] : [SHUT, "scale-[0.96] opacity-0 translate-y-2"]
|
|
4930
4987
|
]
|
|
@@ -4947,7 +5004,7 @@ var SHEET_PANEL = cn(
|
|
|
4947
5004
|
);
|
|
4948
5005
|
|
|
4949
5006
|
// ../../apps/web/src/components/support-widget/widget-teaser.tsx
|
|
4950
|
-
import { useState as
|
|
5007
|
+
import { useState as useState14 } from "react";
|
|
4951
5008
|
|
|
4952
5009
|
// ../../apps/web/src/components/support-widget/plain-text.ts
|
|
4953
5010
|
function plainTextOf(markdown) {
|
|
@@ -4955,7 +5012,7 @@ function plainTextOf(markdown) {
|
|
|
4955
5012
|
}
|
|
4956
5013
|
|
|
4957
5014
|
// ../../apps/web/src/components/support-widget/widget-teaser.tsx
|
|
4958
|
-
import { Fragment as Fragment29, jsx as jsx34, jsxs as
|
|
5015
|
+
import { Fragment as Fragment29, jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
4959
5016
|
var WIDTH2 = "min(20rem, 100%)";
|
|
4960
5017
|
var GAP = "0.5rem";
|
|
4961
5018
|
function WidgetTeaser({
|
|
@@ -4968,13 +5025,13 @@ function WidgetTeaser({
|
|
|
4968
5025
|
onOpen,
|
|
4969
5026
|
onDismiss
|
|
4970
5027
|
}) {
|
|
4971
|
-
const [
|
|
4972
|
-
if (message !== null && message !==
|
|
4973
|
-
const shown = message ??
|
|
5028
|
+
const [held2, setHeld] = useState14(message);
|
|
5029
|
+
if (message !== null && message !== held2) setHeld(message);
|
|
5030
|
+
const shown = message ?? held2;
|
|
4974
5031
|
if (shown === null) return null;
|
|
4975
5032
|
const agent = shown.agent;
|
|
4976
5033
|
const text = plainTextOf(shown.body);
|
|
4977
|
-
return /* @__PURE__ */
|
|
5034
|
+
return /* @__PURE__ */ jsxs19(
|
|
4978
5035
|
"div",
|
|
4979
5036
|
{
|
|
4980
5037
|
inert: !isShown,
|
|
@@ -4999,7 +5056,7 @@ function WidgetTeaser({
|
|
|
4999
5056
|
] : "pointer-events-none scale-95 opacity-0 duration-150 ease-out-quint"
|
|
5000
5057
|
),
|
|
5001
5058
|
children: [
|
|
5002
|
-
/* @__PURE__ */
|
|
5059
|
+
/* @__PURE__ */ jsxs19(
|
|
5003
5060
|
"button",
|
|
5004
5061
|
{
|
|
5005
5062
|
type: "button",
|
|
@@ -5008,17 +5065,17 @@ function WidgetTeaser({
|
|
|
5008
5065
|
className: cn(
|
|
5009
5066
|
// Its own radius scale, like the panel, so the app's token cannot
|
|
5010
5067
|
// reshape a card that sits on somebody else's site.
|
|
5011
|
-
|
|
5068
|
+
`block w-full ${WIDGET_CORNER} border bg-card p-3.5 pr-10 text-left text-card-foreground shadow-lg [--radius:0.625rem]`,
|
|
5012
5069
|
"transition-[background-color,box-shadow] outline-none",
|
|
5013
5070
|
"hover:bg-muted/50 focus-visible:ring-3 focus-visible:ring-ring/50",
|
|
5014
5071
|
"cursor-pointer select-none"
|
|
5015
5072
|
),
|
|
5016
5073
|
children: [
|
|
5017
|
-
/* @__PURE__ */
|
|
5018
|
-
agent && /* @__PURE__ */
|
|
5074
|
+
/* @__PURE__ */ jsxs19("span", { className: "flex items-center gap-2", children: [
|
|
5075
|
+
agent && /* @__PURE__ */ jsxs19(Fragment29, { children: [
|
|
5019
5076
|
/* @__PURE__ */ jsx34(WidgetAvatar, { agent, className: "size-6 rounded-md" }),
|
|
5020
5077
|
/* @__PURE__ */ jsx34("span", { className: "truncate text-sm font-medium", children: agent.name }),
|
|
5021
|
-
agent.kind === "ai" && /* @__PURE__ */ jsx34(Badge, { variant: "muted", className: "shrink-0 rounded-md px-1", children: "AI" })
|
|
5078
|
+
agent.kind === "ai" && /* @__PURE__ */ jsx34(Badge, { variant: "muted", className: "shrink-0 rounded-md bg-muted px-1 inset-ring-0", children: "AI" })
|
|
5022
5079
|
] }),
|
|
5023
5080
|
/* @__PURE__ */ jsx34("span", { className: "ml-auto shrink-0 text-sm text-muted-foreground tabular-nums", children: shown.time })
|
|
5024
5081
|
] }),
|
|
@@ -5048,14 +5105,13 @@ function WidgetTeaser({
|
|
|
5048
5105
|
}
|
|
5049
5106
|
|
|
5050
5107
|
// ../../apps/web/src/components/support-widget/widget-launcher.tsx
|
|
5051
|
-
import { Fragment as Fragment30, jsx as jsx35, jsxs as
|
|
5108
|
+
import { Fragment as Fragment30, jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
5052
5109
|
var DEFAULT_WIDTH = "28rem";
|
|
5053
5110
|
var DEFAULT_HEIGHT = "40rem";
|
|
5054
5111
|
var DEFAULT_BUTTON_SIZE = "3rem";
|
|
5055
5112
|
var EXPANDED_WIDTH = "34rem";
|
|
5056
5113
|
var EXPANDED_HEIGHT = "52rem";
|
|
5057
|
-
var
|
|
5058
|
-
var OPEN_CLIP = `inset(0px 0px 0px 0px round ${PANEL_RADIUS})`;
|
|
5114
|
+
var OPEN_CLIP = `inset(0px 0px 0px 0px round ${WIDGET_RADIUS})`;
|
|
5059
5115
|
var buttonY = (buttonSize) => `var(${BUTTON_Y}, calc(100% - ${buttonSize}))`;
|
|
5060
5116
|
var MARGIN = "1rem";
|
|
5061
5117
|
var CLOSED_SCALE = "scale(0.94)";
|
|
@@ -5105,14 +5161,14 @@ function SupportLauncher({
|
|
|
5105
5161
|
onOpenChange,
|
|
5106
5162
|
className
|
|
5107
5163
|
}) {
|
|
5108
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
5164
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState15(defaultOpen);
|
|
5109
5165
|
const isOpen = open ?? uncontrolledOpen;
|
|
5110
5166
|
const hasBubble = launcher === "bubble";
|
|
5111
5167
|
const isModal = presentation === "modal";
|
|
5112
|
-
const [isExpanded, setExpanded] =
|
|
5113
|
-
const launcherRef =
|
|
5114
|
-
const panelRef =
|
|
5115
|
-
const boxRef =
|
|
5168
|
+
const [isExpanded, setExpanded] = useState15(false);
|
|
5169
|
+
const launcherRef = useRef14(null);
|
|
5170
|
+
const panelRef = useRef14(null);
|
|
5171
|
+
const boxRef = useRef14(null);
|
|
5116
5172
|
const drag = useLauncherDrag({
|
|
5117
5173
|
boxRef,
|
|
5118
5174
|
buttonRef: launcherRef,
|
|
@@ -5132,8 +5188,8 @@ function SupportLauncher({
|
|
|
5132
5188
|
enabled: hasTeaser,
|
|
5133
5189
|
isMoving: drag.isMoving
|
|
5134
5190
|
});
|
|
5135
|
-
const opener =
|
|
5136
|
-
const wasOpen =
|
|
5191
|
+
const opener = useRef14(null);
|
|
5192
|
+
const wasOpen = useRef14(isOpen);
|
|
5137
5193
|
const setOpen = useCallback7(
|
|
5138
5194
|
(next) => {
|
|
5139
5195
|
if (open === void 0) setUncontrolledOpen(next);
|
|
@@ -5149,10 +5205,10 @@ function SupportLauncher({
|
|
|
5149
5205
|
},
|
|
5150
5206
|
[onFollow, isSheet, isModal, close]
|
|
5151
5207
|
);
|
|
5152
|
-
|
|
5208
|
+
useEffect10(() => {
|
|
5153
5209
|
if (isOpen) warmMarkdown();
|
|
5154
5210
|
}, [isOpen]);
|
|
5155
|
-
|
|
5211
|
+
useEffect10(() => {
|
|
5156
5212
|
if (!isOpen) return;
|
|
5157
5213
|
function handleKeyDown(event) {
|
|
5158
5214
|
if (event.key === "Escape") close();
|
|
@@ -5160,7 +5216,7 @@ function SupportLauncher({
|
|
|
5160
5216
|
document.addEventListener("keydown", handleKeyDown);
|
|
5161
5217
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
5162
5218
|
}, [isOpen, close]);
|
|
5163
|
-
|
|
5219
|
+
useEffect10(() => {
|
|
5164
5220
|
if (wasOpen.current === isOpen) return;
|
|
5165
5221
|
wasOpen.current = isOpen;
|
|
5166
5222
|
if (isOpen) {
|
|
@@ -5201,8 +5257,8 @@ function SupportLauncher({
|
|
|
5201
5257
|
compact: isModal
|
|
5202
5258
|
}
|
|
5203
5259
|
);
|
|
5204
|
-
return /* @__PURE__ */
|
|
5205
|
-
/* @__PURE__ */
|
|
5260
|
+
return /* @__PURE__ */ jsxs20(Fragment30, { children: [
|
|
5261
|
+
/* @__PURE__ */ jsxs20(
|
|
5206
5262
|
"div",
|
|
5207
5263
|
{
|
|
5208
5264
|
ref: boxRef,
|
|
@@ -5271,7 +5327,7 @@ function SupportLauncher({
|
|
|
5271
5327
|
children: widget(isSheet)
|
|
5272
5328
|
}
|
|
5273
5329
|
),
|
|
5274
|
-
hasBubble && /* @__PURE__ */
|
|
5330
|
+
hasBubble && /* @__PURE__ */ jsxs20(
|
|
5275
5331
|
"button",
|
|
5276
5332
|
{
|
|
5277
5333
|
ref: launcherRef,
|
|
@@ -5386,9 +5442,9 @@ function SupportLauncher({
|
|
|
5386
5442
|
}
|
|
5387
5443
|
|
|
5388
5444
|
// ../../apps/web/src/components/support-widget/widget-spotlight.tsx
|
|
5389
|
-
import { useEffect as
|
|
5445
|
+
import { useEffect as useEffect11, useRef as useRef15, useState as useState16 } from "react";
|
|
5390
5446
|
import { createPortal as createPortal2 } from "react-dom";
|
|
5391
|
-
import { jsx as jsx36, jsxs as
|
|
5447
|
+
import { jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
5392
5448
|
var FIND_TIMEOUT_MS = 4e3;
|
|
5393
5449
|
var HOLD_MS = 2600;
|
|
5394
5450
|
var FADE_MS = 300;
|
|
@@ -5397,10 +5453,10 @@ function prefersReducedMotion4() {
|
|
|
5397
5453
|
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
5398
5454
|
}
|
|
5399
5455
|
function WidgetSpotlight({ selector }) {
|
|
5400
|
-
const [isShown, setIsShown] =
|
|
5401
|
-
const [isLeaving, setIsLeaving] =
|
|
5402
|
-
const ring =
|
|
5403
|
-
|
|
5456
|
+
const [isShown, setIsShown] = useState16(false);
|
|
5457
|
+
const [isLeaving, setIsLeaving] = useState16(false);
|
|
5458
|
+
const ring = useRef15(null);
|
|
5459
|
+
useEffect11(() => {
|
|
5404
5460
|
let target = null;
|
|
5405
5461
|
let frame = 0;
|
|
5406
5462
|
let startedAt = 0;
|
|
@@ -5459,7 +5515,7 @@ function WidgetSpotlight({ selector }) {
|
|
|
5459
5515
|
}, [selector]);
|
|
5460
5516
|
if (!isShown || typeof document === "undefined") return null;
|
|
5461
5517
|
return createPortal2(
|
|
5462
|
-
/* @__PURE__ */
|
|
5518
|
+
/* @__PURE__ */ jsxs21(
|
|
5463
5519
|
"div",
|
|
5464
5520
|
{
|
|
5465
5521
|
ref: ring,
|
|
@@ -5473,7 +5529,9 @@ function WidgetSpotlight({ selector }) {
|
|
|
5473
5529
|
{
|
|
5474
5530
|
className: [
|
|
5475
5531
|
"absolute -inset-1 rounded-lg outline-2 outline-offset-0 outline-primary",
|
|
5476
|
-
|
|
5532
|
+
// With the widget's own primary behind the host's, like every
|
|
5533
|
+
// other colour it draws.
|
|
5534
|
+
"shadow-[0_0_0_6px_color-mix(in_oklch,var(--primary,oklch(0.205_0_0))_20%,transparent)]",
|
|
5477
5535
|
"transition-opacity duration-300 ease-out motion-reduce:transition-none",
|
|
5478
5536
|
isLeaving ? "opacity-0" : "opacity-100"
|
|
5479
5537
|
].join(" ")
|
|
@@ -5497,7 +5555,7 @@ function WidgetSpotlight({ selector }) {
|
|
|
5497
5555
|
}
|
|
5498
5556
|
|
|
5499
5557
|
// ../../apps/web/src/components/support-widget/sdk/control.ts
|
|
5500
|
-
import { useSyncExternalStore as
|
|
5558
|
+
import { useSyncExternalStore as useSyncExternalStore13 } from "react";
|
|
5501
5559
|
|
|
5502
5560
|
// ../backend/convex/shared/customData.ts
|
|
5503
5561
|
var MAX_CUSTOM_ENTRIES = 8;
|
|
@@ -5544,7 +5602,20 @@ function mergeCustomData(...sources) {
|
|
|
5544
5602
|
}
|
|
5545
5603
|
|
|
5546
5604
|
// ../../apps/web/src/components/support-widget/sdk/custom-data.ts
|
|
5605
|
+
import { useEffect as useEffect12 } from "react";
|
|
5547
5606
|
var queued = [];
|
|
5607
|
+
var senders = 0;
|
|
5608
|
+
function useCustomDataSender() {
|
|
5609
|
+
useEffect12(() => {
|
|
5610
|
+
senders += 1;
|
|
5611
|
+
return () => {
|
|
5612
|
+
senders -= 1;
|
|
5613
|
+
};
|
|
5614
|
+
}, []);
|
|
5615
|
+
}
|
|
5616
|
+
function hasCustomDataSender() {
|
|
5617
|
+
return senders > 0;
|
|
5618
|
+
}
|
|
5548
5619
|
function queueCustomData(label, value) {
|
|
5549
5620
|
const cleaned = cleanCustomData([{ label, value }]);
|
|
5550
5621
|
if (cleaned === void 0) return false;
|
|
@@ -5562,23 +5633,26 @@ function restoreCustomData(entries) {
|
|
|
5562
5633
|
}
|
|
5563
5634
|
|
|
5564
5635
|
// ../../apps/web/src/components/support-widget/sdk/open-store.ts
|
|
5565
|
-
import { useCallback as useCallback8, useEffect as useEffect13, useSyncExternalStore as useSyncExternalStore7 } from "react";
|
|
5636
|
+
import { useCallback as useCallback8, useEffect as useEffect13, useRef as useRef16, useSyncExternalStore as useSyncExternalStore7 } from "react";
|
|
5566
5637
|
var isDevelopment = typeof process !== "undefined" && process.env.NODE_ENV === "development";
|
|
5567
5638
|
function createOpenStore(component) {
|
|
5568
5639
|
let requested = null;
|
|
5569
5640
|
let effective = false;
|
|
5570
5641
|
let mounted = 0;
|
|
5571
|
-
const
|
|
5642
|
+
const mountedNames = [];
|
|
5643
|
+
const listeners7 = /* @__PURE__ */ new Set();
|
|
5644
|
+
const requestListeners = /* @__PURE__ */ new Set();
|
|
5645
|
+
let isReporting = false;
|
|
5572
5646
|
function emit() {
|
|
5573
|
-
for (const listener of
|
|
5647
|
+
for (const listener of listeners7) listener();
|
|
5574
5648
|
}
|
|
5575
5649
|
return {
|
|
5576
5650
|
/** The component a warning should name, so it reads like the host's code. */
|
|
5577
5651
|
component,
|
|
5578
5652
|
subscribe(listener) {
|
|
5579
|
-
|
|
5653
|
+
listeners7.add(listener);
|
|
5580
5654
|
return () => {
|
|
5581
|
-
|
|
5655
|
+
listeners7.delete(listener);
|
|
5582
5656
|
};
|
|
5583
5657
|
},
|
|
5584
5658
|
readRequested: () => requested,
|
|
@@ -5592,6 +5666,20 @@ function createOpenStore(component) {
|
|
|
5592
5666
|
request(next) {
|
|
5593
5667
|
requested = next;
|
|
5594
5668
|
emit();
|
|
5669
|
+
if (isReporting) return;
|
|
5670
|
+
isReporting = true;
|
|
5671
|
+
try {
|
|
5672
|
+
for (const listener of requestListeners) listener(next);
|
|
5673
|
+
} finally {
|
|
5674
|
+
isReporting = false;
|
|
5675
|
+
}
|
|
5676
|
+
},
|
|
5677
|
+
/** Hears each request: a trigger, the hook, or the panel's own button. */
|
|
5678
|
+
onRequest(listener) {
|
|
5679
|
+
requestListeners.add(listener);
|
|
5680
|
+
return () => {
|
|
5681
|
+
requestListeners.delete(listener);
|
|
5682
|
+
};
|
|
5595
5683
|
},
|
|
5596
5684
|
/** Told, not asked: the panel saying what it settled on. */
|
|
5597
5685
|
settle(next) {
|
|
@@ -5599,12 +5687,17 @@ function createOpenStore(component) {
|
|
|
5599
5687
|
effective = next;
|
|
5600
5688
|
emit();
|
|
5601
5689
|
},
|
|
5602
|
-
countMounted() {
|
|
5690
|
+
countMounted(name = component) {
|
|
5603
5691
|
mounted += 1;
|
|
5692
|
+
mountedNames.push(name);
|
|
5604
5693
|
return mounted;
|
|
5605
5694
|
},
|
|
5606
|
-
|
|
5695
|
+
/** The components on the page, for a warning that names them. */
|
|
5696
|
+
mountedNames: () => [...mountedNames],
|
|
5697
|
+
countUnmounted(name = component) {
|
|
5607
5698
|
mounted -= 1;
|
|
5699
|
+
const at2 = mountedNames.indexOf(name);
|
|
5700
|
+
if (at2 !== -1) mountedNames.splice(at2, 1);
|
|
5608
5701
|
if (mounted === 0 && effective) {
|
|
5609
5702
|
effective = false;
|
|
5610
5703
|
emit();
|
|
@@ -5645,24 +5738,48 @@ function useOpenState(store3, {
|
|
|
5645
5738
|
useEffect13(() => {
|
|
5646
5739
|
store3.settle(isOpen);
|
|
5647
5740
|
}, [store3, isOpen]);
|
|
5741
|
+
const reportRef = useRef16(onOpenChange);
|
|
5742
|
+
useEffect13(() => {
|
|
5743
|
+
reportRef.current = onOpenChange;
|
|
5744
|
+
});
|
|
5745
|
+
useEffect13(
|
|
5746
|
+
() => store3.onRequest((next) => reportRef.current?.(next)),
|
|
5747
|
+
[store3]
|
|
5748
|
+
);
|
|
5648
5749
|
const setOpen = useCallback8(
|
|
5649
5750
|
(next) => {
|
|
5650
5751
|
store3.request(next);
|
|
5651
|
-
onOpenChange?.(next);
|
|
5652
5752
|
},
|
|
5653
|
-
[store3
|
|
5753
|
+
[store3]
|
|
5654
5754
|
);
|
|
5655
5755
|
return [isOpen, setOpen];
|
|
5656
5756
|
}
|
|
5657
|
-
function useRegister(store3) {
|
|
5757
|
+
function useRegister(store3, name = store3.component) {
|
|
5658
5758
|
useEffect13(() => {
|
|
5659
|
-
if (store3.countMounted() > 1 && isDevelopment) {
|
|
5759
|
+
if (store3.countMounted(name) > 1 && isDevelopment) {
|
|
5760
|
+
const names = [...new Set(store3.mountedNames())];
|
|
5761
|
+
const which = names.length === 1 ? `more than one <${names[0]}> is mounted` : `${names.map((one) => `<${one}>`).join(" and ")} are both mounted`;
|
|
5660
5762
|
console.warn(
|
|
5661
|
-
`Median:
|
|
5763
|
+
`Median: ${which}. They share one open state and open together. Mount one, once, near the root of your app.`
|
|
5662
5764
|
);
|
|
5663
5765
|
}
|
|
5664
|
-
return () => store3.countUnmounted();
|
|
5665
|
-
}, [store3]);
|
|
5766
|
+
return () => store3.countUnmounted(name);
|
|
5767
|
+
}, [store3, name]);
|
|
5768
|
+
}
|
|
5769
|
+
|
|
5770
|
+
// ../backend/convex/shared/mutationResult.ts
|
|
5771
|
+
import { ConvexError } from "convex/values";
|
|
5772
|
+
function unwrapResult(result) {
|
|
5773
|
+
if (result.auditResult === "error") throw new ConvexError(result.data);
|
|
5774
|
+
return result.value;
|
|
5775
|
+
}
|
|
5776
|
+
|
|
5777
|
+
// ../backend/client/mutationResult.ts
|
|
5778
|
+
function unwrapMutationResult(result) {
|
|
5779
|
+
if (result && typeof result === "object" && "auditResult" in result && (result.auditResult === "ok" && "value" in result || result.auditResult === "error" && "data" in result)) {
|
|
5780
|
+
return unwrapResult(result);
|
|
5781
|
+
}
|
|
5782
|
+
return result;
|
|
5666
5783
|
}
|
|
5667
5784
|
|
|
5668
5785
|
// ../backend/convex/_generated/api.js
|
|
@@ -5702,6 +5819,33 @@ function cleanCrash(input) {
|
|
|
5702
5819
|
import { ConvexHttpClient } from "convex/browser";
|
|
5703
5820
|
import { useSyncExternalStore as useSyncExternalStore10 } from "react";
|
|
5704
5821
|
|
|
5822
|
+
// ../../apps/web/src/lib/upload.ts
|
|
5823
|
+
async function uploadFile(getUploadUrl, file) {
|
|
5824
|
+
const url = await getUploadUrl();
|
|
5825
|
+
const response = await fetch(url, {
|
|
5826
|
+
method: "POST",
|
|
5827
|
+
headers: { "Content-Type": file.type || "application/octet-stream" },
|
|
5828
|
+
body: file
|
|
5829
|
+
});
|
|
5830
|
+
if (!response.ok) {
|
|
5831
|
+
throw new Error(`Uploading ${file.name} failed with ${response.status}`);
|
|
5832
|
+
}
|
|
5833
|
+
const { storageId } = await response.json();
|
|
5834
|
+
return storageId;
|
|
5835
|
+
}
|
|
5836
|
+
async function uploadAttachments(getUploadUrl, files) {
|
|
5837
|
+
const attachments = [];
|
|
5838
|
+
for (const file of files) {
|
|
5839
|
+
attachments.push({
|
|
5840
|
+
storageId: await uploadFile(getUploadUrl, file),
|
|
5841
|
+
name: file.name,
|
|
5842
|
+
size: file.size,
|
|
5843
|
+
type: file.type || "application/octet-stream"
|
|
5844
|
+
});
|
|
5845
|
+
}
|
|
5846
|
+
return attachments;
|
|
5847
|
+
}
|
|
5848
|
+
|
|
5705
5849
|
// ../../apps/web/src/components/support-widget/sdk/context.ts
|
|
5706
5850
|
var BROWSERS = [
|
|
5707
5851
|
{ name: "Edge", token: /Edg(?:e|A|iOS)?\/(\d+)/ },
|
|
@@ -5867,7 +6011,7 @@ function cleanClientDiagnostics(input) {
|
|
|
5867
6011
|
}
|
|
5868
6012
|
|
|
5869
6013
|
// ../../apps/web/src/components/support-widget/sdk/diagnostics.ts
|
|
5870
|
-
import { useCallback as useCallback9, useEffect as useEffect14, useRef as
|
|
6014
|
+
import { useCallback as useCallback9, useEffect as useEffect14, useRef as useRef17 } from "react";
|
|
5871
6015
|
function settingsOf(option) {
|
|
5872
6016
|
if (option === void 0 || option === false) return null;
|
|
5873
6017
|
if (option === true) return { errors: true, network: false, console: false };
|
|
@@ -5897,9 +6041,8 @@ function messageOf(value) {
|
|
|
5897
6041
|
function stackOf(value) {
|
|
5898
6042
|
return value instanceof Error && typeof value.stack === "string" ? value.stack.slice(0, STACK_MAX_LENGTH) : void 0;
|
|
5899
6043
|
}
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
if (settings.errors) {
|
|
6044
|
+
var INSTALLERS = {
|
|
6045
|
+
errors: () => {
|
|
5903
6046
|
const onError = (event) => {
|
|
5904
6047
|
if (!event.error && !event.message) return;
|
|
5905
6048
|
record({
|
|
@@ -5925,12 +6068,14 @@ function collect(settings) {
|
|
|
5925
6068
|
};
|
|
5926
6069
|
window.addEventListener("error", onError);
|
|
5927
6070
|
window.addEventListener("unhandledrejection", onRejection);
|
|
5928
|
-
|
|
6071
|
+
return () => {
|
|
5929
6072
|
window.removeEventListener("error", onError);
|
|
5930
6073
|
window.removeEventListener("unhandledrejection", onRejection);
|
|
5931
|
-
}
|
|
5932
|
-
}
|
|
5933
|
-
|
|
6074
|
+
};
|
|
6075
|
+
},
|
|
6076
|
+
network: () => {
|
|
6077
|
+
if (typeof window.fetch !== "function") return () => {
|
|
6078
|
+
};
|
|
5934
6079
|
const original = window.fetch;
|
|
5935
6080
|
window.fetch = async function medianFetch(...args) {
|
|
5936
6081
|
const [input, init] = args;
|
|
@@ -5964,11 +6109,11 @@ function collect(settings) {
|
|
|
5964
6109
|
throw thrown;
|
|
5965
6110
|
}
|
|
5966
6111
|
};
|
|
5967
|
-
|
|
6112
|
+
return () => {
|
|
5968
6113
|
window.fetch = original;
|
|
5969
|
-
}
|
|
5970
|
-
}
|
|
5971
|
-
|
|
6114
|
+
};
|
|
6115
|
+
},
|
|
6116
|
+
console: () => {
|
|
5972
6117
|
const original = console.error;
|
|
5973
6118
|
console.error = function medianConsoleError(...args) {
|
|
5974
6119
|
record({
|
|
@@ -5979,12 +6124,32 @@ function collect(settings) {
|
|
|
5979
6124
|
});
|
|
5980
6125
|
original.apply(console, args);
|
|
5981
6126
|
};
|
|
5982
|
-
|
|
6127
|
+
return () => {
|
|
5983
6128
|
console.error = original;
|
|
5984
|
-
}
|
|
6129
|
+
};
|
|
6130
|
+
}
|
|
6131
|
+
};
|
|
6132
|
+
var wanted = {
|
|
6133
|
+
errors: 0,
|
|
6134
|
+
network: 0,
|
|
6135
|
+
console: 0
|
|
6136
|
+
};
|
|
6137
|
+
var removers = {};
|
|
6138
|
+
function collect(settings) {
|
|
6139
|
+
const kinds = Object.keys(settings).filter(
|
|
6140
|
+
(kind) => settings[kind]
|
|
6141
|
+
);
|
|
6142
|
+
for (const kind of kinds) {
|
|
6143
|
+
wanted[kind] += 1;
|
|
6144
|
+
if (wanted[kind] === 1) removers[kind] = INSTALLERS[kind]();
|
|
5985
6145
|
}
|
|
5986
6146
|
return () => {
|
|
5987
|
-
for (const
|
|
6147
|
+
for (const kind of kinds) {
|
|
6148
|
+
wanted[kind] -= 1;
|
|
6149
|
+
if (wanted[kind] > 0) continue;
|
|
6150
|
+
removers[kind]?.();
|
|
6151
|
+
delete removers[kind];
|
|
6152
|
+
}
|
|
5988
6153
|
};
|
|
5989
6154
|
}
|
|
5990
6155
|
function snapshot(state) {
|
|
@@ -5998,24 +6163,37 @@ function snapshot(state) {
|
|
|
5998
6163
|
});
|
|
5999
6164
|
}
|
|
6000
6165
|
function snapshotNow(extraState) {
|
|
6001
|
-
|
|
6166
|
+
const merged = { ...extraState };
|
|
6167
|
+
for (const [key, value] of Object.entries(latestState ?? {})) {
|
|
6168
|
+
if (!Object.prototype.hasOwnProperty.call(merged, key)) {
|
|
6169
|
+
merged[key] = value;
|
|
6170
|
+
}
|
|
6171
|
+
}
|
|
6172
|
+
return snapshot(merged);
|
|
6002
6173
|
}
|
|
6003
6174
|
function useDiagnostics(option, appState) {
|
|
6004
6175
|
const settings = settingsOf(option);
|
|
6005
6176
|
const key = settings === null ? null : JSON.stringify(settings);
|
|
6006
|
-
const stateRef =
|
|
6177
|
+
const stateRef = useRef17(appState);
|
|
6178
|
+
const shared = useRef17(void 0);
|
|
6007
6179
|
useEffect14(() => {
|
|
6008
6180
|
stateRef.current = appState;
|
|
6009
|
-
|
|
6181
|
+
if (appState !== void 0) {
|
|
6182
|
+
latestState = appState;
|
|
6183
|
+
} else if (shared.current !== void 0 && latestState === shared.current) {
|
|
6184
|
+
latestState = void 0;
|
|
6185
|
+
}
|
|
6186
|
+
shared.current = appState;
|
|
6010
6187
|
});
|
|
6011
|
-
const sentAt =
|
|
6188
|
+
const sentAt = useRef17(null);
|
|
6012
6189
|
useEffect14(() => {
|
|
6013
6190
|
if (key === null) return;
|
|
6014
6191
|
return collect(JSON.parse(key));
|
|
6015
6192
|
}, [key]);
|
|
6016
6193
|
const take = useCallback9(() => {
|
|
6017
6194
|
if (key === null) return void 0;
|
|
6018
|
-
if (sentAt.current !== null && sentAt.current === recorded)
|
|
6195
|
+
if (sentAt.current !== null && sentAt.current === recorded)
|
|
6196
|
+
return void 0;
|
|
6019
6197
|
sentAt.current = recorded;
|
|
6020
6198
|
return snapshot(stateRef.current);
|
|
6021
6199
|
}, [key]);
|
|
@@ -6051,10 +6229,117 @@ function useRememberInstall(apiKey, user) {
|
|
|
6051
6229
|
});
|
|
6052
6230
|
}
|
|
6053
6231
|
|
|
6232
|
+
// ../../apps/web/src/components/support-widget/sdk/screenshot.ts
|
|
6233
|
+
var MAX_WIDTH = 1440;
|
|
6234
|
+
var TIMEOUT_MS = 6e3;
|
|
6235
|
+
var TYPE = "image/jpeg";
|
|
6236
|
+
var QUALITY = 0.85;
|
|
6237
|
+
var SCREENSHOT_NAME = "screenshot.jpg";
|
|
6238
|
+
var PIN_ATTRIBUTE = "data-median-pin";
|
|
6239
|
+
async function capturePage() {
|
|
6240
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
6241
|
+
return null;
|
|
6242
|
+
}
|
|
6243
|
+
const page = document.documentElement;
|
|
6244
|
+
if (page === null) return null;
|
|
6245
|
+
try {
|
|
6246
|
+
const blob = await Promise.race([
|
|
6247
|
+
draw(page),
|
|
6248
|
+
new Promise((resolve) => setTimeout(() => resolve(null), TIMEOUT_MS))
|
|
6249
|
+
]);
|
|
6250
|
+
if (blob === null) return null;
|
|
6251
|
+
return new File([blob], SCREENSHOT_NAME, { type: TYPE });
|
|
6252
|
+
} catch (caught) {
|
|
6253
|
+
console.warn("Median: taking a screenshot for this report failed", caught);
|
|
6254
|
+
return null;
|
|
6255
|
+
}
|
|
6256
|
+
}
|
|
6257
|
+
async function draw(page) {
|
|
6258
|
+
const { domToBlob } = await import("./dist-VC6ZVTA2.js");
|
|
6259
|
+
const width = page.clientWidth || window.innerWidth;
|
|
6260
|
+
const height = page.clientHeight || window.innerHeight;
|
|
6261
|
+
const unpin = pinFixed();
|
|
6262
|
+
try {
|
|
6263
|
+
return await domToBlob(page, {
|
|
6264
|
+
width,
|
|
6265
|
+
height,
|
|
6266
|
+
// Their view, not the whole document: the page is drawn in full and
|
|
6267
|
+
// the part they are looking at is what the frame is put around. A page
|
|
6268
|
+
// held still by `usePageLock` has already been scrolled to nothing,
|
|
6269
|
+
// and is shifted by nothing here.
|
|
6270
|
+
style: {
|
|
6271
|
+
transform: `translate(${-window.scrollX}px, ${-window.scrollY}px)`,
|
|
6272
|
+
transformOrigin: "top left"
|
|
6273
|
+
},
|
|
6274
|
+
scale: Math.min(1, MAX_WIDTH / Math.max(width, 1)),
|
|
6275
|
+
type: TYPE,
|
|
6276
|
+
quality: QUALITY,
|
|
6277
|
+
// JPEG has no transparency, so anything clear would come out black.
|
|
6278
|
+
backgroundColor: pageBackground(),
|
|
6279
|
+
filter: notOurs,
|
|
6280
|
+
onCloneNode: placePinned,
|
|
6281
|
+
timeout: TIMEOUT_MS,
|
|
6282
|
+
features: { copyScrollbar: false }
|
|
6283
|
+
});
|
|
6284
|
+
} finally {
|
|
6285
|
+
unpin();
|
|
6286
|
+
}
|
|
6287
|
+
}
|
|
6288
|
+
function pinFixed() {
|
|
6289
|
+
const pinned = [];
|
|
6290
|
+
for (const element of document.body.querySelectorAll("*")) {
|
|
6291
|
+
if (window.getComputedStyle(element).position !== "fixed") continue;
|
|
6292
|
+
const box = element.getBoundingClientRect();
|
|
6293
|
+
if (box.width === 0 || box.height === 0) continue;
|
|
6294
|
+
element.setAttribute(
|
|
6295
|
+
PIN_ATTRIBUTE,
|
|
6296
|
+
[box.left, box.top, box.width, box.height].join(",")
|
|
6297
|
+
);
|
|
6298
|
+
pinned.push(element);
|
|
6299
|
+
}
|
|
6300
|
+
return () => {
|
|
6301
|
+
for (const element of pinned) element.removeAttribute(PIN_ATTRIBUTE);
|
|
6302
|
+
};
|
|
6303
|
+
}
|
|
6304
|
+
function placePinned(clone) {
|
|
6305
|
+
if (!(clone instanceof Element)) return;
|
|
6306
|
+
for (const element of clone.querySelectorAll(`[${PIN_ATTRIBUTE}]`)) {
|
|
6307
|
+
const [left, top, width, height] = (element.getAttribute(PIN_ATTRIBUTE) ?? "").split(",").map(Number);
|
|
6308
|
+
element.removeAttribute(PIN_ATTRIBUTE);
|
|
6309
|
+
if (!(element instanceof HTMLElement) || Number.isNaN(top)) continue;
|
|
6310
|
+
element.style.setProperty("left", `${left + window.scrollX}px`, "important");
|
|
6311
|
+
element.style.setProperty("top", `${top + window.scrollY}px`, "important");
|
|
6312
|
+
element.style.setProperty("right", "auto", "important");
|
|
6313
|
+
element.style.setProperty("bottom", "auto", "important");
|
|
6314
|
+
element.style.setProperty("width", `${width}px`, "important");
|
|
6315
|
+
element.style.setProperty("height", `${height}px`, "important");
|
|
6316
|
+
element.style.setProperty("margin", "0", "important");
|
|
6317
|
+
}
|
|
6318
|
+
}
|
|
6319
|
+
function notOurs(node) {
|
|
6320
|
+
return !(node instanceof Element && node.hasAttribute("data-median-widget"));
|
|
6321
|
+
}
|
|
6322
|
+
function pageBackground() {
|
|
6323
|
+
for (const element of [document.body, document.documentElement]) {
|
|
6324
|
+
if (element === null) continue;
|
|
6325
|
+
const color = window.getComputedStyle(element).backgroundColor;
|
|
6326
|
+
if (color && !isClear(color)) return color;
|
|
6327
|
+
}
|
|
6328
|
+
return "#ffffff";
|
|
6329
|
+
}
|
|
6330
|
+
function isClear(color) {
|
|
6331
|
+
const clear = color.replace(/\s/g, "");
|
|
6332
|
+
return clear === "transparent" || clear === "rgba(0,0,0,0)";
|
|
6333
|
+
}
|
|
6334
|
+
|
|
6054
6335
|
// ../../apps/web/src/components/support-widget/sdk/session.ts
|
|
6055
6336
|
var STORAGE_PREFIX = "median:session:";
|
|
6056
6337
|
var inMemorySessions = /* @__PURE__ */ new Map();
|
|
6057
6338
|
var listeners4 = /* @__PURE__ */ new Set();
|
|
6339
|
+
var resetCount = 0;
|
|
6340
|
+
function getResetCount() {
|
|
6341
|
+
return resetCount;
|
|
6342
|
+
}
|
|
6058
6343
|
function subscribeSession(listener) {
|
|
6059
6344
|
listeners4.add(listener);
|
|
6060
6345
|
return () => {
|
|
@@ -6077,6 +6362,7 @@ function getOrCreateSessionId(apiKey) {
|
|
|
6077
6362
|
}
|
|
6078
6363
|
}
|
|
6079
6364
|
function resetSessions() {
|
|
6365
|
+
resetCount += 1;
|
|
6080
6366
|
inMemorySessions.clear();
|
|
6081
6367
|
if (typeof window !== "undefined") {
|
|
6082
6368
|
try {
|
|
@@ -6093,19 +6379,32 @@ function resetSessions() {
|
|
|
6093
6379
|
}
|
|
6094
6380
|
|
|
6095
6381
|
// ../../apps/web/src/components/support-widget/sdk/use-median-thread.ts
|
|
6096
|
-
import { useMutation, useQuery } from "convex/react";
|
|
6382
|
+
import { useMutation as useMutation2, useQuery } from "convex/react";
|
|
6383
|
+
|
|
6384
|
+
// ../../apps/web/src/components/support-widget/sdk/use-widget-mutation.ts
|
|
6385
|
+
import { useMutation } from "convex/react";
|
|
6386
|
+
import { useCallback as useCallback10 } from "react";
|
|
6387
|
+
function useWidgetMutation(reference) {
|
|
6388
|
+
const mutation = useMutation(reference);
|
|
6389
|
+
return useCallback10(
|
|
6390
|
+
async (...args) => unwrapMutationResult(await mutation(...args)),
|
|
6391
|
+
[mutation]
|
|
6392
|
+
);
|
|
6393
|
+
}
|
|
6394
|
+
|
|
6395
|
+
// ../../apps/web/src/components/support-widget/sdk/use-median-thread.ts
|
|
6097
6396
|
import {
|
|
6098
|
-
useCallback as
|
|
6099
|
-
useEffect as
|
|
6397
|
+
useCallback as useCallback12,
|
|
6398
|
+
useEffect as useEffect18,
|
|
6100
6399
|
useMemo as useMemo2,
|
|
6101
|
-
useState as
|
|
6400
|
+
useState as useState18,
|
|
6102
6401
|
useSyncExternalStore as useSyncExternalStore9
|
|
6103
6402
|
} from "react";
|
|
6104
6403
|
|
|
6105
6404
|
// ../../apps/web/src/hooks/use-now.ts
|
|
6106
|
-
import { useEffect as useEffect16, useState as
|
|
6405
|
+
import { useEffect as useEffect16, useState as useState17 } from "react";
|
|
6107
6406
|
function useNow(intervalMs = 3e4) {
|
|
6108
|
-
const [now, setNow] =
|
|
6407
|
+
const [now, setNow] = useState17(() => Date.now());
|
|
6109
6408
|
useEffect16(() => {
|
|
6110
6409
|
const timer = setInterval(() => setNow(Date.now()), intervalMs);
|
|
6111
6410
|
return () => clearInterval(timer);
|
|
@@ -6114,16 +6413,21 @@ function useNow(intervalMs = 3e4) {
|
|
|
6114
6413
|
}
|
|
6115
6414
|
|
|
6116
6415
|
// ../../apps/web/src/lib/errors.ts
|
|
6117
|
-
import { ConvexError } from "convex/values";
|
|
6416
|
+
import { ConvexError as ConvexError2 } from "convex/values";
|
|
6118
6417
|
var FALLBACK = "Something went wrong on our end. Please try again.";
|
|
6418
|
+
var OUT_OF_DATE = "This page is out of date. Refresh to get the latest version.";
|
|
6419
|
+
function isMissingFunction(error) {
|
|
6420
|
+
return error instanceof Error && error.message.includes("Could not find public function");
|
|
6421
|
+
}
|
|
6119
6422
|
function isErrorPayload(data) {
|
|
6120
6423
|
return typeof data === "object" && data !== null && "message" in data && typeof data.message === "string";
|
|
6121
6424
|
}
|
|
6122
6425
|
function errorMessage(error) {
|
|
6123
|
-
if (error instanceof
|
|
6426
|
+
if (error instanceof ConvexError2) {
|
|
6124
6427
|
if (typeof error.data === "string") return error.data;
|
|
6125
6428
|
if (isErrorPayload(error.data)) return error.data.message;
|
|
6126
6429
|
}
|
|
6430
|
+
if (isMissingFunction(error)) return OUT_OF_DATE;
|
|
6127
6431
|
return FALLBACK;
|
|
6128
6432
|
}
|
|
6129
6433
|
|
|
@@ -6161,33 +6465,6 @@ function isNewDay(previous, next) {
|
|
|
6161
6465
|
return startOfDay(previous) !== startOfDay(next);
|
|
6162
6466
|
}
|
|
6163
6467
|
|
|
6164
|
-
// ../../apps/web/src/lib/upload.ts
|
|
6165
|
-
async function uploadFile(getUploadUrl, file) {
|
|
6166
|
-
const url = await getUploadUrl();
|
|
6167
|
-
const response = await fetch(url, {
|
|
6168
|
-
method: "POST",
|
|
6169
|
-
headers: { "Content-Type": file.type || "application/octet-stream" },
|
|
6170
|
-
body: file
|
|
6171
|
-
});
|
|
6172
|
-
if (!response.ok) {
|
|
6173
|
-
throw new Error(`Uploading ${file.name} failed with ${response.status}`);
|
|
6174
|
-
}
|
|
6175
|
-
const { storageId } = await response.json();
|
|
6176
|
-
return storageId;
|
|
6177
|
-
}
|
|
6178
|
-
async function uploadAttachments(getUploadUrl, files) {
|
|
6179
|
-
const attachments = [];
|
|
6180
|
-
for (const file of files) {
|
|
6181
|
-
attachments.push({
|
|
6182
|
-
storageId: await uploadFile(getUploadUrl, file),
|
|
6183
|
-
name: file.name,
|
|
6184
|
-
size: file.size,
|
|
6185
|
-
type: file.type || "application/octet-stream"
|
|
6186
|
-
});
|
|
6187
|
-
}
|
|
6188
|
-
return attachments;
|
|
6189
|
-
}
|
|
6190
|
-
|
|
6191
6468
|
// ../../apps/web/src/components/support-widget/sdk/rating-skips.ts
|
|
6192
6469
|
var STORAGE_PREFIX2 = "median:rating-skips:";
|
|
6193
6470
|
var MAX_REMEMBERED = 20;
|
|
@@ -6222,45 +6499,56 @@ function writeSkippedRating(apiKey, conversationId) {
|
|
|
6222
6499
|
}
|
|
6223
6500
|
}
|
|
6224
6501
|
|
|
6225
|
-
// ../../apps/web/src/components/support-widget/sdk/
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
return `median:${name}:${apiKey}`;
|
|
6229
|
-
}
|
|
6230
|
-
function readStamp(name, apiKey) {
|
|
6231
|
-
if (typeof window === "undefined") return 0;
|
|
6232
|
-
const key = keyOf(name, apiKey);
|
|
6233
|
-
try {
|
|
6234
|
-
const stored = window.localStorage.getItem(key);
|
|
6235
|
-
const at2 = stored === null ? Number.NaN : Number(stored);
|
|
6236
|
-
return Number.isFinite(at2) ? at2 : 0;
|
|
6237
|
-
} catch {
|
|
6238
|
-
return inMemory2.get(key) ?? 0;
|
|
6239
|
-
}
|
|
6502
|
+
// ../../apps/web/src/components/support-widget/sdk/read-state.ts
|
|
6503
|
+
function isUnreadReply(message) {
|
|
6504
|
+
return message.sender === "agent" && !message.pending && !message.isRead;
|
|
6240
6505
|
}
|
|
6241
|
-
function
|
|
6242
|
-
|
|
6243
|
-
const
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6506
|
+
function widgetReadReceipts(messages, now) {
|
|
6507
|
+
const receipts = /* @__PURE__ */ new Map();
|
|
6508
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
6509
|
+
for (const message of messages) {
|
|
6510
|
+
const { conversationId } = message;
|
|
6511
|
+
if (!receipts.has(conversationId)) {
|
|
6512
|
+
receipts.set(conversationId, { conversationId });
|
|
6513
|
+
}
|
|
6514
|
+
if (blocked.has(conversationId)) continue;
|
|
6515
|
+
if (message.pending) {
|
|
6516
|
+
if (message.typingAt === null || now - message.typingAt <= TYPING_TTL_MS) {
|
|
6517
|
+
blocked.add(conversationId);
|
|
6518
|
+
}
|
|
6519
|
+
continue;
|
|
6520
|
+
}
|
|
6521
|
+
if (message.sender === "agent" && (message.body.trim() || message.attachments.length > 0)) {
|
|
6522
|
+
receipts.set(conversationId, { conversationId, messageId: message._id });
|
|
6523
|
+
}
|
|
6248
6524
|
}
|
|
6525
|
+
return [...receipts.values()];
|
|
6249
6526
|
}
|
|
6250
6527
|
|
|
6251
|
-
// ../../apps/web/src/components/support-widget/sdk/
|
|
6252
|
-
|
|
6253
|
-
function
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6528
|
+
// ../../apps/web/src/components/support-widget/sdk/use-screenshot-ask.ts
|
|
6529
|
+
import { useEffect as useEffect17, useRef as useRef18 } from "react";
|
|
6530
|
+
function useScreenshotAsk({
|
|
6531
|
+
ask,
|
|
6532
|
+
enabled: enabled2,
|
|
6533
|
+
answer
|
|
6534
|
+
}) {
|
|
6535
|
+
const answered = useRef18(/* @__PURE__ */ new Set());
|
|
6536
|
+
useEffect17(() => {
|
|
6537
|
+
if (ask === null || answered.current.has(ask.key)) return;
|
|
6538
|
+
answered.current.add(ask.key);
|
|
6539
|
+
void (async () => {
|
|
6540
|
+
const shot = enabled2 ? await capturePage() : null;
|
|
6541
|
+
await answer(ask.key, shot);
|
|
6542
|
+
})().catch((caught) => {
|
|
6543
|
+
console.warn("Median: answering the agent's request for a picture failed", caught);
|
|
6544
|
+
});
|
|
6545
|
+
}, [ask, enabled2, answer]);
|
|
6258
6546
|
}
|
|
6259
6547
|
|
|
6260
6548
|
// ../../apps/web/src/components/support-widget/sdk/visitor-email.ts
|
|
6261
|
-
import { useCallback as
|
|
6549
|
+
import { useCallback as useCallback11, useSyncExternalStore as useSyncExternalStore8 } from "react";
|
|
6262
6550
|
var STORAGE_PREFIX3 = "median:email:";
|
|
6263
|
-
var
|
|
6551
|
+
var inMemory2 = /* @__PURE__ */ new Map();
|
|
6264
6552
|
var listeners5 = /* @__PURE__ */ new Set();
|
|
6265
6553
|
function subscribeVisitorEmail(listener) {
|
|
6266
6554
|
listeners5.add(listener);
|
|
@@ -6274,11 +6562,11 @@ function readVisitorEmail(apiKey) {
|
|
|
6274
6562
|
const stored = window.localStorage.getItem(`${STORAGE_PREFIX3}${apiKey}`);
|
|
6275
6563
|
return stored && stored.length > 0 ? stored : null;
|
|
6276
6564
|
} catch {
|
|
6277
|
-
return
|
|
6565
|
+
return inMemory2.get(apiKey) ?? null;
|
|
6278
6566
|
}
|
|
6279
6567
|
}
|
|
6280
6568
|
function writeVisitorEmail(apiKey, email) {
|
|
6281
|
-
|
|
6569
|
+
inMemory2.set(apiKey, email);
|
|
6282
6570
|
try {
|
|
6283
6571
|
window.localStorage.setItem(`${STORAGE_PREFIX3}${apiKey}`, email);
|
|
6284
6572
|
} catch {
|
|
@@ -6286,7 +6574,7 @@ function writeVisitorEmail(apiKey, email) {
|
|
|
6286
6574
|
for (const listener of listeners5) listener();
|
|
6287
6575
|
}
|
|
6288
6576
|
function resetVisitorEmails() {
|
|
6289
|
-
|
|
6577
|
+
inMemory2.clear();
|
|
6290
6578
|
if (typeof window !== "undefined") {
|
|
6291
6579
|
try {
|
|
6292
6580
|
const stale = [];
|
|
@@ -6303,10 +6591,10 @@ function resetVisitorEmails() {
|
|
|
6303
6591
|
function useVisitorEmail(apiKey) {
|
|
6304
6592
|
const email = useSyncExternalStore8(
|
|
6305
6593
|
subscribeVisitorEmail,
|
|
6306
|
-
|
|
6594
|
+
useCallback11(() => readVisitorEmail(apiKey), [apiKey]),
|
|
6307
6595
|
() => null
|
|
6308
6596
|
);
|
|
6309
|
-
const setEmail =
|
|
6597
|
+
const setEmail = useCallback11(
|
|
6310
6598
|
(next) => writeVisitorEmail(apiKey, next),
|
|
6311
6599
|
[apiKey]
|
|
6312
6600
|
);
|
|
@@ -6333,10 +6621,20 @@ var IDENTITY_COMPLAINTS = {
|
|
|
6333
6621
|
unverified: "Median: the user hash passed to <MedianSupport> did not match. Sign the same string you pass as `user.id` with the Median key that produced this widget id. Until it matches, this visitor gets a conversation of their own on every device.",
|
|
6334
6622
|
unconfigured: "Median: a user hash was passed to <MedianSupport>, but its widget id and hash came from different Median keys. Derive both from the same key."
|
|
6335
6623
|
};
|
|
6336
|
-
function useMedianThread(
|
|
6624
|
+
function useMedianThread({
|
|
6625
|
+
apiKey,
|
|
6626
|
+
user,
|
|
6627
|
+
telemetry = true,
|
|
6628
|
+
screenshot = true,
|
|
6629
|
+
isLocked = false,
|
|
6630
|
+
diagnostics,
|
|
6631
|
+
appState,
|
|
6632
|
+
requireEmail = true,
|
|
6633
|
+
messagePreview = true
|
|
6634
|
+
}) {
|
|
6337
6635
|
const sessionId = useSyncExternalStore9(
|
|
6338
6636
|
subscribeSession,
|
|
6339
|
-
|
|
6637
|
+
useCallback12(() => getOrCreateSessionId(apiKey), [apiKey]),
|
|
6340
6638
|
() => null
|
|
6341
6639
|
);
|
|
6342
6640
|
const config = useQuery(api.widget.config, { apiKey });
|
|
@@ -6346,18 +6644,45 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6346
6644
|
api.widget.thread,
|
|
6347
6645
|
sessionId === null || isLocked ? "skip" : { apiKey, sessionId }
|
|
6348
6646
|
);
|
|
6349
|
-
const send =
|
|
6350
|
-
const sendTyping =
|
|
6351
|
-
const sendPresence =
|
|
6352
|
-
const rateConversation =
|
|
6353
|
-
const identify =
|
|
6354
|
-
const generateUploadUrl =
|
|
6647
|
+
const send = useWidgetMutation(api.widget.sendV2);
|
|
6648
|
+
const sendTyping = useMutation2(api.widget.setTyping);
|
|
6649
|
+
const sendPresence = useMutation2(api.widget.presence);
|
|
6650
|
+
const rateConversation = useWidgetMutation(api.widget.rateV2);
|
|
6651
|
+
const identify = useWidgetMutation(api.widget.identifyV2);
|
|
6652
|
+
const generateUploadUrl = useWidgetMutation(api.widget.generateUploadUrlV2);
|
|
6653
|
+
const answerScreenshot = useWidgetMutation(api.widget.answerScreenshotV2);
|
|
6654
|
+
const answerAsk = useCallback12(
|
|
6655
|
+
async (key, shot) => {
|
|
6656
|
+
if (sessionId === null) return;
|
|
6657
|
+
let attachment;
|
|
6658
|
+
if (shot !== null) {
|
|
6659
|
+
try {
|
|
6660
|
+
[attachment] = await uploadAttachments(
|
|
6661
|
+
() => generateUploadUrl({ apiKey, sessionId }),
|
|
6662
|
+
[shot]
|
|
6663
|
+
);
|
|
6664
|
+
} catch (caught) {
|
|
6665
|
+
console.warn(
|
|
6666
|
+
"Median: the picture the agent asked for could not be uploaded",
|
|
6667
|
+
caught
|
|
6668
|
+
);
|
|
6669
|
+
}
|
|
6670
|
+
}
|
|
6671
|
+
await answerScreenshot({
|
|
6672
|
+
apiKey,
|
|
6673
|
+
sessionId,
|
|
6674
|
+
key,
|
|
6675
|
+
...attachment === void 0 ? {} : { attachment }
|
|
6676
|
+
});
|
|
6677
|
+
},
|
|
6678
|
+
[apiKey, sessionId, generateUploadUrl, answerScreenshot]
|
|
6679
|
+
);
|
|
6355
6680
|
const identityKey = user ? JSON.stringify(user) : null;
|
|
6356
6681
|
const identity = useMemo2(
|
|
6357
6682
|
() => identityKey === null ? null : JSON.parse(identityKey),
|
|
6358
6683
|
[identityKey]
|
|
6359
6684
|
);
|
|
6360
|
-
|
|
6685
|
+
useEffect18(() => {
|
|
6361
6686
|
if (sessionId === null || identity === null) return;
|
|
6362
6687
|
const { facts, claim } = splitIdentity(identity);
|
|
6363
6688
|
identify({
|
|
@@ -6376,8 +6701,8 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6376
6701
|
) ?? false;
|
|
6377
6702
|
const now = useNow(hasLiveDots ? 1e3 : 6e4);
|
|
6378
6703
|
const takeDiagnostics = useDiagnostics(diagnostics, appState);
|
|
6379
|
-
const [isSending, setIsSending] =
|
|
6380
|
-
const [sendError, setSendError] =
|
|
6704
|
+
const [isSending, setIsSending] = useState18(false);
|
|
6705
|
+
const [sendError, setSendError] = useState18(null);
|
|
6381
6706
|
const agent = useMemo2(
|
|
6382
6707
|
() => config === void 0 ? null : {
|
|
6383
6708
|
id: "median-agent",
|
|
@@ -6450,17 +6775,16 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6450
6775
|
team: [...[...humans.values()].slice(-2), agent]
|
|
6451
6776
|
};
|
|
6452
6777
|
}, [config, agent, messages]);
|
|
6453
|
-
const
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
)
|
|
6458
|
-
|
|
6459
|
-
);
|
|
6778
|
+
const unread = useMemo2(() => {
|
|
6779
|
+
const unreadIds = new Set(
|
|
6780
|
+
thread?.messages.filter(isUnreadReply).map((message) => message._id)
|
|
6781
|
+
);
|
|
6782
|
+
return messages.filter((message) => unreadIds.has(message.id));
|
|
6783
|
+
}, [messages, thread]);
|
|
6460
6784
|
const unreadCount = unread.length;
|
|
6461
6785
|
const latestUnread = messagePreview && (config?.messagePreview ?? true) ? unread[unread.length - 1] ?? null : null;
|
|
6462
|
-
const [picked, setPicked] =
|
|
6463
|
-
const [skipped, setSkipped] =
|
|
6786
|
+
const [picked, setPicked] = useState18(null);
|
|
6787
|
+
const [skipped, setSkipped] = useState18(
|
|
6464
6788
|
() => readSkippedRatings(apiKey)
|
|
6465
6789
|
);
|
|
6466
6790
|
const conversationId = thread?.conversationId ?? null;
|
|
@@ -6484,15 +6808,6 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6484
6808
|
setSkipped((current2) => new Set(current2).add(conversationId));
|
|
6485
6809
|
}
|
|
6486
6810
|
} : null;
|
|
6487
|
-
const markSeen = useCallback11(() => {
|
|
6488
|
-
const newest = messages.reduce(
|
|
6489
|
-
(latest, message) => Math.max(latest, message.sentAt ?? 0),
|
|
6490
|
-
0
|
|
6491
|
-
);
|
|
6492
|
-
if (newest <= lastSeenAt) return;
|
|
6493
|
-
writeLastSeenAt(apiKey, newest);
|
|
6494
|
-
setLastSeenAt(newest);
|
|
6495
|
-
}, [apiKey, messages, lastSeenAt]);
|
|
6496
6811
|
async function handleSend(body, files) {
|
|
6497
6812
|
if (sessionId === null || isSending) return;
|
|
6498
6813
|
setSendError(null);
|
|
@@ -6534,12 +6849,29 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6534
6849
|
sendTyping({ apiKey, sessionId, isTyping }).catch(() => {
|
|
6535
6850
|
});
|
|
6536
6851
|
}
|
|
6537
|
-
const
|
|
6852
|
+
const readsKey = JSON.stringify(
|
|
6853
|
+
widgetReadReceipts(thread?.messages ?? [], now)
|
|
6854
|
+
);
|
|
6855
|
+
const reads = useMemo2(
|
|
6856
|
+
() => JSON.parse(readsKey),
|
|
6857
|
+
[readsKey]
|
|
6858
|
+
);
|
|
6859
|
+
const reportPresence = useCallback12(() => {
|
|
6538
6860
|
if (sessionId === null || isLocked) return;
|
|
6539
|
-
sendPresence({
|
|
6861
|
+
sendPresence({
|
|
6862
|
+
apiKey,
|
|
6863
|
+
sessionId,
|
|
6864
|
+
reads
|
|
6865
|
+
}).catch((caught) => {
|
|
6866
|
+
console.warn("Median: support read status could not be synced", caught);
|
|
6540
6867
|
});
|
|
6541
|
-
}, [apiKey, sessionId, isLocked, sendPresence]);
|
|
6868
|
+
}, [apiKey, sessionId, isLocked, sendPresence, reads]);
|
|
6542
6869
|
const ask = thread?.direction ?? null;
|
|
6870
|
+
useScreenshotAsk({
|
|
6871
|
+
ask: thread?.screenshotAsk ?? null,
|
|
6872
|
+
enabled: screenshot,
|
|
6873
|
+
answer: answerAsk
|
|
6874
|
+
});
|
|
6543
6875
|
return {
|
|
6544
6876
|
presence,
|
|
6545
6877
|
messages,
|
|
@@ -6574,7 +6906,6 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6574
6906
|
unreadCount,
|
|
6575
6907
|
/** The newest of those, for the card on the closed button. */
|
|
6576
6908
|
latestUnread,
|
|
6577
|
-
markSeen,
|
|
6578
6909
|
/** Say the panel is on screen, so replies are not also emailed. */
|
|
6579
6910
|
reportPresence,
|
|
6580
6911
|
sendError,
|
|
@@ -6649,17 +6980,19 @@ async function reportError(error, options = {}) {
|
|
|
6649
6980
|
const diagnostics = snapshotNow({ ...factsOf(crash), ...options.state });
|
|
6650
6981
|
try {
|
|
6651
6982
|
client ??= new ConvexHttpClient(MEDIAN_DEPLOYMENT_URL);
|
|
6652
|
-
const
|
|
6983
|
+
const images = options.screenshot === false ? [] : await screenshotOf(client, apiKey, sessionId);
|
|
6984
|
+
const outcome = await client.mutation(api.feedback.reportErrorV2, {
|
|
6653
6985
|
apiKey,
|
|
6654
6986
|
sessionId,
|
|
6655
6987
|
error: crash,
|
|
6988
|
+
...images.length > 0 ? { images } : {},
|
|
6656
6989
|
...user ? { user: facts } : {},
|
|
6657
6990
|
...claim ? { identity: claim } : {},
|
|
6658
6991
|
...context ? { context } : {},
|
|
6659
6992
|
...page ? { page } : {},
|
|
6660
6993
|
...diagnostics ? { diagnostics } : {},
|
|
6661
6994
|
...custom ? { customData: custom } : {}
|
|
6662
|
-
});
|
|
6995
|
+
}).then(unwrapMutationResult);
|
|
6663
6996
|
if (outcome === "off") {
|
|
6664
6997
|
if (custom) restoreCustomData(custom);
|
|
6665
6998
|
return { reported: false, reason: REASONS.off };
|
|
@@ -6671,6 +7004,22 @@ async function reportError(error, options = {}) {
|
|
|
6671
7004
|
return { reported: false, reason: REASONS.failed };
|
|
6672
7005
|
}
|
|
6673
7006
|
}
|
|
7007
|
+
async function screenshotOf(client3, apiKey, sessionId) {
|
|
7008
|
+
try {
|
|
7009
|
+
const shot = await capturePage();
|
|
7010
|
+
if (shot === null) return [];
|
|
7011
|
+
return await uploadAttachments(
|
|
7012
|
+
() => client3.mutation(api.widget.generateUploadUrlV2, { apiKey, sessionId }).then(unwrapMutationResult),
|
|
7013
|
+
[shot]
|
|
7014
|
+
);
|
|
7015
|
+
} catch (caught) {
|
|
7016
|
+
console.warn(
|
|
7017
|
+
"Median: the crash report's screenshot could not be sent",
|
|
7018
|
+
caught
|
|
7019
|
+
);
|
|
7020
|
+
return [];
|
|
7021
|
+
}
|
|
7022
|
+
}
|
|
6674
7023
|
function useCanReportError() {
|
|
6675
7024
|
const isInstalled = useSyncExternalStore10(
|
|
6676
7025
|
subscribeInstall,
|
|
@@ -6683,6 +7032,77 @@ function useCanReportError() {
|
|
|
6683
7032
|
return isInstalled && Boolean(MEDIAN_DEPLOYMENT_URL);
|
|
6684
7033
|
}
|
|
6685
7034
|
|
|
7035
|
+
// ../../apps/web/src/components/support-widget/sdk/signed-out.ts
|
|
7036
|
+
import { useEffect as useEffect19, useRef as useRef19, useState as useState19, useSyncExternalStore as useSyncExternalStore11 } from "react";
|
|
7037
|
+
var held = /* @__PURE__ */ new Map();
|
|
7038
|
+
var signedOut = /* @__PURE__ */ new Set();
|
|
7039
|
+
var RELEASE_AFTER_MS = 2e3;
|
|
7040
|
+
function signOutHeldUsers() {
|
|
7041
|
+
for (const person of held.values()) signedOut.add(person);
|
|
7042
|
+
}
|
|
7043
|
+
function releaseLater(person) {
|
|
7044
|
+
if (!signedOut.has(person)) return;
|
|
7045
|
+
setTimeout(() => {
|
|
7046
|
+
for (const other of held.values()) if (other === person) return;
|
|
7047
|
+
signedOut.delete(person);
|
|
7048
|
+
}, RELEASE_AFTER_MS);
|
|
7049
|
+
}
|
|
7050
|
+
function personKey(user) {
|
|
7051
|
+
if (user === void 0) return null;
|
|
7052
|
+
return user.id && user.hash ? `id:${user.id}` : JSON.stringify(user);
|
|
7053
|
+
}
|
|
7054
|
+
function useSignedInUser(user) {
|
|
7055
|
+
const person = personKey(user);
|
|
7056
|
+
useSyncExternalStore11(subscribeSession, getResetCount, () => 0);
|
|
7057
|
+
const [token] = useState19(() => Symbol("median-panel"));
|
|
7058
|
+
const previous = useRef19(null);
|
|
7059
|
+
useEffect19(() => {
|
|
7060
|
+
if (previous.current !== null && previous.current !== person) {
|
|
7061
|
+
signedOut.delete(previous.current);
|
|
7062
|
+
}
|
|
7063
|
+
previous.current = person;
|
|
7064
|
+
if (person === null) held.delete(token);
|
|
7065
|
+
else held.set(token, person);
|
|
7066
|
+
}, [person, token]);
|
|
7067
|
+
useEffect19(
|
|
7068
|
+
() => () => {
|
|
7069
|
+
const person2 = held.get(token);
|
|
7070
|
+
held.delete(token);
|
|
7071
|
+
if (person2 !== void 0) releaseLater(person2);
|
|
7072
|
+
},
|
|
7073
|
+
[token]
|
|
7074
|
+
);
|
|
7075
|
+
return person !== null && signedOut.has(person) ? void 0 : user;
|
|
7076
|
+
}
|
|
7077
|
+
|
|
7078
|
+
// ../../apps/web/src/components/support-widget/sdk/unread-store.ts
|
|
7079
|
+
import { useSyncExternalStore as useSyncExternalStore12 } from "react";
|
|
7080
|
+
var count = 0;
|
|
7081
|
+
var listeners6 = /* @__PURE__ */ new Set();
|
|
7082
|
+
var unreadStore = {
|
|
7083
|
+
subscribe(listener) {
|
|
7084
|
+
listeners6.add(listener);
|
|
7085
|
+
return () => {
|
|
7086
|
+
listeners6.delete(listener);
|
|
7087
|
+
};
|
|
7088
|
+
},
|
|
7089
|
+
read: () => count,
|
|
7090
|
+
/** The server has no thread to count, and neither does the first paint. */
|
|
7091
|
+
readServer: () => 0,
|
|
7092
|
+
set(next) {
|
|
7093
|
+
if (count === next) return;
|
|
7094
|
+
count = next;
|
|
7095
|
+
for (const listener of listeners6) listener();
|
|
7096
|
+
}
|
|
7097
|
+
};
|
|
7098
|
+
function useUnreadCount() {
|
|
7099
|
+
return useSyncExternalStore12(
|
|
7100
|
+
unreadStore.subscribe,
|
|
7101
|
+
unreadStore.read,
|
|
7102
|
+
unreadStore.readServer
|
|
7103
|
+
);
|
|
7104
|
+
}
|
|
7105
|
+
|
|
6686
7106
|
// ../../apps/web/src/components/support-widget/sdk/control.ts
|
|
6687
7107
|
var store = createOpenStore("MedianSupport");
|
|
6688
7108
|
var medianSupport = {
|
|
@@ -6690,6 +7110,10 @@ var medianSupport = {
|
|
|
6690
7110
|
get isOpen() {
|
|
6691
7111
|
return store.readEffective();
|
|
6692
7112
|
},
|
|
7113
|
+
/** Replies the visitor has not read. Zero while nothing is mounted. */
|
|
7114
|
+
get unreadCount() {
|
|
7115
|
+
return unreadStore.read();
|
|
7116
|
+
},
|
|
6693
7117
|
open() {
|
|
6694
7118
|
store.request(true);
|
|
6695
7119
|
store.warnIfNothingIsMounted("the widget was asked to open");
|
|
@@ -6717,7 +7141,13 @@ var medianSupport = {
|
|
|
6717
7141
|
}
|
|
6718
7142
|
return;
|
|
6719
7143
|
}
|
|
6720
|
-
|
|
7144
|
+
if (!isDevelopment || hasCustomDataSender()) return;
|
|
7145
|
+
setTimeout(() => {
|
|
7146
|
+
if (hasCustomDataSender()) return;
|
|
7147
|
+
console.warn(
|
|
7148
|
+
"Median: data was attached, but no <MedianSupport>, <MedianFeedback> or contact form is on the page to send it. It goes with the next message, note, sendMedianContact() or reportError() call."
|
|
7149
|
+
);
|
|
7150
|
+
}, 1e3);
|
|
6721
7151
|
},
|
|
6722
7152
|
/**
|
|
6723
7153
|
* File the crash your error screen is showing, with everything the browser
|
|
@@ -6736,20 +7166,27 @@ var medianSupport = {
|
|
|
6736
7166
|
* Forget this browser's conversation, so the next one starts fresh and
|
|
6737
7167
|
* anonymous. Call it when your user signs out: whoever sits down next
|
|
6738
7168
|
* should not find somebody else's thread waiting.
|
|
7169
|
+
*
|
|
7170
|
+
* The user the widget holds right now is signed out with it, even if your
|
|
7171
|
+
* own state still passes them for a moment, and an identity route is read
|
|
7172
|
+
* again.
|
|
6739
7173
|
*/
|
|
6740
7174
|
reset() {
|
|
7175
|
+
signOutHeldUsers();
|
|
6741
7176
|
resetSessions();
|
|
6742
7177
|
resetVisitorEmails();
|
|
6743
7178
|
}
|
|
6744
7179
|
};
|
|
6745
7180
|
function useMedianSupport() {
|
|
6746
|
-
const isOpen =
|
|
7181
|
+
const isOpen = useSyncExternalStore13(
|
|
6747
7182
|
store.subscribe,
|
|
6748
7183
|
store.readEffective,
|
|
6749
7184
|
store.readServerEffective
|
|
6750
7185
|
);
|
|
7186
|
+
const unreadCount = useUnreadCount();
|
|
6751
7187
|
return {
|
|
6752
7188
|
isOpen,
|
|
7189
|
+
unreadCount,
|
|
6753
7190
|
open: medianSupport.open,
|
|
6754
7191
|
close: medianSupport.close,
|
|
6755
7192
|
toggle: medianSupport.toggle,
|
|
@@ -6761,18 +7198,18 @@ function useMedianSupport() {
|
|
|
6761
7198
|
function useMedianOpenState(options) {
|
|
6762
7199
|
return useOpenState(store, options);
|
|
6763
7200
|
}
|
|
6764
|
-
function useRegisterMedianSupport() {
|
|
6765
|
-
useRegister(store);
|
|
7201
|
+
function useRegisterMedianSupport(name = "MedianSupport") {
|
|
7202
|
+
useRegister(store, name);
|
|
6766
7203
|
}
|
|
6767
7204
|
|
|
6768
7205
|
// ../../apps/web/src/components/support-widget/sdk/error-boundary.tsx
|
|
6769
|
-
import { ConvexError as
|
|
7206
|
+
import { ConvexError as ConvexError3 } from "convex/values";
|
|
6770
7207
|
import { Component } from "react";
|
|
6771
|
-
function adviceFor(error) {
|
|
6772
|
-
if (error instanceof
|
|
6773
|
-
return
|
|
7208
|
+
function adviceFor(error, component) {
|
|
7209
|
+
if (error instanceof ConvexError3 && typeof error.data === "object" && error.data !== null && error.data.code === "invalid_api_key") {
|
|
7210
|
+
return `Median did not recognize the apiKey passed to <${component}>, so it has been hidden. Derive it from an active MEDIAN_KEY with publicKeyFromMedianKey.`;
|
|
6774
7211
|
}
|
|
6775
|
-
return
|
|
7212
|
+
return `Median: <${component}> hit an error and has been hidden. Your page is unaffected.`;
|
|
6776
7213
|
}
|
|
6777
7214
|
var MedianErrorBoundary = class extends Component {
|
|
6778
7215
|
state = { hasFailed: false };
|
|
@@ -6780,7 +7217,7 @@ var MedianErrorBoundary = class extends Component {
|
|
|
6780
7217
|
return { hasFailed: true };
|
|
6781
7218
|
}
|
|
6782
7219
|
componentDidCatch(error) {
|
|
6783
|
-
console.error(adviceFor(error), error);
|
|
7220
|
+
console.error(adviceFor(error, this.props.component), error);
|
|
6784
7221
|
}
|
|
6785
7222
|
render() {
|
|
6786
7223
|
return this.state.hasFailed ? null : this.props.children;
|
|
@@ -6788,7 +7225,7 @@ var MedianErrorBoundary = class extends Component {
|
|
|
6788
7225
|
};
|
|
6789
7226
|
|
|
6790
7227
|
// ../../apps/web/src/components/support-widget/sdk/use-identity.ts
|
|
6791
|
-
import { useEffect as
|
|
7228
|
+
import { useEffect as useEffect20, useState as useState20, useSyncExternalStore as useSyncExternalStore14 } from "react";
|
|
6792
7229
|
var NOTHING = {
|
|
6793
7230
|
apiKey: void 0,
|
|
6794
7231
|
user: void 0,
|
|
@@ -6796,8 +7233,9 @@ var NOTHING = {
|
|
|
6796
7233
|
};
|
|
6797
7234
|
var WAITING = { ...NOTHING, isLoading: true };
|
|
6798
7235
|
var inFlight2 = /* @__PURE__ */ new Map();
|
|
6799
|
-
function read3(endpoint) {
|
|
6800
|
-
const
|
|
7236
|
+
function read3(endpoint, resets) {
|
|
7237
|
+
const cacheKey = `${resets}:${endpoint}`;
|
|
7238
|
+
const existing = inFlight2.get(cacheKey);
|
|
6801
7239
|
if (existing !== void 0) return existing;
|
|
6802
7240
|
const request = (async () => {
|
|
6803
7241
|
const response = await fetch(endpoint, {
|
|
@@ -6812,26 +7250,27 @@ function read3(endpoint) {
|
|
|
6812
7250
|
);
|
|
6813
7251
|
}
|
|
6814
7252
|
return await response.json();
|
|
6815
|
-
})().finally(() => inFlight2.delete(
|
|
6816
|
-
inFlight2.set(
|
|
7253
|
+
})().finally(() => inFlight2.delete(cacheKey));
|
|
7254
|
+
inFlight2.set(cacheKey, request);
|
|
6817
7255
|
return request;
|
|
6818
7256
|
}
|
|
6819
|
-
function useMissingCredentials(
|
|
6820
|
-
|
|
7257
|
+
function useMissingCredentials(caller, apiKey, endpoint, consequence = "nothing is on the page") {
|
|
7258
|
+
useEffect20(() => {
|
|
6821
7259
|
if (apiKey !== void 0 || endpoint !== void 0) return;
|
|
6822
7260
|
console.error(
|
|
6823
|
-
`Median:
|
|
7261
|
+
`Median: ${caller} was given neither apiKey nor identity, so ${consequence}. Pass the median_pk_ id from publicKeyFromMedianKey(MEDIAN_KEY), or the path of a route built with medianIdentity().`
|
|
6824
7262
|
);
|
|
6825
|
-
}, [
|
|
7263
|
+
}, [caller, apiKey, endpoint, consequence]);
|
|
6826
7264
|
}
|
|
6827
7265
|
function useMedianIdentity(endpoint) {
|
|
6828
7266
|
const [answered, setAnswered] = useState20(null);
|
|
6829
|
-
|
|
7267
|
+
const resets = useSyncExternalStore14(subscribeSession, getResetCount, () => 0);
|
|
7268
|
+
useEffect20(() => {
|
|
6830
7269
|
if (endpoint === void 0) return;
|
|
6831
7270
|
let listening = true;
|
|
6832
7271
|
void (async () => {
|
|
6833
7272
|
try {
|
|
6834
|
-
const body = await read3(endpoint);
|
|
7273
|
+
const body = await read3(endpoint, resets);
|
|
6835
7274
|
if (!listening) return;
|
|
6836
7275
|
setAnswered({
|
|
6837
7276
|
endpoint,
|
|
@@ -6855,21 +7294,60 @@ function useMedianIdentity(endpoint) {
|
|
|
6855
7294
|
return () => {
|
|
6856
7295
|
listening = false;
|
|
6857
7296
|
};
|
|
6858
|
-
}, [endpoint]);
|
|
7297
|
+
}, [endpoint, resets]);
|
|
6859
7298
|
if (endpoint === void 0) return NOTHING;
|
|
6860
7299
|
if (answered?.endpoint === endpoint) return answered.identity;
|
|
6861
7300
|
return WAITING;
|
|
6862
7301
|
}
|
|
6863
7302
|
|
|
7303
|
+
// ../../apps/web/src/components/support-widget/sdk/use-median-branding.ts
|
|
7304
|
+
import { ConvexHttpClient as ConvexHttpClient2 } from "convex/browser";
|
|
7305
|
+
import { useEffect as useEffect21, useState as useState21 } from "react";
|
|
7306
|
+
function useMedianBranding(apiKey) {
|
|
7307
|
+
const [state, setState] = useState21({ key: apiKey, show: true });
|
|
7308
|
+
useEffect21(() => {
|
|
7309
|
+
if (!apiKey || !MEDIAN_DEPLOYMENT_URL) return;
|
|
7310
|
+
const client3 = new ConvexHttpClient2(MEDIAN_DEPLOYMENT_URL);
|
|
7311
|
+
let active = true;
|
|
7312
|
+
let expiry;
|
|
7313
|
+
async function refresh() {
|
|
7314
|
+
try {
|
|
7315
|
+
const result = await client3.action(api.billingAccess.branding, {
|
|
7316
|
+
apiKey
|
|
7317
|
+
});
|
|
7318
|
+
if (!active) return;
|
|
7319
|
+
clearTimeout(expiry);
|
|
7320
|
+
const expired = result.expiresAt !== null && result.expiresAt <= Date.now();
|
|
7321
|
+
setState({ key: apiKey, show: result.showBranding || expired });
|
|
7322
|
+
if (!result.showBranding && result.expiresAt !== null)
|
|
7323
|
+
expiry = setTimeout(
|
|
7324
|
+
() => setState({ key: apiKey, show: true }),
|
|
7325
|
+
Math.min(2147483647, Math.max(0, result.expiresAt - Date.now()))
|
|
7326
|
+
);
|
|
7327
|
+
} catch {
|
|
7328
|
+
if (active) setState({ key: apiKey, show: true });
|
|
7329
|
+
}
|
|
7330
|
+
}
|
|
7331
|
+
void refresh();
|
|
7332
|
+
const timer = setInterval(() => void refresh(), 6e4);
|
|
7333
|
+
return () => {
|
|
7334
|
+
active = false;
|
|
7335
|
+
clearInterval(timer);
|
|
7336
|
+
clearTimeout(expiry);
|
|
7337
|
+
};
|
|
7338
|
+
}, [apiKey]);
|
|
7339
|
+
return state.key === apiKey ? state.show : true;
|
|
7340
|
+
}
|
|
7341
|
+
|
|
6864
7342
|
// ../../apps/web/src/components/support-widget/sdk/median-connection.tsx
|
|
6865
7343
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
|
6866
|
-
import { useState as
|
|
7344
|
+
import { useState as useState22 } from "react";
|
|
6867
7345
|
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
6868
7346
|
function MedianConnection({
|
|
6869
7347
|
what,
|
|
6870
7348
|
children
|
|
6871
7349
|
}) {
|
|
6872
|
-
const [client3] =
|
|
7350
|
+
const [client3] = useState22(() => {
|
|
6873
7351
|
if (!MEDIAN_DEPLOYMENT_URL) {
|
|
6874
7352
|
throw new Error(
|
|
6875
7353
|
`The Median ${what} was built without a deployment URL. Set NEXT_PUBLIC_CONVEX_URL.`
|
|
@@ -6881,15 +7359,15 @@ function MedianConnection({
|
|
|
6881
7359
|
}
|
|
6882
7360
|
|
|
6883
7361
|
// ../../apps/web/src/components/support-widget/sdk/use-api-key-warning.ts
|
|
6884
|
-
import { useEffect as
|
|
6885
|
-
function useApiKeyShapeWarning(
|
|
6886
|
-
|
|
7362
|
+
import { useEffect as useEffect22 } from "react";
|
|
7363
|
+
function useApiKeyShapeWarning(caller, apiKey) {
|
|
7364
|
+
useEffect22(() => {
|
|
6887
7365
|
if (apiKey === void 0 || hasPrefix(apiKey, API_KEY_PREFIX)) return;
|
|
6888
7366
|
const shown = apiKey === "" ? "an empty string" : `"${apiKey.length > 16 ? `${apiKey.slice(0, 16)}\u2026` : apiKey}"`;
|
|
6889
7367
|
console.error(
|
|
6890
|
-
`Median: the apiKey passed to
|
|
7368
|
+
`Median: the apiKey passed to ${caller} is ${shown}, which does not look like the browser-safe id from publicKeyFromMedianKey(MEDIAN_KEY). It should start with ${API_KEY_PREFIX}.`
|
|
6891
7369
|
);
|
|
6892
|
-
}, [
|
|
7370
|
+
}, [caller, apiKey]);
|
|
6893
7371
|
}
|
|
6894
7372
|
|
|
6895
7373
|
// ../../node_modules/.bun/cuelume@0.2.2/node_modules/cuelume/dist/sounds/recipes.js
|
|
@@ -7210,16 +7688,16 @@ function play(sound = "chime", options) {
|
|
|
7210
7688
|
}
|
|
7211
7689
|
|
|
7212
7690
|
// ../../apps/web/src/components/support-widget/sdk/use-message-sound.ts
|
|
7213
|
-
import { useEffect as
|
|
7691
|
+
import { useEffect as useEffect23, useRef as useRef20 } from "react";
|
|
7214
7692
|
var ARRIVAL_VOLUME = 0.45;
|
|
7215
7693
|
function useMessageSound({
|
|
7216
7694
|
messages,
|
|
7217
7695
|
conversationId = null,
|
|
7218
7696
|
isLoading
|
|
7219
7697
|
}) {
|
|
7220
|
-
const heard =
|
|
7221
|
-
const watching =
|
|
7222
|
-
|
|
7698
|
+
const heard = useRef20(null);
|
|
7699
|
+
const watching = useRef20(null);
|
|
7700
|
+
useEffect23(() => {
|
|
7223
7701
|
if (isLoading) {
|
|
7224
7702
|
heard.current = null;
|
|
7225
7703
|
return;
|
|
@@ -7243,7 +7721,7 @@ function useMessageSound({
|
|
|
7243
7721
|
}
|
|
7244
7722
|
|
|
7245
7723
|
// ../../apps/web/src/components/support-widget/sdk/use-navigation.ts
|
|
7246
|
-
import { useCallback as
|
|
7724
|
+
import { useCallback as useCallback13, useEffect as useEffect24, useLayoutEffect as useLayoutEffect10, useRef as useRef21, useState as useState23 } from "react";
|
|
7247
7725
|
var isDevelopment2 = typeof process !== "undefined" && process.env.NODE_ENV === "development";
|
|
7248
7726
|
var STALE_AFTER_MS = 5 * 60 * 1e3;
|
|
7249
7727
|
function isFresh(at2) {
|
|
@@ -7287,12 +7765,12 @@ function useSupportNavigation({
|
|
|
7287
7765
|
isLoading,
|
|
7288
7766
|
onNavigate
|
|
7289
7767
|
}) {
|
|
7290
|
-
const seen =
|
|
7291
|
-
const watching =
|
|
7292
|
-
const [spotlight, setSpotlight] =
|
|
7293
|
-
const drawn =
|
|
7294
|
-
const [taken, setTaken] =
|
|
7295
|
-
const follow =
|
|
7768
|
+
const seen = useRef21(null);
|
|
7769
|
+
const watching = useRef21(null);
|
|
7770
|
+
const [spotlight, setSpotlight] = useState23(null);
|
|
7771
|
+
const drawn = useRef21(0);
|
|
7772
|
+
const [taken, setTaken] = useState23(null);
|
|
7773
|
+
const follow = useCallback13(
|
|
7296
7774
|
(destination) => {
|
|
7297
7775
|
if (onNavigate === void 0) return;
|
|
7298
7776
|
const path = pathOnThisSite(destination.path);
|
|
@@ -7314,7 +7792,7 @@ function useSupportNavigation({
|
|
|
7314
7792
|
},
|
|
7315
7793
|
[onNavigate]
|
|
7316
7794
|
);
|
|
7317
|
-
|
|
7795
|
+
useLayoutEffect10(() => {
|
|
7318
7796
|
if (isLoading) return;
|
|
7319
7797
|
const asked = ringing(messages, ask);
|
|
7320
7798
|
if (seen.current === null || watching.current !== conversationId) {
|
|
@@ -7332,8 +7810,8 @@ function useSupportNavigation({
|
|
|
7332
7810
|
}
|
|
7333
7811
|
if (latest !== null) setSpotlight(latest);
|
|
7334
7812
|
}, [messages, ask, conversationId, isLoading]);
|
|
7335
|
-
const warned =
|
|
7336
|
-
|
|
7813
|
+
const warned = useRef21(false);
|
|
7814
|
+
useEffect24(() => {
|
|
7337
7815
|
if (!isDevelopment2 || onNavigate !== void 0 || warned.current) return;
|
|
7338
7816
|
const offered = messages.some((message) => message.navigateTo !== void 0) || ask?.navigateTo != null;
|
|
7339
7817
|
if (!offered) return;
|
|
@@ -7342,12 +7820,12 @@ function useSupportNavigation({
|
|
|
7342
7820
|
"Median: a tool offered to take this visitor to a page, but <MedianSupport> has no onNavigate, so no button is shown for it. Pass one, such as onNavigate={router.push}."
|
|
7343
7821
|
);
|
|
7344
7822
|
}, [messages, ask, onNavigate]);
|
|
7345
|
-
const [, expire] =
|
|
7346
|
-
|
|
7823
|
+
const [, expire] = useState23(0);
|
|
7824
|
+
useEffect24(() => {
|
|
7347
7825
|
if (ask === null || ask.navigateTo === null) return;
|
|
7348
7826
|
const left = ask.at + STALE_AFTER_MS - Date.now();
|
|
7349
7827
|
if (left <= 0) return;
|
|
7350
|
-
const timer = setTimeout(() => expire((
|
|
7828
|
+
const timer = setTimeout(() => expire((count2) => count2 + 1), left);
|
|
7351
7829
|
return () => clearTimeout(timer);
|
|
7352
7830
|
}, [ask]);
|
|
7353
7831
|
const offer = ask !== null && ask.navigateTo !== null && ask.key !== taken && onNavigate !== void 0 && isFresh(ask.at) ? { key: ask.key, path: ask.navigateTo, highlight: ask.highlight } : null;
|
|
@@ -7355,7 +7833,33 @@ function useSupportNavigation({
|
|
|
7355
7833
|
}
|
|
7356
7834
|
|
|
7357
7835
|
// ../../apps/web/src/components/support-widget/sdk/use-teaser.ts
|
|
7358
|
-
import { useCallback as
|
|
7836
|
+
import { useCallback as useCallback14, useState as useState24 } from "react";
|
|
7837
|
+
|
|
7838
|
+
// ../../apps/web/src/components/support-widget/sdk/stamps.ts
|
|
7839
|
+
var inMemory3 = /* @__PURE__ */ new Map();
|
|
7840
|
+
function keyOf(name, apiKey) {
|
|
7841
|
+
return `median:${name}:${apiKey}`;
|
|
7842
|
+
}
|
|
7843
|
+
function readStamp(name, apiKey) {
|
|
7844
|
+
if (typeof window === "undefined") return 0;
|
|
7845
|
+
const key = keyOf(name, apiKey);
|
|
7846
|
+
try {
|
|
7847
|
+
const stored = window.localStorage.getItem(key);
|
|
7848
|
+
const at2 = stored === null ? Number.NaN : Number(stored);
|
|
7849
|
+
return Number.isFinite(at2) ? at2 : 0;
|
|
7850
|
+
} catch {
|
|
7851
|
+
return inMemory3.get(key) ?? 0;
|
|
7852
|
+
}
|
|
7853
|
+
}
|
|
7854
|
+
function writeStamp(name, apiKey, at2) {
|
|
7855
|
+
if (typeof window === "undefined") return;
|
|
7856
|
+
const key = keyOf(name, apiKey);
|
|
7857
|
+
inMemory3.set(key, at2);
|
|
7858
|
+
try {
|
|
7859
|
+
window.localStorage.setItem(key, String(at2));
|
|
7860
|
+
} catch {
|
|
7861
|
+
}
|
|
7862
|
+
}
|
|
7359
7863
|
|
|
7360
7864
|
// ../../apps/web/src/components/support-widget/sdk/teaser-state.ts
|
|
7361
7865
|
var TEASER = "teaser";
|
|
@@ -7368,11 +7872,11 @@ function writeTeaserDismissedAt(apiKey, at2) {
|
|
|
7368
7872
|
|
|
7369
7873
|
// ../../apps/web/src/components/support-widget/sdk/use-teaser.ts
|
|
7370
7874
|
function useTeaser(apiKey, latestUnread) {
|
|
7371
|
-
const [dismissedAt, setDismissedAt] =
|
|
7875
|
+
const [dismissedAt, setDismissedAt] = useState24(
|
|
7372
7876
|
() => readTeaserDismissedAt(apiKey)
|
|
7373
7877
|
);
|
|
7374
7878
|
const teaser = latestUnread !== null && (latestUnread.sentAt ?? 0) > dismissedAt ? latestUnread : null;
|
|
7375
|
-
const dismiss =
|
|
7879
|
+
const dismiss = useCallback14(() => {
|
|
7376
7880
|
if (teaser === null) return;
|
|
7377
7881
|
const at2 = teaser.sentAt ?? Date.now();
|
|
7378
7882
|
writeTeaserDismissedAt(apiKey, at2);
|
|
@@ -7381,8 +7885,38 @@ function useTeaser(apiKey, latestUnread) {
|
|
|
7381
7885
|
return { teaser, dismiss };
|
|
7382
7886
|
}
|
|
7383
7887
|
|
|
7888
|
+
// ../../apps/web/src/components/support-widget/sdk/use-unread-title.ts
|
|
7889
|
+
import { useEffect as useEffect25 } from "react";
|
|
7890
|
+
function badged(count2, title) {
|
|
7891
|
+
return `(${count2}) ${title}`.trim();
|
|
7892
|
+
}
|
|
7893
|
+
function useUnreadTitle(unreadCount) {
|
|
7894
|
+
useEffect25(() => {
|
|
7895
|
+
if (unreadCount === 0 || typeof document === "undefined") return;
|
|
7896
|
+
let plain = document.title;
|
|
7897
|
+
let shown = badged(unreadCount, plain);
|
|
7898
|
+
document.title = shown;
|
|
7899
|
+
const observer = new MutationObserver(() => {
|
|
7900
|
+
const current2 = document.title;
|
|
7901
|
+
if (current2 === shown) return;
|
|
7902
|
+
plain = current2;
|
|
7903
|
+
shown = badged(unreadCount, plain);
|
|
7904
|
+
document.title = shown;
|
|
7905
|
+
});
|
|
7906
|
+
observer.observe(document.head, {
|
|
7907
|
+
childList: true,
|
|
7908
|
+
subtree: true,
|
|
7909
|
+
characterData: true
|
|
7910
|
+
});
|
|
7911
|
+
return () => {
|
|
7912
|
+
observer.disconnect();
|
|
7913
|
+
if (document.title === shown) document.title = plain;
|
|
7914
|
+
};
|
|
7915
|
+
}, [unreadCount]);
|
|
7916
|
+
}
|
|
7917
|
+
|
|
7384
7918
|
// ../../apps/web/src/components/support-widget/sdk/median-support.tsx
|
|
7385
|
-
import { Fragment as Fragment31, jsx as jsx38, jsxs as
|
|
7919
|
+
import { Fragment as Fragment31, jsx as jsx38, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
7386
7920
|
var PRESENCE_BEAT_MS = 45e3;
|
|
7387
7921
|
function MedianSupport(props) {
|
|
7388
7922
|
return /* @__PURE__ */ jsx38(MedianSupportPreview, { ...props });
|
|
@@ -7393,7 +7927,7 @@ function MedianSupportPreview({
|
|
|
7393
7927
|
className,
|
|
7394
7928
|
...props
|
|
7395
7929
|
}) {
|
|
7396
|
-
return /* @__PURE__ */ jsx38(MedianErrorBoundary, { children: /* @__PURE__ */ jsx38(
|
|
7930
|
+
return /* @__PURE__ */ jsx38(MedianErrorBoundary, { component: componentName(presentation), children: /* @__PURE__ */ jsx38(
|
|
7397
7931
|
MedianIdentity,
|
|
7398
7932
|
{
|
|
7399
7933
|
...props,
|
|
@@ -7403,17 +7937,25 @@ function MedianSupportPreview({
|
|
|
7403
7937
|
}
|
|
7404
7938
|
) });
|
|
7405
7939
|
}
|
|
7940
|
+
function componentName(presentation) {
|
|
7941
|
+
return presentation === "modal" ? "MedianSupportModal" : "MedianSupport";
|
|
7942
|
+
}
|
|
7406
7943
|
function MedianIdentity({ apiKey, identity, user, ...rest }) {
|
|
7407
7944
|
const resolved = useMedianIdentity(identity);
|
|
7408
|
-
useMissingCredentials(
|
|
7945
|
+
useMissingCredentials(
|
|
7946
|
+
`<${componentName(rest.presentation)}>`,
|
|
7947
|
+
apiKey,
|
|
7948
|
+
identity
|
|
7949
|
+
);
|
|
7409
7950
|
const key = apiKey ?? resolved.apiKey;
|
|
7951
|
+
const person = useSignedInUser(user ?? resolved.user);
|
|
7410
7952
|
if (key === void 0) return null;
|
|
7411
7953
|
return /* @__PURE__ */ jsx38(MedianConnection, { what: "widget", children: /* @__PURE__ */ jsx38(
|
|
7412
7954
|
MedianLauncher,
|
|
7413
7955
|
{
|
|
7414
7956
|
...rest,
|
|
7415
7957
|
apiKey: key,
|
|
7416
|
-
user:
|
|
7958
|
+
user: person,
|
|
7417
7959
|
isResolvingIdentity: resolved.isLoading
|
|
7418
7960
|
}
|
|
7419
7961
|
) });
|
|
@@ -7422,12 +7964,14 @@ function MedianLauncher({
|
|
|
7422
7964
|
apiKey,
|
|
7423
7965
|
user,
|
|
7424
7966
|
telemetry,
|
|
7967
|
+
screenshot,
|
|
7425
7968
|
diagnostics,
|
|
7426
7969
|
appState,
|
|
7427
7970
|
requireSignIn = false,
|
|
7428
7971
|
onSignIn,
|
|
7429
7972
|
requireEmail = true,
|
|
7430
7973
|
messagePreview = true,
|
|
7974
|
+
titleCount = true,
|
|
7431
7975
|
launcher,
|
|
7432
7976
|
presentation,
|
|
7433
7977
|
defaultOpen,
|
|
@@ -7437,12 +7981,11 @@ function MedianLauncher({
|
|
|
7437
7981
|
isResolvingIdentity,
|
|
7438
7982
|
className
|
|
7439
7983
|
}) {
|
|
7440
|
-
useRegisterMedianSupport();
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
apiKey
|
|
7444
|
-
);
|
|
7984
|
+
useRegisterMedianSupport(componentName(presentation));
|
|
7985
|
+
useCustomDataSender();
|
|
7986
|
+
useApiKeyShapeWarning(`<${componentName(presentation)}>`, apiKey);
|
|
7445
7987
|
useRememberInstall(apiKey, user);
|
|
7988
|
+
const showBranding = useMedianBranding(apiKey);
|
|
7446
7989
|
const [isOpen, setOpen] = useMedianOpenState({
|
|
7447
7990
|
open,
|
|
7448
7991
|
defaultOpen,
|
|
@@ -7462,31 +8005,28 @@ function MedianLauncher({
|
|
|
7462
8005
|
rating,
|
|
7463
8006
|
unreadCount,
|
|
7464
8007
|
latestUnread,
|
|
7465
|
-
markSeen,
|
|
7466
8008
|
reportPresence,
|
|
7467
8009
|
sendError,
|
|
7468
8010
|
send,
|
|
7469
8011
|
setTyping
|
|
7470
|
-
} = useMedianThread(
|
|
8012
|
+
} = useMedianThread({
|
|
7471
8013
|
apiKey,
|
|
7472
8014
|
user,
|
|
7473
8015
|
telemetry,
|
|
8016
|
+
screenshot,
|
|
7474
8017
|
isLocked,
|
|
7475
8018
|
diagnostics,
|
|
7476
8019
|
appState,
|
|
7477
8020
|
requireEmail,
|
|
7478
8021
|
messagePreview
|
|
7479
|
-
);
|
|
8022
|
+
});
|
|
7480
8023
|
const { teaser, dismiss: dismissTeaser } = useTeaser(apiKey, latestUnread);
|
|
7481
8024
|
const isSettling = isLoading || isResolvingIdentity;
|
|
7482
|
-
|
|
7483
|
-
if (isOpen) markSeen();
|
|
7484
|
-
}, [isOpen, markSeen]);
|
|
7485
|
-
useEffect22(() => {
|
|
8025
|
+
useEffect26(() => {
|
|
7486
8026
|
if (!threadRendersMarkdown(messages)) return;
|
|
7487
8027
|
return warmMarkdownWhenIdle();
|
|
7488
8028
|
}, [messages]);
|
|
7489
|
-
|
|
8029
|
+
useEffect26(() => {
|
|
7490
8030
|
if (!isOpen) return;
|
|
7491
8031
|
const beat = () => {
|
|
7492
8032
|
if (document.visibilityState === "visible") reportPresence();
|
|
@@ -7519,16 +8059,22 @@ function MedianLauncher({
|
|
|
7519
8059
|
conversationId,
|
|
7520
8060
|
isLoading: isSettling || isLocked
|
|
7521
8061
|
});
|
|
8062
|
+
useUnreadTitle(titleCount ? unreadCount : 0);
|
|
8063
|
+
useEffect26(() => {
|
|
8064
|
+
unreadStore.set(unreadCount);
|
|
8065
|
+
}, [unreadCount]);
|
|
8066
|
+
useEffect26(() => () => unreadStore.set(0), []);
|
|
7522
8067
|
const resolvedPresence = presence ?? {
|
|
7523
8068
|
name: "Support",
|
|
7524
8069
|
status: "Connecting",
|
|
7525
8070
|
team: []
|
|
7526
8071
|
};
|
|
7527
|
-
return /* @__PURE__ */
|
|
8072
|
+
return /* @__PURE__ */ jsxs22(Fragment31, { children: [
|
|
7528
8073
|
spotlight !== null && /* @__PURE__ */ jsx38(WidgetSpotlight, { selector: spotlight.selector }, spotlight.key),
|
|
7529
8074
|
/* @__PURE__ */ jsx38(
|
|
7530
8075
|
SupportLauncher,
|
|
7531
8076
|
{
|
|
8077
|
+
showBadge: showBranding,
|
|
7532
8078
|
presence: resolvedPresence,
|
|
7533
8079
|
messages,
|
|
7534
8080
|
onSend: send,
|
|
@@ -7644,7 +8190,12 @@ function mountMedianSupportModal(options) {
|
|
|
7644
8190
|
}
|
|
7645
8191
|
|
|
7646
8192
|
// ../../apps/web/src/components/support-widget/sdk/median-feedback.tsx
|
|
7647
|
-
import {
|
|
8193
|
+
import {
|
|
8194
|
+
useCallback as useCallback16,
|
|
8195
|
+
useEffect as useEffect29,
|
|
8196
|
+
useRef as useRef24,
|
|
8197
|
+
useState as useState28
|
|
8198
|
+
} from "react";
|
|
7648
8199
|
|
|
7649
8200
|
// ../backend/convex/shared/feedback.ts
|
|
7650
8201
|
var NOTE_MAX_LENGTH = 2e3;
|
|
@@ -7654,17 +8205,17 @@ var MAX_REPORT_IMAGES = 6;
|
|
|
7654
8205
|
|
|
7655
8206
|
// ../../apps/web/src/components/support-widget/feedback/feedback-panel.tsx
|
|
7656
8207
|
import {
|
|
7657
|
-
useEffect as
|
|
7658
|
-
useRef as
|
|
7659
|
-
useState as
|
|
8208
|
+
useEffect as useEffect28,
|
|
8209
|
+
useRef as useRef23,
|
|
8210
|
+
useState as useState26
|
|
7660
8211
|
} from "react";
|
|
7661
8212
|
|
|
7662
8213
|
// ../../apps/web/src/components/support-widget/feedback/feedback-popover.tsx
|
|
7663
|
-
import { useEffect as
|
|
8214
|
+
import { useEffect as useEffect27, useRef as useRef22 } from "react";
|
|
7664
8215
|
import { createPortal as createPortal3 } from "react-dom";
|
|
7665
8216
|
|
|
7666
8217
|
// ../../apps/web/src/components/support-widget/feedback/use-anchor.ts
|
|
7667
|
-
import { useLayoutEffect as
|
|
8218
|
+
import { useLayoutEffect as useLayoutEffect11, useState as useState25 } from "react";
|
|
7668
8219
|
var GAP2 = 8;
|
|
7669
8220
|
var MARGIN2 = 16;
|
|
7670
8221
|
function findAnchor(selector) {
|
|
@@ -7684,8 +8235,8 @@ function useAnchor({
|
|
|
7684
8235
|
panelRef,
|
|
7685
8236
|
isOpen
|
|
7686
8237
|
}) {
|
|
7687
|
-
const [side, setSide] =
|
|
7688
|
-
|
|
8238
|
+
const [side, setSide] = useState25("bottom");
|
|
8239
|
+
useLayoutEffect11(() => {
|
|
7689
8240
|
if (!isOpen) return;
|
|
7690
8241
|
let frame = 0;
|
|
7691
8242
|
function place() {
|
|
@@ -7753,12 +8304,12 @@ function FeedbackPopover({
|
|
|
7753
8304
|
width,
|
|
7754
8305
|
children
|
|
7755
8306
|
}) {
|
|
7756
|
-
const panelRef =
|
|
8307
|
+
const panelRef = useRef22(null);
|
|
7757
8308
|
const side = useAnchor({ triggerRef, anchor, panelRef, isOpen });
|
|
7758
8309
|
const isHydrated = useHydrated();
|
|
7759
|
-
const opener =
|
|
7760
|
-
const wasOpen =
|
|
7761
|
-
|
|
8310
|
+
const opener = useRef22(null);
|
|
8311
|
+
const wasOpen = useRef22(isOpen);
|
|
8312
|
+
useEffect27(() => {
|
|
7762
8313
|
if (!isOpen) return;
|
|
7763
8314
|
function handleKeyDown(event) {
|
|
7764
8315
|
if (event.key === "Escape") onClose();
|
|
@@ -7766,7 +8317,7 @@ function FeedbackPopover({
|
|
|
7766
8317
|
document.addEventListener("keydown", handleKeyDown);
|
|
7767
8318
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
7768
8319
|
}, [isOpen, onClose]);
|
|
7769
|
-
|
|
8320
|
+
useEffect27(() => {
|
|
7770
8321
|
if (!isOpen) return;
|
|
7771
8322
|
function handlePointerDown(event) {
|
|
7772
8323
|
const target = event.target;
|
|
@@ -7778,7 +8329,7 @@ function FeedbackPopover({
|
|
|
7778
8329
|
document.addEventListener("pointerdown", handlePointerDown);
|
|
7779
8330
|
return () => document.removeEventListener("pointerdown", handlePointerDown);
|
|
7780
8331
|
}, [isOpen, onClose, triggerRef]);
|
|
7781
|
-
|
|
8332
|
+
useEffect27(() => {
|
|
7782
8333
|
if (wasOpen.current === isOpen) return;
|
|
7783
8334
|
wasOpen.current = isOpen;
|
|
7784
8335
|
if (isOpen) {
|
|
@@ -7834,7 +8385,7 @@ function FeedbackPopover({
|
|
|
7834
8385
|
}
|
|
7835
8386
|
|
|
7836
8387
|
// ../../apps/web/src/components/support-widget/feedback/feedback-panel.tsx
|
|
7837
|
-
import { Fragment as Fragment32, jsx as jsx43, jsxs as
|
|
8388
|
+
import { Fragment as Fragment32, jsx as jsx43, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
7838
8389
|
var THANKS_MS2 = 1600;
|
|
7839
8390
|
function FeedbackPanel({
|
|
7840
8391
|
onSubmit,
|
|
@@ -7843,21 +8394,21 @@ function FeedbackPanel({
|
|
|
7843
8394
|
notice,
|
|
7844
8395
|
showBadge = true,
|
|
7845
8396
|
title = "Share feedback",
|
|
7846
|
-
description = "
|
|
8397
|
+
description = "Bugs, ideas, anything.",
|
|
7847
8398
|
placeholder = "Tell us what could be better.",
|
|
7848
8399
|
className
|
|
7849
8400
|
}) {
|
|
7850
|
-
const [draft, setDraft] =
|
|
7851
|
-
const [isSending, setSending] =
|
|
7852
|
-
const [isSent, setSent] =
|
|
7853
|
-
const fileInputRef =
|
|
8401
|
+
const [draft, setDraft] = useState26("");
|
|
8402
|
+
const [isSending, setSending] = useState26(false);
|
|
8403
|
+
const [isSent, setSent] = useState26(false);
|
|
8404
|
+
const fileInputRef = useRef23(null);
|
|
7854
8405
|
const images = useAttachmentDrafts({
|
|
7855
8406
|
accept: "image",
|
|
7856
8407
|
max: MAX_REPORT_IMAGES
|
|
7857
8408
|
});
|
|
7858
8409
|
const target = useAttachmentTarget({ onFiles: images.add });
|
|
7859
8410
|
const canSend = draft.trim().length > 0 && !images.hasBlocker && !isSending && !isSent;
|
|
7860
|
-
|
|
8411
|
+
useEffect28(() => {
|
|
7861
8412
|
if (!isSent) return;
|
|
7862
8413
|
const timer = setTimeout(() => onSent?.(), THANKS_MS2);
|
|
7863
8414
|
return () => clearTimeout(timer);
|
|
@@ -7885,7 +8436,7 @@ function FeedbackPanel({
|
|
|
7885
8436
|
event.preventDefault();
|
|
7886
8437
|
void send();
|
|
7887
8438
|
}
|
|
7888
|
-
return /* @__PURE__ */
|
|
8439
|
+
return /* @__PURE__ */ jsxs23(
|
|
7889
8440
|
"section",
|
|
7890
8441
|
{
|
|
7891
8442
|
"aria-label": title,
|
|
@@ -7893,12 +8444,12 @@ function FeedbackPanel({
|
|
|
7893
8444
|
className: cn(
|
|
7894
8445
|
// The widget's own radius scale, so the app's token can climb as the
|
|
7895
8446
|
// chrome gets rounder without this changing shape under its hosts.
|
|
7896
|
-
|
|
8447
|
+
`flex w-full flex-col gap-2 overflow-hidden ${WIDGET_CORNER} border bg-card p-3 text-card-foreground [--radius:0.625rem]`,
|
|
7897
8448
|
className
|
|
7898
8449
|
),
|
|
7899
8450
|
children: [
|
|
7900
|
-
/* @__PURE__ */
|
|
7901
|
-
/* @__PURE__ */
|
|
8451
|
+
/* @__PURE__ */ jsxs23("header", { className: "flex items-start gap-2", children: [
|
|
8452
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
7902
8453
|
/* @__PURE__ */ jsx43("h2", { className: "truncate text-sm font-semibold tracking-tight", children: title }),
|
|
7903
8454
|
/* @__PURE__ */ jsx43("p", { className: "text-xs text-muted-foreground", children: description })
|
|
7904
8455
|
] }),
|
|
@@ -7915,8 +8466,8 @@ function FeedbackPanel({
|
|
|
7915
8466
|
}
|
|
7916
8467
|
)
|
|
7917
8468
|
] }),
|
|
7918
|
-
/* @__PURE__ */
|
|
7919
|
-
/* @__PURE__ */ jsx43(Collapse, { isOpen: !isSent, children: /* @__PURE__ */
|
|
8469
|
+
/* @__PURE__ */ jsxs23("div", { className: "grid", children: [
|
|
8470
|
+
/* @__PURE__ */ jsx43(Collapse, { isOpen: !isSent, children: /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-1.5", children: [
|
|
7920
8471
|
/* @__PURE__ */ jsx43(
|
|
7921
8472
|
Textarea,
|
|
7922
8473
|
{
|
|
@@ -7929,7 +8480,7 @@ function FeedbackPanel({
|
|
|
7929
8480
|
"aria-label": title,
|
|
7930
8481
|
...{ [AUTOFOCUS_ATTRIBUTE]: "" },
|
|
7931
8482
|
className: cn(
|
|
7932
|
-
|
|
8483
|
+
WIDGET_TEXT_FIELD_SHELL,
|
|
7933
8484
|
"max-h-40 min-h-18 px-2.5 py-2",
|
|
7934
8485
|
// 16px on phones, in pixels: any focused field smaller than
|
|
7935
8486
|
// that makes iOS zoom the host's whole page in.
|
|
@@ -7947,14 +8498,14 @@ function FeedbackPanel({
|
|
|
7947
8498
|
)) }),
|
|
7948
8499
|
notice && /* @__PURE__ */ jsx43("p", { className: "animate-in px-0.5 text-xs text-destructive fade-in duration-150", children: notice })
|
|
7949
8500
|
] }) }),
|
|
7950
|
-
/* @__PURE__ */ jsx43(Collapse, { isOpen: isSent, children: /* @__PURE__ */
|
|
8501
|
+
/* @__PURE__ */ jsx43(Collapse, { isOpen: isSent, children: /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-center gap-2 py-4 text-sm font-medium", children: [
|
|
7951
8502
|
/* @__PURE__ */ jsx43("span", { className: "grid size-5 shrink-0 place-items-center rounded-full bg-primary text-primary-foreground", children: /* @__PURE__ */ jsx43(Check, { className: "size-3" }) }),
|
|
7952
8503
|
"Thanks for your feedback."
|
|
7953
8504
|
] }) })
|
|
7954
8505
|
] }),
|
|
7955
|
-
/* @__PURE__ */
|
|
8506
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex min-h-8 items-center gap-2", children: [
|
|
7956
8507
|
showBadge && /* @__PURE__ */ jsx43(PoweredByMedian, { className: "justify-start" }),
|
|
7957
|
-
!isSent && /* @__PURE__ */
|
|
8508
|
+
!isSent && /* @__PURE__ */ jsxs23(Fragment32, { children: [
|
|
7958
8509
|
/* @__PURE__ */ jsx43(
|
|
7959
8510
|
"input",
|
|
7960
8511
|
{
|
|
@@ -7980,7 +8531,7 @@ function FeedbackPanel({
|
|
|
7980
8531
|
children: /* @__PURE__ */ jsx43(ImageSquare, {})
|
|
7981
8532
|
}
|
|
7982
8533
|
),
|
|
7983
|
-
/* @__PURE__ */
|
|
8534
|
+
/* @__PURE__ */ jsxs23(
|
|
7984
8535
|
WidgetButton,
|
|
7985
8536
|
{
|
|
7986
8537
|
type: "button",
|
|
@@ -8017,7 +8568,7 @@ function FeedbackPanel({
|
|
|
8017
8568
|
}
|
|
8018
8569
|
|
|
8019
8570
|
// ../../apps/web/src/components/support-widget/sdk/feedback-control.ts
|
|
8020
|
-
import { useSyncExternalStore as
|
|
8571
|
+
import { useSyncExternalStore as useSyncExternalStore15 } from "react";
|
|
8021
8572
|
var store2 = createOpenStore("MedianFeedback");
|
|
8022
8573
|
var medianFeedback = {
|
|
8023
8574
|
/** What the panel is doing right now. */
|
|
@@ -8040,7 +8591,7 @@ var medianFeedback = {
|
|
|
8040
8591
|
}
|
|
8041
8592
|
};
|
|
8042
8593
|
function useMedianFeedback() {
|
|
8043
|
-
const isOpen =
|
|
8594
|
+
const isOpen = useSyncExternalStore15(
|
|
8044
8595
|
store2.subscribe,
|
|
8045
8596
|
store2.readEffective,
|
|
8046
8597
|
store2.readServerEffective
|
|
@@ -8060,8 +8611,7 @@ function useRegisterMedianFeedback() {
|
|
|
8060
8611
|
}
|
|
8061
8612
|
|
|
8062
8613
|
// ../../apps/web/src/components/support-widget/sdk/use-feedback-note.ts
|
|
8063
|
-
import {
|
|
8064
|
-
import { useCallback as useCallback14, useState as useState26, useSyncExternalStore as useSyncExternalStore13 } from "react";
|
|
8614
|
+
import { useCallback as useCallback15, useState as useState27, useSyncExternalStore as useSyncExternalStore16 } from "react";
|
|
8065
8615
|
var REFUSALS = {
|
|
8066
8616
|
off: "Feedback is currently unavailable. Try again later.",
|
|
8067
8617
|
empty: "Enter your feedback before sending."
|
|
@@ -8070,19 +8620,20 @@ function useFeedbackNote({
|
|
|
8070
8620
|
apiKey,
|
|
8071
8621
|
user,
|
|
8072
8622
|
telemetry = true,
|
|
8623
|
+
screenshot = true,
|
|
8073
8624
|
diagnostics,
|
|
8074
8625
|
appState
|
|
8075
8626
|
}) {
|
|
8076
|
-
const sessionId =
|
|
8627
|
+
const sessionId = useSyncExternalStore16(
|
|
8077
8628
|
subscribeSession,
|
|
8078
|
-
|
|
8629
|
+
useCallback15(() => getOrCreateSessionId(apiKey), [apiKey]),
|
|
8079
8630
|
() => null
|
|
8080
8631
|
);
|
|
8081
|
-
const submitNote =
|
|
8082
|
-
const getUploadUrl =
|
|
8632
|
+
const submitNote = useWidgetMutation(api.feedback.submitV2);
|
|
8633
|
+
const getUploadUrl = useWidgetMutation(api.widget.generateUploadUrlV2);
|
|
8083
8634
|
const takeDiagnostics = useDiagnostics(diagnostics, appState);
|
|
8084
|
-
const [notice, setNotice] =
|
|
8085
|
-
const submit =
|
|
8635
|
+
const [notice, setNotice] = useState27(null);
|
|
8636
|
+
const submit = useCallback15(
|
|
8086
8637
|
async (body, images = []) => {
|
|
8087
8638
|
setNotice(null);
|
|
8088
8639
|
if (sessionId === null) {
|
|
@@ -8096,9 +8647,10 @@ function useFeedbackNote({
|
|
|
8096
8647
|
const page = telemetry ? collectPage() : void 0;
|
|
8097
8648
|
const collected = takeDiagnostics();
|
|
8098
8649
|
const { facts, claim } = splitIdentity(user ?? null);
|
|
8650
|
+
const shot = screenshot && images.length < MAX_REPORT_IMAGES ? await capturePage() : null;
|
|
8099
8651
|
const attached = await uploadAttachments(
|
|
8100
8652
|
() => getUploadUrl({ apiKey, sessionId }),
|
|
8101
|
-
images
|
|
8653
|
+
shot === null ? images : [...images, shot]
|
|
8102
8654
|
);
|
|
8103
8655
|
const outcome = await submitNote({
|
|
8104
8656
|
apiKey,
|
|
@@ -8114,13 +8666,18 @@ function useFeedbackNote({
|
|
|
8114
8666
|
});
|
|
8115
8667
|
if (outcome !== "taken") {
|
|
8116
8668
|
explained = true;
|
|
8117
|
-
setNotice(
|
|
8669
|
+
setNotice(
|
|
8670
|
+
REFUSALS[outcome] ?? "Could not send your feedback. Try again."
|
|
8671
|
+
);
|
|
8118
8672
|
throw new Error(outcome);
|
|
8119
8673
|
}
|
|
8120
8674
|
} catch (caught) {
|
|
8121
8675
|
if (custom) restoreCustomData(custom);
|
|
8122
8676
|
if (!explained) {
|
|
8123
|
-
console.error(
|
|
8677
|
+
console.error(
|
|
8678
|
+
"Sending feedback from the Median panel failed",
|
|
8679
|
+
caught
|
|
8680
|
+
);
|
|
8124
8681
|
setNotice(errorMessage(caught));
|
|
8125
8682
|
}
|
|
8126
8683
|
throw caught;
|
|
@@ -8131,6 +8688,7 @@ function useFeedbackNote({
|
|
|
8131
8688
|
sessionId,
|
|
8132
8689
|
user,
|
|
8133
8690
|
telemetry,
|
|
8691
|
+
screenshot,
|
|
8134
8692
|
takeDiagnostics,
|
|
8135
8693
|
submitNote,
|
|
8136
8694
|
getUploadUrl
|
|
@@ -8140,10 +8698,10 @@ function useFeedbackNote({
|
|
|
8140
8698
|
}
|
|
8141
8699
|
|
|
8142
8700
|
// ../../apps/web/src/components/support-widget/sdk/median-feedback.tsx
|
|
8143
|
-
import { Fragment as Fragment33, jsx as jsx44, jsxs as
|
|
8701
|
+
import { Fragment as Fragment33, jsx as jsx44, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
8144
8702
|
var DEFAULT_WIDTH2 = "20rem";
|
|
8145
8703
|
function MedianFeedback(props) {
|
|
8146
|
-
return /* @__PURE__ */ jsx44(MedianErrorBoundary, { children: /* @__PURE__ */ jsx44(FeedbackIdentity, { ...props }) });
|
|
8704
|
+
return /* @__PURE__ */ jsx44(MedianErrorBoundary, { component: "MedianFeedback", children: /* @__PURE__ */ jsx44(FeedbackIdentity, { ...props }) });
|
|
8147
8705
|
}
|
|
8148
8706
|
function FeedbackIdentity({
|
|
8149
8707
|
apiKey,
|
|
@@ -8152,18 +8710,11 @@ function FeedbackIdentity({
|
|
|
8152
8710
|
...rest
|
|
8153
8711
|
}) {
|
|
8154
8712
|
const resolved = useMedianIdentity(identity);
|
|
8155
|
-
useMissingCredentials("MedianFeedback", apiKey, identity);
|
|
8713
|
+
useMissingCredentials("<MedianFeedback>", apiKey, identity);
|
|
8156
8714
|
const key = apiKey ?? resolved.apiKey;
|
|
8157
|
-
const person = user ?? resolved.user;
|
|
8715
|
+
const person = useSignedInUser(user ?? resolved.user);
|
|
8158
8716
|
if (key === void 0) return null;
|
|
8159
|
-
return /* @__PURE__ */ jsx44(MedianConnection, { what: "feedback panel", children: /* @__PURE__ */ jsx44(
|
|
8160
|
-
Feedback,
|
|
8161
|
-
{
|
|
8162
|
-
...rest,
|
|
8163
|
-
apiKey: key,
|
|
8164
|
-
...person ? { user: person } : {}
|
|
8165
|
-
}
|
|
8166
|
-
) });
|
|
8717
|
+
return /* @__PURE__ */ jsx44(MedianConnection, { what: "feedback panel", children: /* @__PURE__ */ jsx44(Feedback, { ...rest, apiKey: key, ...person ? { user: person } : {} }) });
|
|
8167
8718
|
}
|
|
8168
8719
|
function Feedback({
|
|
8169
8720
|
apiKey,
|
|
@@ -8171,6 +8722,7 @@ function Feedback({
|
|
|
8171
8722
|
anchor,
|
|
8172
8723
|
user,
|
|
8173
8724
|
telemetry,
|
|
8725
|
+
screenshot,
|
|
8174
8726
|
diagnostics,
|
|
8175
8727
|
appState,
|
|
8176
8728
|
open,
|
|
@@ -8181,9 +8733,10 @@ function Feedback({
|
|
|
8181
8733
|
placeholder
|
|
8182
8734
|
}) {
|
|
8183
8735
|
useRegisterMedianFeedback();
|
|
8184
|
-
useApiKeyShapeWarning("MedianFeedback", apiKey);
|
|
8736
|
+
useApiKeyShapeWarning("<MedianFeedback>", apiKey);
|
|
8737
|
+
useCustomDataSender();
|
|
8185
8738
|
useRememberInstall(apiKey, user);
|
|
8186
|
-
const triggerRef =
|
|
8739
|
+
const triggerRef = useRef24(null);
|
|
8187
8740
|
const [isOpen, setOpen] = useMedianFeedbackOpenState({
|
|
8188
8741
|
...open !== void 0 ? { open } : {},
|
|
8189
8742
|
...onOpenChange ? { onOpenChange } : {}
|
|
@@ -8192,18 +8745,20 @@ function Feedback({
|
|
|
8192
8745
|
apiKey,
|
|
8193
8746
|
...user ? { user } : {},
|
|
8194
8747
|
...telemetry !== void 0 ? { telemetry } : {},
|
|
8748
|
+
...screenshot !== void 0 ? { screenshot } : {},
|
|
8195
8749
|
...diagnostics !== void 0 ? { diagnostics } : {},
|
|
8196
8750
|
...appState ? { appState } : {}
|
|
8197
8751
|
});
|
|
8198
|
-
const
|
|
8199
|
-
const
|
|
8200
|
-
const
|
|
8201
|
-
|
|
8752
|
+
const showBranding = useMedianBranding(apiKey);
|
|
8753
|
+
const close = useCallback16(() => setOpen(false), [setOpen]);
|
|
8754
|
+
const [attempt, setAttempt] = useState28(0);
|
|
8755
|
+
const hasSent = useRef24(false);
|
|
8756
|
+
useEffect29(() => {
|
|
8202
8757
|
if (!isOpen || !hasSent.current) return;
|
|
8203
8758
|
hasSent.current = false;
|
|
8204
|
-
setAttempt((
|
|
8759
|
+
setAttempt((count2) => count2 + 1);
|
|
8205
8760
|
}, [isOpen]);
|
|
8206
|
-
return /* @__PURE__ */
|
|
8761
|
+
return /* @__PURE__ */ jsxs24(Fragment33, { children: [
|
|
8207
8762
|
children !== void 0 && // An inline span rather than a clone of whatever was passed: the
|
|
8208
8763
|
// host's trigger keeps its own props, its own ref and its own
|
|
8209
8764
|
// styles, and the click is caught on the way past. `display:
|
|
@@ -8228,6 +8783,7 @@ function Feedback({
|
|
|
8228
8783
|
children: /* @__PURE__ */ jsx44(
|
|
8229
8784
|
FeedbackPanel,
|
|
8230
8785
|
{
|
|
8786
|
+
showBadge: showBranding,
|
|
8231
8787
|
onSubmit: note.submit,
|
|
8232
8788
|
onClose: close,
|
|
8233
8789
|
onSent: () => {
|
|
@@ -8260,23 +8816,23 @@ function mountMedianFeedback(options) {
|
|
|
8260
8816
|
}
|
|
8261
8817
|
|
|
8262
8818
|
// ../../apps/web/src/components/support-widget/sdk/median-contact-form.tsx
|
|
8263
|
-
import { useEffect as
|
|
8819
|
+
import { useEffect as useEffect31, useMemo as useMemo5 } from "react";
|
|
8264
8820
|
|
|
8265
8821
|
// ../../apps/web/src/components/support-widget/contact/contact-form.tsx
|
|
8266
8822
|
import {
|
|
8267
|
-
useEffect as
|
|
8823
|
+
useEffect as useEffect30,
|
|
8268
8824
|
useId,
|
|
8269
8825
|
useMemo as useMemo3,
|
|
8270
|
-
useRef as
|
|
8271
|
-
useState as
|
|
8826
|
+
useRef as useRef26,
|
|
8827
|
+
useState as useState30
|
|
8272
8828
|
} from "react";
|
|
8273
8829
|
|
|
8274
8830
|
// ../../apps/web/src/components/support-widget/contact/contact-field.tsx
|
|
8275
|
-
import { useState as
|
|
8276
|
-
import { jsx as jsx46, jsxs as
|
|
8831
|
+
import { useState as useState29 } from "react";
|
|
8832
|
+
import { jsx as jsx46, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
8277
8833
|
var LINE_MAX_LENGTH = 200;
|
|
8278
8834
|
var SHELL = cn(
|
|
8279
|
-
|
|
8835
|
+
WIDGET_TEXT_FIELD_SHELL,
|
|
8280
8836
|
"w-full bg-card text-base max-sm:text-[16px] dark:bg-card"
|
|
8281
8837
|
);
|
|
8282
8838
|
var LINE = "h-11 rounded-full px-4";
|
|
@@ -8290,9 +8846,9 @@ function ContactField({
|
|
|
8290
8846
|
onChange,
|
|
8291
8847
|
onSubmit
|
|
8292
8848
|
}) {
|
|
8293
|
-
const [
|
|
8294
|
-
if (error !== null && error !==
|
|
8295
|
-
const shown = error ??
|
|
8849
|
+
const [held2, setHeld] = useState29(error);
|
|
8850
|
+
if (error !== null && error !== held2) setHeld(error);
|
|
8851
|
+
const shown = error ?? held2;
|
|
8296
8852
|
const errorId = `${id}-error`;
|
|
8297
8853
|
const control = {
|
|
8298
8854
|
id,
|
|
@@ -8308,8 +8864,8 @@ function ContactField({
|
|
|
8308
8864
|
event.preventDefault();
|
|
8309
8865
|
onSubmit?.();
|
|
8310
8866
|
}
|
|
8311
|
-
return /* @__PURE__ */
|
|
8312
|
-
/* @__PURE__ */
|
|
8867
|
+
return /* @__PURE__ */ jsxs25("div", { className: "flex flex-col", children: [
|
|
8868
|
+
/* @__PURE__ */ jsxs25(
|
|
8313
8869
|
"label",
|
|
8314
8870
|
{
|
|
8315
8871
|
htmlFor: id,
|
|
@@ -8331,8 +8887,8 @@ function ContactField({
|
|
|
8331
8887
|
onKeyDown: handleKeyDown,
|
|
8332
8888
|
className: cn(SHELL, PARAGRAPH)
|
|
8333
8889
|
}
|
|
8334
|
-
) : field.type === "select" ? /* @__PURE__ */
|
|
8335
|
-
/* @__PURE__ */
|
|
8890
|
+
) : field.type === "select" ? /* @__PURE__ */ jsxs25("div", { className: "relative", children: [
|
|
8891
|
+
/* @__PURE__ */ jsxs25(
|
|
8336
8892
|
"select",
|
|
8337
8893
|
{
|
|
8338
8894
|
...control,
|
|
@@ -8498,8 +9054,8 @@ function fieldComplaints(fields) {
|
|
|
8498
9054
|
}
|
|
8499
9055
|
|
|
8500
9056
|
// ../../apps/web/src/components/support-widget/contact/sent-mark.tsx
|
|
8501
|
-
import { useLayoutEffect as
|
|
8502
|
-
import { jsx as jsx47, jsxs as
|
|
9057
|
+
import { useLayoutEffect as useLayoutEffect12, useRef as useRef25 } from "react";
|
|
9058
|
+
import { jsx as jsx47, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
8503
9059
|
var EASE_OUT = "cubic-bezier(0.22, 1, 0.36, 1)";
|
|
8504
9060
|
var TRAVEL_MS = 550;
|
|
8505
9061
|
var DRAW_LEAD_MS = 150;
|
|
@@ -8512,11 +9068,11 @@ function SentMark({
|
|
|
8512
9068
|
from = null,
|
|
8513
9069
|
className
|
|
8514
9070
|
}) {
|
|
8515
|
-
const frame =
|
|
8516
|
-
const square =
|
|
8517
|
-
const tick =
|
|
8518
|
-
const ring =
|
|
8519
|
-
|
|
9071
|
+
const frame = useRef25(null);
|
|
9072
|
+
const square = useRef25(null);
|
|
9073
|
+
const tick = useRef25(null);
|
|
9074
|
+
const ring = useRef25(null);
|
|
9075
|
+
useLayoutEffect12(() => {
|
|
8520
9076
|
const rest = frame.current;
|
|
8521
9077
|
const box = square.current;
|
|
8522
9078
|
const path = tick.current;
|
|
@@ -8574,7 +9130,7 @@ function SentMark({
|
|
|
8574
9130
|
for (const animation of animations) animation.cancel();
|
|
8575
9131
|
};
|
|
8576
9132
|
}, [from]);
|
|
8577
|
-
return /* @__PURE__ */
|
|
9133
|
+
return /* @__PURE__ */ jsxs26(
|
|
8578
9134
|
"span",
|
|
8579
9135
|
{
|
|
8580
9136
|
ref: frame,
|
|
@@ -8618,7 +9174,7 @@ function SentMark({
|
|
|
8618
9174
|
}
|
|
8619
9175
|
|
|
8620
9176
|
// ../../apps/web/src/components/support-widget/contact/contact-form.tsx
|
|
8621
|
-
import { jsx as jsx48, jsxs as
|
|
9177
|
+
import { jsx as jsx48, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
8622
9178
|
var EMAIL_PATTERN2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
8623
9179
|
var FORM_SWAP = "transition-[opacity,translate] duration-250 ease-out-quint motion-reduce:transition-none";
|
|
8624
9180
|
var THANKS_SWAP = "transition-opacity ease-out motion-reduce:transition-none";
|
|
@@ -8663,18 +9219,18 @@ function ContactForm({
|
|
|
8663
9219
|
}) {
|
|
8664
9220
|
const fields = useMemo3(() => resolveFields(hostFields), [hostFields]);
|
|
8665
9221
|
const prefix = useId();
|
|
8666
|
-
const formRef =
|
|
8667
|
-
const sendRef =
|
|
8668
|
-
const [values, setValues] =
|
|
9222
|
+
const formRef = useRef26(null);
|
|
9223
|
+
const sendRef = useRef26(null);
|
|
9224
|
+
const [values, setValues] = useState30(
|
|
8669
9225
|
() => startingValues(fields, initialValues)
|
|
8670
9226
|
);
|
|
8671
|
-
const [errors, setErrors] =
|
|
8672
|
-
const [isSending, setSending] =
|
|
8673
|
-
const [sent, setSent] =
|
|
9227
|
+
const [errors, setErrors] = useState30({});
|
|
9228
|
+
const [isSending, setSending] = useState30(false);
|
|
9229
|
+
const [sent, setSent] = useState30(null);
|
|
8674
9230
|
const isSent = sent !== null;
|
|
8675
9231
|
const knownEmail = initialValues?.email;
|
|
8676
9232
|
const knownName = initialValues?.name;
|
|
8677
|
-
const [known, setKnown] =
|
|
9233
|
+
const [known, setKnown] = useState30({ email: knownEmail, name: knownName });
|
|
8678
9234
|
if (known.email !== knownEmail || known.name !== knownName) {
|
|
8679
9235
|
setKnown({ email: knownEmail, name: knownName });
|
|
8680
9236
|
setValues((current2) => {
|
|
@@ -8684,8 +9240,8 @@ function ContactForm({
|
|
|
8684
9240
|
return next;
|
|
8685
9241
|
});
|
|
8686
9242
|
}
|
|
8687
|
-
const [focusRequest, setFocusRequest] =
|
|
8688
|
-
|
|
9243
|
+
const [focusRequest, setFocusRequest] = useState30(0);
|
|
9244
|
+
useEffect30(() => {
|
|
8689
9245
|
if (focusRequest === 0) return;
|
|
8690
9246
|
formRef.current?.querySelector('[aria-invalid="true"]')?.focus({ preventScroll: false });
|
|
8691
9247
|
}, [focusRequest]);
|
|
@@ -8707,7 +9263,7 @@ function ContactForm({
|
|
|
8707
9263
|
}
|
|
8708
9264
|
if (Object.keys(found).length > 0) {
|
|
8709
9265
|
setErrors(found);
|
|
8710
|
-
setFocusRequest((
|
|
9266
|
+
setFocusRequest((count2) => count2 + 1);
|
|
8711
9267
|
return;
|
|
8712
9268
|
}
|
|
8713
9269
|
const message = composeMessage(fields, values);
|
|
@@ -8736,22 +9292,22 @@ function ContactForm({
|
|
|
8736
9292
|
event.preventDefault();
|
|
8737
9293
|
void send();
|
|
8738
9294
|
}
|
|
8739
|
-
return /* @__PURE__ */
|
|
9295
|
+
return /* @__PURE__ */ jsxs27(
|
|
8740
9296
|
"section",
|
|
8741
9297
|
{
|
|
8742
9298
|
"aria-label": title,
|
|
8743
9299
|
"data-median-widget": "",
|
|
8744
9300
|
className: cn(
|
|
8745
|
-
|
|
9301
|
+
`flex w-full flex-col overflow-hidden ${WIDGET_CORNER} border bg-card p-5 text-card-foreground [--radius:0.625rem]`,
|
|
8746
9302
|
className
|
|
8747
9303
|
),
|
|
8748
9304
|
children: [
|
|
8749
|
-
/* @__PURE__ */
|
|
9305
|
+
/* @__PURE__ */ jsxs27("header", { className: "flex flex-col gap-0.5 pb-4", children: [
|
|
8750
9306
|
/* @__PURE__ */ jsx48("h2", { className: "text-lg font-semibold tracking-tight", children: title }),
|
|
8751
9307
|
/* @__PURE__ */ jsx48("p", { className: "text-sm text-muted-foreground", children: description })
|
|
8752
9308
|
] }),
|
|
8753
|
-
/* @__PURE__ */
|
|
8754
|
-
/* @__PURE__ */
|
|
9309
|
+
/* @__PURE__ */ jsxs27("div", { className: "grid", children: [
|
|
9310
|
+
/* @__PURE__ */ jsxs27(
|
|
8755
9311
|
"form",
|
|
8756
9312
|
{
|
|
8757
9313
|
ref: formRef,
|
|
@@ -8778,9 +9334,9 @@ function ContactForm({
|
|
|
8778
9334
|
field.name
|
|
8779
9335
|
)),
|
|
8780
9336
|
notice && /* @__PURE__ */ jsx48("p", { className: "animate-in px-1 text-sm text-destructive fade-in duration-150", children: notice }),
|
|
8781
|
-
/* @__PURE__ */
|
|
9337
|
+
/* @__PURE__ */ jsxs27("div", { className: "flex min-h-10 flex-wrap items-center gap-3 pt-1", children: [
|
|
8782
9338
|
showBadge && /* @__PURE__ */ jsx48(PoweredByMedian, { className: "justify-start" }),
|
|
8783
|
-
/* @__PURE__ */
|
|
9339
|
+
/* @__PURE__ */ jsxs27(
|
|
8784
9340
|
WidgetButton,
|
|
8785
9341
|
{
|
|
8786
9342
|
ref: sendRef,
|
|
@@ -8832,15 +9388,15 @@ function ContactForm({
|
|
|
8832
9388
|
THANKS_SWAP,
|
|
8833
9389
|
isSent ? "duration-0" : "pointer-events-none opacity-0 duration-200"
|
|
8834
9390
|
),
|
|
8835
|
-
children: sent !== null && /* @__PURE__ */
|
|
9391
|
+
children: sent !== null && /* @__PURE__ */ jsxs27("div", { className: "contents", children: [
|
|
8836
9392
|
/* @__PURE__ */ jsx48(SentMark, { from: sent.from }),
|
|
8837
|
-
/* @__PURE__ */
|
|
9393
|
+
/* @__PURE__ */ jsxs27(
|
|
8838
9394
|
"div",
|
|
8839
9395
|
{
|
|
8840
9396
|
className: cn("flex max-w-72 flex-col gap-1", ARRIVES2, "delay-[400ms]"),
|
|
8841
9397
|
children: [
|
|
8842
9398
|
/* @__PURE__ */ jsx48("p", { className: "text-xl font-semibold tracking-tight", children: "Message sent" }),
|
|
8843
|
-
/* @__PURE__ */
|
|
9399
|
+
/* @__PURE__ */ jsxs27("p", { className: "text-base text-balance text-muted-foreground", children: [
|
|
8844
9400
|
"Replies go to ",
|
|
8845
9401
|
sent.email,
|
|
8846
9402
|
"."
|
|
@@ -8848,7 +9404,7 @@ function ContactForm({
|
|
|
8848
9404
|
]
|
|
8849
9405
|
}
|
|
8850
9406
|
),
|
|
8851
|
-
/* @__PURE__ */
|
|
9407
|
+
/* @__PURE__ */ jsxs27(
|
|
8852
9408
|
"div",
|
|
8853
9409
|
{
|
|
8854
9410
|
className: cn(
|
|
@@ -8882,10 +9438,10 @@ function ContactForm({
|
|
|
8882
9438
|
}
|
|
8883
9439
|
|
|
8884
9440
|
// ../../apps/web/src/components/support-widget/sdk/use-median-contact.ts
|
|
8885
|
-
import { useCallback as
|
|
9441
|
+
import { useCallback as useCallback17, useMemo as useMemo4, useState as useState31, useSyncExternalStore as useSyncExternalStore17 } from "react";
|
|
8886
9442
|
|
|
8887
9443
|
// ../../apps/web/src/components/support-widget/sdk/contact.ts
|
|
8888
|
-
import { ConvexHttpClient as
|
|
9444
|
+
import { ConvexHttpClient as ConvexHttpClient3 } from "convex/browser";
|
|
8889
9445
|
var client2 = null;
|
|
8890
9446
|
async function deliverContact(options, message) {
|
|
8891
9447
|
const { apiKey, sessionId, user, telemetry = true } = options;
|
|
@@ -8898,11 +9454,11 @@ async function deliverContact(options, message) {
|
|
|
8898
9454
|
"The Median SDK was built without a deployment URL. Set NEXT_PUBLIC_CONVEX_URL."
|
|
8899
9455
|
);
|
|
8900
9456
|
}
|
|
8901
|
-
client2 ??= new
|
|
9457
|
+
client2 ??= new ConvexHttpClient3(MEDIAN_DEPLOYMENT_URL);
|
|
8902
9458
|
const context = telemetry ? collectContext() : void 0;
|
|
8903
9459
|
const page = telemetry ? collectPage() : void 0;
|
|
8904
9460
|
const { facts, claim } = splitIdentity(user ?? null);
|
|
8905
|
-
await client2.mutation(api.widget.
|
|
9461
|
+
await client2.mutation(api.widget.sendV2, {
|
|
8906
9462
|
apiKey,
|
|
8907
9463
|
sessionId,
|
|
8908
9464
|
body: composeBody(message),
|
|
@@ -8913,8 +9469,10 @@ async function deliverContact(options, message) {
|
|
|
8913
9469
|
...context ? { context } : {},
|
|
8914
9470
|
...page ? { page } : {},
|
|
8915
9471
|
...options.diagnostics ? { diagnostics: options.diagnostics } : {},
|
|
8916
|
-
...custom ? { customData: custom } : {}
|
|
8917
|
-
|
|
9472
|
+
...custom ? { customData: custom } : {},
|
|
9473
|
+
// Replies go to the address they typed: nothing on the page shows one.
|
|
9474
|
+
fromContactForm: true
|
|
9475
|
+
}).then(unwrapMutationResult);
|
|
8918
9476
|
} catch (caught) {
|
|
8919
9477
|
if (custom) restoreCustomData(custom);
|
|
8920
9478
|
console.error("Median: sending a contact message failed", caught);
|
|
@@ -8933,24 +9491,29 @@ async function sendMedianContact(options, message) {
|
|
|
8933
9491
|
}
|
|
8934
9492
|
|
|
8935
9493
|
// ../../apps/web/src/components/support-widget/sdk/use-median-contact.ts
|
|
8936
|
-
function useMedianContact(options) {
|
|
9494
|
+
function useMedianContact(options, caller = "useMedianContact()") {
|
|
8937
9495
|
const { apiKey, identity, user, telemetry, diagnostics, appState } = options;
|
|
8938
9496
|
const resolved = useMedianIdentity(identity);
|
|
8939
|
-
useMissingCredentials(
|
|
9497
|
+
useMissingCredentials(caller, apiKey, identity, "it cannot send");
|
|
8940
9498
|
const key = apiKey ?? resolved.apiKey;
|
|
8941
|
-
|
|
8942
|
-
|
|
9499
|
+
const showBranding = useMedianBranding(key);
|
|
9500
|
+
useApiKeyShapeWarning(caller, key);
|
|
9501
|
+
useCustomDataSender();
|
|
9502
|
+
const person = useSignedInUser(user ?? resolved.user);
|
|
8943
9503
|
useRememberInstall(key, person);
|
|
8944
|
-
const sessionId =
|
|
9504
|
+
const sessionId = useSyncExternalStore17(
|
|
8945
9505
|
subscribeSession,
|
|
8946
|
-
|
|
9506
|
+
useCallback17(
|
|
9507
|
+
() => key === void 0 ? null : getOrCreateSessionId(key),
|
|
9508
|
+
[key]
|
|
9509
|
+
),
|
|
8947
9510
|
() => null
|
|
8948
9511
|
);
|
|
8949
9512
|
const takeDiagnostics = useDiagnostics(diagnostics, appState);
|
|
8950
9513
|
const [knownEmail] = useVisitorEmail(key ?? "");
|
|
8951
|
-
const [isSending, setSending] =
|
|
8952
|
-
const [error, setError] =
|
|
8953
|
-
const send =
|
|
9514
|
+
const [isSending, setSending] = useState31(false);
|
|
9515
|
+
const [error, setError] = useState31(null);
|
|
9516
|
+
const send = useCallback17(
|
|
8954
9517
|
async (message) => {
|
|
8955
9518
|
setError(null);
|
|
8956
9519
|
if (key === void 0 || sessionId === null) {
|
|
@@ -8987,6 +9550,7 @@ function useMedianContact(options) {
|
|
|
8987
9550
|
}, [person, knownEmail]);
|
|
8988
9551
|
return {
|
|
8989
9552
|
send,
|
|
9553
|
+
showBranding,
|
|
8990
9554
|
isSending,
|
|
8991
9555
|
error,
|
|
8992
9556
|
isReady: key !== void 0 && sessionId !== null,
|
|
@@ -8997,14 +9561,16 @@ function useMedianContact(options) {
|
|
|
8997
9561
|
// ../../apps/web/src/components/support-widget/sdk/median-contact-form.tsx
|
|
8998
9562
|
import { jsx as jsx49 } from "react/jsx-runtime";
|
|
8999
9563
|
function MedianContactForm(props) {
|
|
9000
|
-
return /* @__PURE__ */ jsx49(MedianErrorBoundary, { children: /* @__PURE__ */ jsx49(ConnectedContactForm, { ...props }) });
|
|
9564
|
+
return /* @__PURE__ */ jsx49(MedianErrorBoundary, { component: "MedianContactForm", children: /* @__PURE__ */ jsx49(ConnectedContactForm, { ...props }) });
|
|
9001
9565
|
}
|
|
9002
9566
|
function useFieldComplaints(fields) {
|
|
9003
9567
|
const key = fields === void 0 ? null : JSON.stringify(fields);
|
|
9004
|
-
|
|
9568
|
+
useEffect31(() => {
|
|
9005
9569
|
if (key === null) return;
|
|
9006
9570
|
for (const complaint of fieldComplaints(JSON.parse(key))) {
|
|
9007
|
-
console.error(
|
|
9571
|
+
console.error(
|
|
9572
|
+
`Median: in the fields passed to <MedianContactForm>, ${complaint}`
|
|
9573
|
+
);
|
|
9008
9574
|
}
|
|
9009
9575
|
}, [key]);
|
|
9010
9576
|
}
|
|
@@ -9015,7 +9581,7 @@ function ConnectedContactForm({
|
|
|
9015
9581
|
onSent,
|
|
9016
9582
|
...options
|
|
9017
9583
|
}) {
|
|
9018
|
-
const contact = useMedianContact(options);
|
|
9584
|
+
const contact = useMedianContact(options, "<MedianContactForm>");
|
|
9019
9585
|
useFieldComplaints(fields);
|
|
9020
9586
|
const knownEmail = contact.user?.email || void 0;
|
|
9021
9587
|
const knownName = contact.user?.name || void 0;
|
|
@@ -9029,10 +9595,18 @@ function ConnectedContactForm({
|
|
|
9029
9595
|
return /* @__PURE__ */ jsx49(
|
|
9030
9596
|
ContactForm,
|
|
9031
9597
|
{
|
|
9598
|
+
showBadge: contact.showBranding,
|
|
9032
9599
|
fields,
|
|
9033
9600
|
onSubmit: async (message) => {
|
|
9034
9601
|
await contact.send(message);
|
|
9035
|
-
|
|
9602
|
+
try {
|
|
9603
|
+
onSent?.();
|
|
9604
|
+
} catch (caught) {
|
|
9605
|
+
console.error(
|
|
9606
|
+
"Median: onSent threw after the message was sent.",
|
|
9607
|
+
caught
|
|
9608
|
+
);
|
|
9609
|
+
}
|
|
9036
9610
|
},
|
|
9037
9611
|
notice: contact.error,
|
|
9038
9612
|
initialValues,
|