@mediansh/widget 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{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 +60 -5
- package/dist/index.js +1163 -754
- 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 useEffect24 } 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,16 +63,16 @@ 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: r38,
|
|
73
|
+
color: a29 = "currentColor",
|
|
74
|
+
size: t11 = "1em",
|
|
75
|
+
weight: o46 = "regular",
|
|
74
76
|
mirrored: i3 = false,
|
|
75
77
|
children: n,
|
|
76
78
|
weights: c8,
|
|
@@ -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: t11,
|
|
87
|
+
height: t11,
|
|
88
|
+
fill: a29,
|
|
87
89
|
viewBox: "0 0 256 256",
|
|
88
90
|
transform: i3 ? "scale(-1, 1)" : void 0,
|
|
89
91
|
...m5
|
|
90
92
|
},
|
|
91
|
-
!!
|
|
93
|
+
!!r38 && /* @__PURE__ */ e.createElement("title", null, r38),
|
|
92
94
|
n,
|
|
93
|
-
c8.get(
|
|
95
|
+
c8.get(o46)
|
|
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((e56, t11) => /* @__PURE__ */ o.createElement(w, { ref: t11, ...e56, 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((t11, e56) => /* @__PURE__ */ r2.createElement(w, { ref: e56, ...t11, 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((e56, t11) => /* @__PURE__ */ r3.createElement(w, { ref: t11, ...e56, 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((e56, s4) => /* @__PURE__ */ o4.createElement(w, { ref: s4, ...e56, 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((e56, s4) => /* @__PURE__ */ r5.createElement(w, { ref: s4, ...e56, 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((t11, e56) => /* @__PURE__ */ r6.createElement(w, { ref: e56, ...t11, 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((r38, t11) => /* @__PURE__ */ o7.createElement(w, { ref: t11, ...r38, 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((r38, t11) => /* @__PURE__ */ o8.createElement(w, { ref: t11, ...r38, 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((r38, o46) => /* @__PURE__ */ t3.createElement(w, { ref: o46, ...r38, 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((e56, r38) => /* @__PURE__ */ t4.createElement(w, { ref: r38, ...e56, 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((r38, t11) => /* @__PURE__ */ e16.createElement(w, { ref: t11, ...r38, 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((r38, t11) => /* @__PURE__ */ e20.createElement(w, { ref: t11, ...r38, 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((r38, o46) => /* @__PURE__ */ e22.createElement(w, { ref: o46, ...r38, 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((e56, r38) => /* @__PURE__ */ t5.createElement(w, { ref: r38, ...e56, 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, r38) => /* @__PURE__ */ o14.createElement(w, { ref: r38, ...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((e56, r38) => /* @__PURE__ */ o15.createElement(w, { ref: r38, ...e56, 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((r38, s4) => /* @__PURE__ */ o16.createElement(w, { ref: s4, ...r38, 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((o46, a29) => /* @__PURE__ */ e29.createElement(w, { ref: a29, ...o46, 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((o46, a29) => /* @__PURE__ */ r8.createElement(w, { ref: a29, ...o46, 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((o46, s4) => /* @__PURE__ */ e31.createElement(w, { ref: s4, ...o46, 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((o46, a29) => /* @__PURE__ */ r10.createElement(w, { ref: a29, ...o46, 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((r38, t11) => /* @__PURE__ */ o17.createElement(w, { ref: t11, ...r38, 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";
|
|
@@ -1144,57 +1153,57 @@ import * as React3 from "react";
|
|
|
1144
1153
|
|
|
1145
1154
|
// ../../node_modules/.bun/@shadcn+react@0.3.0+03aa47d54245a271/node_modules/@shadcn/react/dist/chunk-HBS6WEDP.js
|
|
1146
1155
|
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 n =
|
|
1160
|
-
for (let
|
|
1161
|
-
let
|
|
1162
|
-
if (
|
|
1163
|
-
let s4 =
|
|
1164
|
-
|
|
1156
|
+
function S({ defaultTagName: a29, props: r38, render: t11, state: n = {}, stateAttributesMapping: e56 }) {
|
|
1157
|
+
let o46 = d(R(n, e56), r38);
|
|
1158
|
+
if (!t11) return i2.createElement(a29, o46);
|
|
1159
|
+
if (typeof t11 == "function") return t11(o46, n);
|
|
1160
|
+
if (!i2.isValidElement(t11)) return null;
|
|
1161
|
+
let s4 = t11.props, u = { ...d(o46, s4), ref: f8(o46.ref, s4.ref) };
|
|
1162
|
+
return i2.cloneElement(t11, u);
|
|
1163
|
+
}
|
|
1164
|
+
function d(...a29) {
|
|
1165
|
+
let r38 = {};
|
|
1166
|
+
for (let t11 of a29) {
|
|
1167
|
+
if (!t11) continue;
|
|
1168
|
+
let n = t11;
|
|
1169
|
+
for (let e56 of Object.keys(n)) {
|
|
1170
|
+
let o46 = n[e56];
|
|
1171
|
+
if (o46 === void 0) continue;
|
|
1172
|
+
let s4 = r38[e56];
|
|
1173
|
+
e56 === "className" ? r38[e56] = [s4, o46].filter(Boolean).join(" ") : e56 === "style" ? r38[e56] = { ...s4, ...o46 } : e56 === "ref" ? r38[e56] = f8(s4, o46) : l4(e56) && typeof s4 == "function" && typeof o46 == "function" ? r38[e56] = p2(o46, s4) : r38[e56] = o46;
|
|
1165
1174
|
}
|
|
1166
1175
|
}
|
|
1167
|
-
return
|
|
1168
|
-
}
|
|
1169
|
-
function R(
|
|
1170
|
-
let
|
|
1171
|
-
for (let n of Object.keys(
|
|
1172
|
-
let
|
|
1173
|
-
if (
|
|
1174
|
-
Object.assign(
|
|
1176
|
+
return r38;
|
|
1177
|
+
}
|
|
1178
|
+
function R(a29, r38) {
|
|
1179
|
+
let t11 = {};
|
|
1180
|
+
for (let n of Object.keys(a29)) {
|
|
1181
|
+
let e56 = a29[n], o46 = r38?.[n]?.(e56);
|
|
1182
|
+
if (o46) {
|
|
1183
|
+
Object.assign(t11, o46);
|
|
1175
1184
|
continue;
|
|
1176
1185
|
}
|
|
1177
1186
|
if (n === "slot") {
|
|
1178
|
-
|
|
1187
|
+
t11["data-slot"] = e56;
|
|
1179
1188
|
continue;
|
|
1180
1189
|
}
|
|
1181
1190
|
let s4 = `data-${String(n).replace(/[A-Z]/g, (c8) => `-${c8.toLowerCase()}`)}`;
|
|
1182
|
-
typeof
|
|
1191
|
+
typeof e56 == "boolean" ? t11[s4] = e56 ? "" : void 0 : e56 != null && (t11[s4] = String(e56));
|
|
1183
1192
|
}
|
|
1184
|
-
return
|
|
1193
|
+
return t11;
|
|
1185
1194
|
}
|
|
1186
|
-
function p2(
|
|
1195
|
+
function p2(a29, r38) {
|
|
1187
1196
|
return function(n) {
|
|
1188
|
-
|
|
1197
|
+
a29(n), n.defaultPrevented || r38(n);
|
|
1189
1198
|
};
|
|
1190
1199
|
}
|
|
1191
|
-
function l4(
|
|
1192
|
-
return /^on[A-Z]/.test(
|
|
1200
|
+
function l4(a29) {
|
|
1201
|
+
return /^on[A-Z]/.test(a29);
|
|
1193
1202
|
}
|
|
1194
|
-
function f8(...
|
|
1195
|
-
let
|
|
1196
|
-
if (
|
|
1197
|
-
for (let n of
|
|
1203
|
+
function f8(...a29) {
|
|
1204
|
+
let r38 = a29.filter(Boolean);
|
|
1205
|
+
if (r38.length !== 0) return (t11) => {
|
|
1206
|
+
for (let n of r38) typeof n == "function" ? n(t11) : n && (n.current = t11);
|
|
1198
1207
|
};
|
|
1199
1208
|
}
|
|
1200
1209
|
|
|
@@ -1210,15 +1219,15 @@ var Be = /* @__PURE__ */ new Set(["ArrowDown", "ArrowUp", "End", "Home", "PageDo
|
|
|
1210
1219
|
var ge = { start: false, end: false };
|
|
1211
1220
|
var dt = [];
|
|
1212
1221
|
var Q = { currentAnchorId: null, visibleMessageIds: dt };
|
|
1213
|
-
function De({ content:
|
|
1214
|
-
if (!n || !
|
|
1215
|
-
let
|
|
1216
|
-
return { start: n.scrollTop >
|
|
1217
|
-
}
|
|
1218
|
-
function Fe({ content:
|
|
1219
|
-
if (!
|
|
1220
|
-
let S2 =
|
|
1221
|
-
for (let C of ee(
|
|
1222
|
+
function De({ content: e56, scrollEdgeThreshold: t11, spacer: r38, viewport: n }) {
|
|
1223
|
+
if (!n || !e56) return ge;
|
|
1224
|
+
let o46 = Se({ content: e56, spacer: r38, viewport: n });
|
|
1225
|
+
return { start: n.scrollTop > t11, end: o46 - n.scrollTop - n.clientHeight > t11 };
|
|
1226
|
+
}
|
|
1227
|
+
function Fe({ content: e56, scrollMargin: t11, scrollPreviousItemPeek: r38, spacer: n, viewport: o46, visibleMessageIds: i3 }) {
|
|
1228
|
+
if (!e56 || !o46) return Q;
|
|
1229
|
+
let S2 = o46.getBoundingClientRect(), l5 = S2.top + t11 + r38, d2 = typeof IntersectionObserver > "u", E = [], b2 = null;
|
|
1230
|
+
for (let C of ee(e56, n)) {
|
|
1222
1231
|
let p3 = C.dataset.messageId;
|
|
1223
1232
|
if (!p3) continue;
|
|
1224
1233
|
let m5 = C.dataset.scrollAnchor === "true", L = m5 || d2 ? C.getBoundingClientRect() : null;
|
|
@@ -1226,100 +1235,100 @@ function Fe({ content: e55, scrollMargin: t10, scrollPreviousItemPeek: r32, spac
|
|
|
1226
1235
|
}
|
|
1227
1236
|
return E.length === 0 && b2 === null ? Q : { currentAnchorId: b2, visibleMessageIds: E };
|
|
1228
1237
|
}
|
|
1229
|
-
function ee(
|
|
1230
|
-
return Array.from(
|
|
1238
|
+
function ee(e56, t11) {
|
|
1239
|
+
return Array.from(e56.children).filter((r38) => r38 instanceof HTMLElement && r38 !== t11);
|
|
1231
1240
|
}
|
|
1232
|
-
function je(
|
|
1233
|
-
for (let
|
|
1234
|
-
let n =
|
|
1241
|
+
function je(e56, t11) {
|
|
1242
|
+
for (let r38 = t11; r38 < e56.length; r38++) {
|
|
1243
|
+
let n = e56[r38];
|
|
1235
1244
|
if (n?.dataset.scrollAnchor === "true") return n;
|
|
1236
1245
|
}
|
|
1237
1246
|
return null;
|
|
1238
1247
|
}
|
|
1239
|
-
function Ge(
|
|
1240
|
-
for (let
|
|
1248
|
+
function Ge(e56, t11) {
|
|
1249
|
+
for (let r38 of e56) if (r38.dataset.scrollAnchor === "true" && !t11.has(r38)) return r38;
|
|
1241
1250
|
return null;
|
|
1242
1251
|
}
|
|
1243
|
-
function Ne(
|
|
1244
|
-
let
|
|
1245
|
-
for (let n =
|
|
1252
|
+
function Ne(e56, t11) {
|
|
1253
|
+
let r38 = 0;
|
|
1254
|
+
for (let n = t11; n < e56.length; n++) if (e56[n]?.dataset.scrollAnchor === "true" && (r38 += 1, r38 > 1)) return true;
|
|
1246
1255
|
return false;
|
|
1247
1256
|
}
|
|
1248
|
-
function Ue(
|
|
1249
|
-
for (let
|
|
1250
|
-
let
|
|
1251
|
-
if (
|
|
1257
|
+
function Ue(e56) {
|
|
1258
|
+
for (let t11 = e56.length - 1; t11 >= 0; t11--) {
|
|
1259
|
+
let r38 = e56[t11];
|
|
1260
|
+
if (r38?.dataset.scrollAnchor === "true") return r38;
|
|
1252
1261
|
}
|
|
1253
1262
|
return null;
|
|
1254
1263
|
}
|
|
1255
|
-
function Ye({ content:
|
|
1256
|
-
let n =
|
|
1257
|
-
for (let
|
|
1258
|
-
if (!
|
|
1259
|
-
let i3 =
|
|
1260
|
-
if (i3.bottom > n.top && i3.top < n.bottom) return
|
|
1264
|
+
function Ye({ content: e56, spacer: t11, viewport: r38 }) {
|
|
1265
|
+
let n = r38.getBoundingClientRect();
|
|
1266
|
+
for (let o46 of ee(e56, t11)) {
|
|
1267
|
+
if (!o46.dataset.messageId) continue;
|
|
1268
|
+
let i3 = o46.getBoundingClientRect();
|
|
1269
|
+
if (i3.bottom > n.top && i3.top < n.bottom) return o46;
|
|
1261
1270
|
}
|
|
1262
1271
|
return null;
|
|
1263
1272
|
}
|
|
1264
|
-
function ze({ align:
|
|
1265
|
-
let i3 = pe(
|
|
1266
|
-
if (
|
|
1267
|
-
let d2 = Math.max(0,
|
|
1268
|
-
return i3 - l5.start - (d2 - S2) / 2 -
|
|
1273
|
+
function ze({ align: e56, element: t11, scrollMargin: r38, spacer: n, viewport: o46 }) {
|
|
1274
|
+
let i3 = pe(t11, o46), S2 = t11.getBoundingClientRect().height, l5 = bt(n);
|
|
1275
|
+
if (e56 === "center") {
|
|
1276
|
+
let d2 = Math.max(0, o46.clientHeight - l5.start - l5.end);
|
|
1277
|
+
return i3 - l5.start - (d2 - S2) / 2 - r38;
|
|
1269
1278
|
}
|
|
1270
|
-
if (
|
|
1271
|
-
if (
|
|
1272
|
-
let d2 = i3 + S2, E =
|
|
1273
|
-
return i3 >= E && d2 <= b2 ?
|
|
1279
|
+
if (e56 === "end") return i3 - o46.clientHeight + S2 + l5.end + r38;
|
|
1280
|
+
if (e56 === "nearest") {
|
|
1281
|
+
let d2 = i3 + S2, E = o46.scrollTop + l5.start, b2 = o46.scrollTop + o46.clientHeight - l5.end;
|
|
1282
|
+
return i3 >= E && d2 <= b2 ? o46.scrollTop : i3 < E ? i3 - l5.start - r38 : d2 - o46.clientHeight + l5.end + r38;
|
|
1274
1283
|
}
|
|
1275
|
-
return i3 - l5.start -
|
|
1284
|
+
return i3 - l5.start - r38;
|
|
1276
1285
|
}
|
|
1277
|
-
function pe(
|
|
1278
|
-
let
|
|
1279
|
-
return
|
|
1286
|
+
function pe(e56, t11) {
|
|
1287
|
+
let r38 = e56.getBoundingClientRect(), n = t11.getBoundingClientRect();
|
|
1288
|
+
return r38.top - n.top + t11.scrollTop;
|
|
1280
1289
|
}
|
|
1281
|
-
function te(
|
|
1282
|
-
return
|
|
1290
|
+
function te(e56, t11) {
|
|
1291
|
+
return e56.getBoundingClientRect().top - t11.getBoundingClientRect().top;
|
|
1283
1292
|
}
|
|
1284
|
-
function qe({ content:
|
|
1285
|
-
let
|
|
1286
|
-
return
|
|
1293
|
+
function qe({ content: e56, scrollTop: t11, spacer: r38, viewport: n }) {
|
|
1294
|
+
let o46 = Se({ content: e56, spacer: r38, viewport: n });
|
|
1295
|
+
return t11 + n.clientHeight - o46;
|
|
1287
1296
|
}
|
|
1288
|
-
function Se({ content:
|
|
1289
|
-
let n = ee(
|
|
1297
|
+
function Se({ content: e56, spacer: t11, viewport: r38 }) {
|
|
1298
|
+
let n = ee(e56, t11), o46 = We(e56), i3 = r38.getBoundingClientRect(), S2 = r38.scrollTop, l5 = o46.start + o46.end;
|
|
1290
1299
|
for (let d2 of n) {
|
|
1291
1300
|
let E = d2.getBoundingClientRect();
|
|
1292
|
-
l5 = Math.max(l5, E.bottom - i3.top + S2 +
|
|
1301
|
+
l5 = Math.max(l5, E.bottom - i3.top + S2 + o46.end);
|
|
1293
1302
|
}
|
|
1294
1303
|
return l5;
|
|
1295
1304
|
}
|
|
1296
|
-
function Ke(
|
|
1297
|
-
return Math.max(0,
|
|
1305
|
+
function Ke(e56) {
|
|
1306
|
+
return Math.max(0, e56.scrollHeight - e56.clientHeight);
|
|
1298
1307
|
}
|
|
1299
|
-
function We(
|
|
1300
|
-
let
|
|
1301
|
-
return { end: Re(
|
|
1308
|
+
function We(e56) {
|
|
1309
|
+
let t11 = window.getComputedStyle(e56);
|
|
1310
|
+
return { end: Re(t11.paddingBlockEnd || t11.paddingBottom), start: Re(t11.paddingBlockStart || t11.paddingTop) };
|
|
1302
1311
|
}
|
|
1303
|
-
function bt(
|
|
1304
|
-
let
|
|
1305
|
-
return
|
|
1312
|
+
function bt(e56) {
|
|
1313
|
+
let t11 = e56?.parentElement;
|
|
1314
|
+
return t11 ? We(t11) : { end: 0, start: 0 };
|
|
1306
1315
|
}
|
|
1307
|
-
function $e(
|
|
1308
|
-
if (!
|
|
1309
|
-
let
|
|
1310
|
-
return Re(
|
|
1316
|
+
function $e(e56) {
|
|
1317
|
+
if (!e56) return 0;
|
|
1318
|
+
let t11 = window.getComputedStyle(e56), r38 = t11.rowGap === "normal" ? t11.gap : t11.rowGap;
|
|
1319
|
+
return Re(r38);
|
|
1311
1320
|
}
|
|
1312
|
-
function Re(
|
|
1313
|
-
if (!
|
|
1314
|
-
let
|
|
1315
|
-
return Number.isFinite(
|
|
1321
|
+
function Re(e56) {
|
|
1322
|
+
if (!e56) return 0;
|
|
1323
|
+
let t11 = Number.parseFloat(e56);
|
|
1324
|
+
return Number.isFinite(t11) ? t11 : 0;
|
|
1316
1325
|
}
|
|
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,
|
|
1326
|
+
function Je({ refs: e56, commitScrollState: t11, scheduleStateCommit: r38, scheduleVisibilitySync: n }) {
|
|
1327
|
+
let { streamingTurnRef: o46, 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: _ } = e56, G = g.useCallback((c8) => {
|
|
1328
|
+
l5.current !== null && (window.clearTimeout(l5.current), l5.current = null), S2.current !== c8 && (S2.current = c8, t11()), c8 && (l5.current = window.setTimeout(() => {
|
|
1329
|
+
l5.current = null, S2.current = false, t11();
|
|
1321
1330
|
}, ke));
|
|
1322
|
-
}, [
|
|
1331
|
+
}, [t11]), v = g.useCallback((c8) => {
|
|
1323
1332
|
let f9 = k.current;
|
|
1324
1333
|
if (!f9) return;
|
|
1325
1334
|
let h = Math.max(0, Math.ceil(c8));
|
|
@@ -1329,20 +1338,20 @@ function Je({ refs: e55, commitScrollState: t10, scheduleStateCommit: r32, sched
|
|
|
1329
1338
|
if (!P) return;
|
|
1330
1339
|
let V = Math.max(0, c8);
|
|
1331
1340
|
if (Math.abs(P.scrollTop - V) <= J) {
|
|
1332
|
-
P.scrollTop = V,
|
|
1341
|
+
P.scrollTop = V, t11();
|
|
1333
1342
|
return;
|
|
1334
1343
|
}
|
|
1335
|
-
h && G(true), P.scrollTo({ top: V, behavior: f9 }),
|
|
1336
|
-
}, [
|
|
1344
|
+
h && G(true), P.scrollTo({ top: V, behavior: f9 }), r38();
|
|
1345
|
+
}, [t11, r38, G]), N = g.useCallback(({ behavior: c8 = "auto" } = {}) => _.current ? (v(0), o46.current = null, p3.current = "free-scrolling", H(0, { behavior: c8 }), n(), true) : false, [n, H, v]), ne = g.useCallback(({ behavior: c8 = "auto" } = {}) => {
|
|
1337
1346
|
let f9 = _.current;
|
|
1338
|
-
return f9 ? (v(0),
|
|
1347
|
+
return f9 ? (v(0), o46.current = null, p3.current = i3.current ? "following-bottom" : "free-scrolling", H(Ke(f9), { autoscrolling: true, behavior: c8 }), n(), true) : false;
|
|
1339
1348
|
}, [n, H, v]), A = g.useCallback((c8, { align: f9 = "start", behavior: h = "auto", scrollMargin: P = y.current } = {}, { keepPreviousPeek: V = false } = {}) => {
|
|
1340
1349
|
let z = d2.current, q = _.current;
|
|
1341
1350
|
if (!z || !q || !z.contains(c8)) return false;
|
|
1342
1351
|
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",
|
|
1352
|
+
return v(se), L.current = { element: c8, viewportTop: te(c8, q) }, p3.current = V ? "anchored-to-message" : "settling-jump", o46.current = V ? c8 : null, H(K, { behavior: h }), n(), true;
|
|
1344
1353
|
}, [n, H, v]), B = g.useCallback(() => {
|
|
1345
|
-
let c8 =
|
|
1354
|
+
let c8 = o46.current;
|
|
1346
1355
|
return !c8 || !c8.isConnected || p3.current !== "anchored-to-message" ? false : A(c8, { align: "start" }, { keepPreviousPeek: true });
|
|
1347
1356
|
}, [A]), D = g.useCallback((c8, f9) => {
|
|
1348
1357
|
let h = C.current.get(c8);
|
|
@@ -1355,52 +1364,52 @@ function Je({ refs: e55, commitScrollState: t10, scheduleStateCommit: r32, sched
|
|
|
1355
1364
|
return !f9 || !A(f9, c8.options) ? false : (m5.current = null, E.current = true, true);
|
|
1356
1365
|
}, [A]), reanchorToAnchoredMessage: B, scrollToElement: A, scrollToEnd: ne, scrollToMessage: D, scrollToStart: N };
|
|
1357
1366
|
}
|
|
1358
|
-
function Qe(
|
|
1359
|
-
let
|
|
1360
|
-
return { getSnapshot: () =>
|
|
1361
|
-
|
|
1362
|
-
}, subscribe: (
|
|
1367
|
+
function Qe(e56, t11) {
|
|
1368
|
+
let r38 = e56, n = /* @__PURE__ */ new Set();
|
|
1369
|
+
return { getSnapshot: () => r38, hasListeners: () => n.size > 0, setSnapshot: (o46) => {
|
|
1370
|
+
t11(r38, o46) || (r38 = o46, n.forEach((i3) => i3()));
|
|
1371
|
+
}, subscribe: (o46, i3, S2) => {
|
|
1363
1372
|
let l5 = n.size === 0;
|
|
1364
|
-
return n.add(
|
|
1365
|
-
n.delete(
|
|
1373
|
+
return n.add(o46), l5 && i3?.(), () => {
|
|
1374
|
+
n.delete(o46), n.size === 0 && S2?.();
|
|
1366
1375
|
};
|
|
1367
1376
|
} };
|
|
1368
1377
|
}
|
|
1369
|
-
function Xe(
|
|
1370
|
-
return Qe(
|
|
1378
|
+
function Xe(e56, t11) {
|
|
1379
|
+
return Qe(e56, t11);
|
|
1371
1380
|
}
|
|
1372
1381
|
function Ze() {
|
|
1373
1382
|
return Qe(Q, Tt);
|
|
1374
1383
|
}
|
|
1375
|
-
function et(
|
|
1376
|
-
return
|
|
1384
|
+
function et(e56, t11) {
|
|
1385
|
+
return e56.start === t11.start && e56.end === t11.end;
|
|
1377
1386
|
}
|
|
1378
|
-
function Tt(
|
|
1379
|
-
return
|
|
1387
|
+
function Tt(e56, t11) {
|
|
1388
|
+
return e56.currentAnchorId !== t11.currentAnchorId || e56.visibleMessageIds.length !== t11.visibleMessageIds.length ? false : e56.visibleMessageIds.every((r38, n) => r38 === t11.visibleMessageIds[n]);
|
|
1380
1389
|
}
|
|
1381
|
-
function tt({ autoScroll:
|
|
1382
|
-
let
|
|
1383
|
-
return A.current === null && (A.current = Xe(ge, et)), f9.current === null && (f9.current = Ze()),
|
|
1390
|
+
function tt({ autoScroll: e56, scrollEdgeThreshold: t11, scrollMargin: r38, scrollPreviousItemPeek: n }) {
|
|
1391
|
+
let o46 = g.useRef(e56), i3 = g.useRef(false), S2 = g.useRef(null), l5 = g.useRef(false), d2 = g.useRef(t11), E = g.useRef(0), b2 = g.useRef(null), C = g.useRef(0), p3 = g.useRef(e56 ? "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(n), Y = g.useRef(true), k = g.useRef(null), _ = g.useRef(r38), 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());
|
|
1392
|
+
return A.current === null && (A.current = Xe(ge, et)), f9.current === null && (f9.current = Ze()), o46.current = e56, d2.current = t11, _.current = r38, x.current = n, { autoScrollRef: o46, 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
1393
|
}
|
|
1385
|
-
function rt(
|
|
1386
|
-
return g.useCallback((
|
|
1387
|
-
|
|
1388
|
-
}, [
|
|
1394
|
+
function rt(e56, t11) {
|
|
1395
|
+
return g.useCallback((r38) => {
|
|
1396
|
+
e56.current = r38, r38 && t11();
|
|
1397
|
+
}, [e56, t11]);
|
|
1389
1398
|
}
|
|
1390
|
-
function nt({ autoScroll:
|
|
1391
|
-
let i3 = tt({ autoScroll:
|
|
1392
|
-
q.current !==
|
|
1399
|
+
function nt({ autoScroll: e56 = false, defaultScrollPosition: t11 = "end", scrollEdgeThreshold: r38 = xe, scrollPreviousItemPeek: n = Ve, scrollMargin: o46 = _e }) {
|
|
1400
|
+
let i3 = tt({ autoScroll: e56, scrollEdgeThreshold: r38, scrollMargin: o46, scrollPreviousItemPeek: n }), { 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(t11);
|
|
1401
|
+
q.current !== t11 && (q.current = t11, C.current = false);
|
|
1393
1402
|
let K = g.useCallback((s4) => {
|
|
1394
|
-
let
|
|
1395
|
-
for (let W of [
|
|
1403
|
+
let a29 = G.current, T = c8.current, O = [s4.start && "start", s4.end && "end"].filter(Boolean).join(" "), ue = d2.current;
|
|
1404
|
+
for (let W of [a29, T]) W && (O ? W.setAttribute("data-scrollable", O) : W.removeAttribute("data-scrollable"), W.toggleAttribute("data-autoscrolling", ue));
|
|
1396
1405
|
}, []), se = g.useCallback((s4) => {
|
|
1397
|
-
let
|
|
1398
|
-
L.current =
|
|
1406
|
+
let a29 = c8.current?.scrollTop ?? 0, T = a29 < L.current - J;
|
|
1407
|
+
L.current = a29, 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
1408
|
}, []), F = g.useCallback(() => {
|
|
1400
1409
|
let s4 = De({ content: b2.current, scrollEdgeThreshold: v.current, spacer: B.current, viewport: c8.current });
|
|
1401
1410
|
se(s4);
|
|
1402
|
-
let
|
|
1403
|
-
K(
|
|
1411
|
+
let a29 = u.current === "following-bottom" ? { ...s4, end: false } : s4;
|
|
1412
|
+
K(a29), U.setSnapshot(a29);
|
|
1404
1413
|
}, [se, U, K]), oe = g.useCallback(() => {
|
|
1405
1414
|
D.current === null && (D.current = window.requestAnimationFrame(() => {
|
|
1406
1415
|
D.current = null, F();
|
|
@@ -1410,54 +1419,54 @@ function nt({ autoScroll: e55 = false, defaultScrollPosition: t10 = "end", scrol
|
|
|
1410
1419
|
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
1420
|
}));
|
|
1412
1421
|
}, [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 : (
|
|
1422
|
+
let s4 = k.current, a29 = c8.current;
|
|
1423
|
+
if (!s4 || !a29 || !s4.element.isConnected) return false;
|
|
1424
|
+
let O = te(s4.element, a29) - s4.viewportTop;
|
|
1425
|
+
return Math.abs(O) <= J ? false : (a29.scrollTop += O, s4.viewportTop = te(s4.element, a29), oe(), w2(), true);
|
|
1417
1426
|
}, [oe, w2]), Z = g.useCallback(() => {
|
|
1418
|
-
let s4 = b2.current,
|
|
1419
|
-
if (!s4 || !
|
|
1427
|
+
let s4 = b2.current, a29 = c8.current;
|
|
1428
|
+
if (!s4 || !a29) {
|
|
1420
1429
|
k.current = null;
|
|
1421
1430
|
return;
|
|
1422
1431
|
}
|
|
1423
|
-
let T = Ye({ content: s4, spacer: B.current, viewport:
|
|
1424
|
-
k.current = T ? { element: T, viewportTop: te(T,
|
|
1432
|
+
let T = Ye({ content: s4, spacer: B.current, viewport: a29 });
|
|
1433
|
+
k.current = T ? { element: T, viewportTop: te(T, a29) } : null;
|
|
1425
1434
|
}, []), be = g.useCallback(() => {
|
|
1426
1435
|
x.current === null && (x.current = window.requestAnimationFrame(() => {
|
|
1427
1436
|
x.current = null, ce() && Z();
|
|
1428
1437
|
}));
|
|
1429
1438
|
}, [Z, ce]), ie = g.useCallback(() => {
|
|
1430
|
-
if (!
|
|
1439
|
+
if (!t11 || C.current || m5.current === 0) return false;
|
|
1431
1440
|
let s4 = false;
|
|
1432
|
-
if (
|
|
1433
|
-
let
|
|
1434
|
-
if (!
|
|
1441
|
+
if (t11 === "last-anchor") {
|
|
1442
|
+
let a29 = b2.current, T = c8.current, O = a29 && T ? Ue(ee(a29, B.current)) : null;
|
|
1443
|
+
if (!a29 || !T || !O) s4 = I2({ behavior: "auto" });
|
|
1435
1444
|
else {
|
|
1436
1445
|
let ue = pe(O, T);
|
|
1437
|
-
s4 = Se({ content:
|
|
1446
|
+
s4 = Se({ content: a29, spacer: B.current, viewport: T }) - ue <= T.clientHeight ? I2({ behavior: "auto" }) : le(O, { align: "start" }, { keepPreviousPeek: true });
|
|
1438
1447
|
}
|
|
1439
|
-
} else s4 =
|
|
1448
|
+
} else s4 = t11 === "end" ? I2({ behavior: "auto" }) : ae({ behavior: "auto" });
|
|
1440
1449
|
return s4 ? (C.current = true, true) : false;
|
|
1441
|
-
}, [
|
|
1450
|
+
}, [t11, le, I2, ae]), Te = g.useCallback(() => {
|
|
1442
1451
|
let s4 = b2.current;
|
|
1443
1452
|
if (!s4) return;
|
|
1444
|
-
let
|
|
1445
|
-
m5.current =
|
|
1453
|
+
let a29 = ee(s4, B.current), T = m5.current, O = p3.current;
|
|
1454
|
+
m5.current = a29.length, p3.current = a29[0] ?? null, (() => {
|
|
1446
1455
|
if (ce()) return;
|
|
1447
1456
|
if (T === 0) {
|
|
1448
|
-
if (ie() ||
|
|
1457
|
+
if (ie() || a29.length > 0 && l5.current && I2({ behavior: "auto" })) return;
|
|
1449
1458
|
F(), w2();
|
|
1450
1459
|
return;
|
|
1451
1460
|
}
|
|
1452
|
-
let W = O ?
|
|
1461
|
+
let W = O ? a29.indexOf(O) : -1;
|
|
1453
1462
|
if (_.current && W > 0) {
|
|
1454
1463
|
de();
|
|
1455
1464
|
return;
|
|
1456
1465
|
}
|
|
1457
|
-
if (
|
|
1458
|
-
let $ = je(
|
|
1466
|
+
if (a29.length > T) {
|
|
1467
|
+
let $ = je(a29, T);
|
|
1459
1468
|
if ($) {
|
|
1460
|
-
if (l5.current && u.current === "following-bottom" && Ne(
|
|
1469
|
+
if (l5.current && u.current === "following-bottom" && Ne(a29, T)) {
|
|
1461
1470
|
I2({ behavior: "auto" });
|
|
1462
1471
|
return;
|
|
1463
1472
|
}
|
|
@@ -1465,8 +1474,8 @@ function nt({ autoScroll: e55 = false, defaultScrollPosition: t10 = "end", scrol
|
|
|
1465
1474
|
return;
|
|
1466
1475
|
}
|
|
1467
1476
|
}
|
|
1468
|
-
if (
|
|
1469
|
-
let $ = Ge(
|
|
1477
|
+
if (a29.length === T) {
|
|
1478
|
+
let $ = Ge(a29, z.current);
|
|
1470
1479
|
if ($) {
|
|
1471
1480
|
le($, { align: "start" }, { keepPreviousPeek: true }), z.current.add($);
|
|
1472
1481
|
return;
|
|
@@ -1492,21 +1501,21 @@ function nt({ autoScroll: e55 = false, defaultScrollPosition: t10 = "end", scrol
|
|
|
1492
1501
|
w2();
|
|
1493
1502
|
return;
|
|
1494
1503
|
}
|
|
1495
|
-
h.current || (h.current = new IntersectionObserver((
|
|
1496
|
-
for (let T of
|
|
1504
|
+
h.current || (h.current = new IntersectionObserver((a29) => {
|
|
1505
|
+
for (let T of a29) {
|
|
1497
1506
|
let O = T.target.dataset.messageId;
|
|
1498
1507
|
O && (T.isIntersecting ? V.current.add(O) : V.current.delete(O));
|
|
1499
1508
|
}
|
|
1500
1509
|
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(
|
|
1510
|
+
}, { root: s4, rootMargin: `${-(H.current + N.current)}px 0px 0px 0px`, threshold: [0, 0.01, 0.5, 1] })), y.current.forEach((a29) => {
|
|
1511
|
+
h.current?.observe(a29);
|
|
1503
1512
|
}), w2();
|
|
1504
1513
|
}
|
|
1505
1514
|
}, [w2, P]), he = g.useCallback(() => {
|
|
1506
1515
|
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,
|
|
1516
|
+
}, [P]), pt = g.useCallback((s4, a29, T) => {
|
|
1517
|
+
if (a29) {
|
|
1518
|
+
y.current.set(s4, a29), h.current?.observe(a29), w2(), Y.current?.messageId === s4 && be();
|
|
1510
1519
|
return;
|
|
1511
1520
|
}
|
|
1512
1521
|
T && y.current.get(s4) === T && (y.current.delete(s4), V.current.delete(s4), h.current?.unobserve(T), w2());
|
|
@@ -1524,38 +1533,38 @@ function nt({ autoScroll: e55 = false, defaultScrollPosition: t10 = "end", scrol
|
|
|
1524
1533
|
}, [ie]), g.useEffect(() => () => {
|
|
1525
1534
|
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
1535
|
}, []), g.useLayoutEffect(() => {
|
|
1527
|
-
if (
|
|
1536
|
+
if (e56 && u.current === "following-bottom" && m5.current > 0) {
|
|
1528
1537
|
I2({ behavior: "auto" });
|
|
1529
1538
|
return;
|
|
1530
1539
|
}
|
|
1531
1540
|
F();
|
|
1532
|
-
}, [
|
|
1541
|
+
}, [e56, F, I2]), { context: mt, registerMessage: pt };
|
|
1533
1542
|
}
|
|
1534
|
-
function lt(
|
|
1535
|
-
let
|
|
1536
|
-
return
|
|
1543
|
+
function lt(e56) {
|
|
1544
|
+
let t11 = g.useRef(e56);
|
|
1545
|
+
return t11.current = e56, t11;
|
|
1537
1546
|
}
|
|
1538
1547
|
var st = g.createContext(null);
|
|
1539
1548
|
var ct = g.createContext(null);
|
|
1540
1549
|
function X2() {
|
|
1541
|
-
let
|
|
1542
|
-
if (!
|
|
1543
|
-
return
|
|
1550
|
+
let e56 = g.useContext(st);
|
|
1551
|
+
if (!e56) throw new Error("useMessageScroller must be used within a MessageScroller.");
|
|
1552
|
+
return e56;
|
|
1544
1553
|
}
|
|
1545
1554
|
function Et() {
|
|
1546
|
-
let
|
|
1547
|
-
if (!
|
|
1548
|
-
return
|
|
1555
|
+
let e56 = g.useContext(ct);
|
|
1556
|
+
if (!e56) throw new Error("MessageScrollerItem must be used within a MessageScroller.");
|
|
1557
|
+
return e56;
|
|
1549
1558
|
}
|
|
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:
|
|
1559
|
+
function at({ autoScroll: e56 = false, children: t11, defaultScrollPosition: r38 = "end", scrollEdgeThreshold: n, scrollPreviousItemPeek: o46, scrollMargin: i3 }) {
|
|
1560
|
+
let { context: S2, registerMessage: l5 } = nt({ autoScroll: e56, defaultScrollPosition: r38, scrollEdgeThreshold: n, scrollPreviousItemPeek: o46, scrollMargin: i3 });
|
|
1561
|
+
return jsx3(st.Provider, { value: S2, children: jsx3(ct.Provider, { value: l5, children: t11 }) });
|
|
1553
1562
|
}
|
|
1554
|
-
function it({ children:
|
|
1555
|
-
let { setRootElement:
|
|
1556
|
-
return jsx3("div", { ref:
|
|
1563
|
+
function it({ children: e56, ...t11 }) {
|
|
1564
|
+
let { setRootElement: r38 } = X2();
|
|
1565
|
+
return jsx3("div", { ref: r38, ...t11, children: e56 });
|
|
1557
1566
|
}
|
|
1558
|
-
function ut({ "aria-label":
|
|
1567
|
+
function ut({ "aria-label": e56, children: t11, onKeyDown: r38, onScroll: n, onTouchMove: o46, onWheel: i3, preserveScrollOnPrepend: S2 = true, ref: l5, role: d2, tabIndex: E, ...b2 }) {
|
|
1559
1568
|
let { handleResize: C, preserveScrollOnPrependRef: p3, setViewportElement: m5, syncAfterScroll: L, userScrollIntent: y, viewportRef: u } = X2();
|
|
1560
1569
|
p3.current = S2;
|
|
1561
1570
|
let x = g.useCallback((v) => {
|
|
@@ -1568,10 +1577,10 @@ function ut({ "aria-label": e55, children: t10, onKeyDown: r32, onScroll: n, onT
|
|
|
1568
1577
|
y(), i3?.(v);
|
|
1569
1578
|
}
|
|
1570
1579
|
function _(v) {
|
|
1571
|
-
y(),
|
|
1580
|
+
y(), o46?.(v);
|
|
1572
1581
|
}
|
|
1573
1582
|
function G(v) {
|
|
1574
|
-
Be.has(v.key) && y(),
|
|
1583
|
+
Be.has(v.key) && y(), r38?.(v);
|
|
1575
1584
|
}
|
|
1576
1585
|
return g.useEffect(() => {
|
|
1577
1586
|
let v = u.current;
|
|
@@ -1582,12 +1591,12 @@ function ut({ "aria-label": e55, children: t10, onKeyDown: r32, onScroll: n, onT
|
|
|
1582
1591
|
return N.observe(v), () => {
|
|
1583
1592
|
window.cancelAnimationFrame(H), N.disconnect();
|
|
1584
1593
|
};
|
|
1585
|
-
}, [C, u]), jsx3("div", { ref: x, role: d2 ?? "region", "aria-label":
|
|
1594
|
+
}, [C, u]), jsx3("div", { ref: x, role: d2 ?? "region", "aria-label": e56 ?? "Messages", tabIndex: E ?? 0, onKeyDown: G, onScroll: Y, onTouchMove: _, onWheel: k, ...b2, children: t11 });
|
|
1586
1595
|
}
|
|
1587
|
-
function ft({ "aria-relevant":
|
|
1596
|
+
function ft({ "aria-relevant": e56, children: t11, ref: r38, role: n, spacerClassName: o46, ...i3 }) {
|
|
1588
1597
|
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
|
-
}, [
|
|
1598
|
+
b2.current = p3, d2(p3), f8(r38)?.(p3);
|
|
1599
|
+
}, [r38, d2]);
|
|
1591
1600
|
return g.useLayoutEffect(() => {
|
|
1592
1601
|
let p3 = b2.current;
|
|
1593
1602
|
if (!p3 || (S2(), typeof MutationObserver > "u")) return;
|
|
@@ -1604,23 +1613,23 @@ function ft({ "aria-relevant": e55, children: t10, ref: r32, role: n, spacerClas
|
|
|
1604
1613
|
return L.observe(p3), () => {
|
|
1605
1614
|
window.cancelAnimationFrame(m5), L.disconnect();
|
|
1606
1615
|
};
|
|
1607
|
-
}, [l5]), jsxs("div", { ref: C, role: n ?? "log", "aria-relevant":
|
|
1616
|
+
}, [l5]), jsxs("div", { ref: C, role: n ?? "log", "aria-relevant": e56 ?? "additions", ...i3, children: [t11, jsx3("div", { ref: E, "aria-hidden": "true", "data-message-scroller-spacer": "", hidden: true, className: o46 })] });
|
|
1608
1617
|
}
|
|
1609
|
-
function gt({ messageId:
|
|
1610
|
-
let
|
|
1618
|
+
function gt({ messageId: e56, ref: t11, scrollAnchor: r38 = false, ...n }) {
|
|
1619
|
+
let o46 = Et(), i3 = g.useRef(null), S2 = g.useCallback((l5) => {
|
|
1611
1620
|
let d2 = i3.current;
|
|
1612
|
-
i3.current = l5,
|
|
1613
|
-
}, [
|
|
1614
|
-
return jsx3("div", { ref: S2, "data-message-id":
|
|
1621
|
+
i3.current = l5, e56 && o46(e56, l5, d2), f8(t11)?.(l5);
|
|
1622
|
+
}, [e56, t11, o46]);
|
|
1623
|
+
return jsx3("div", { ref: S2, "data-message-id": e56, "data-scroll-anchor": r38 ? "true" : "false", ...n });
|
|
1615
1624
|
}
|
|
1616
|
-
function St({ behavior:
|
|
1625
|
+
function St({ behavior: e56 = "smooth", children: t11, direction: r38 = "end", onClick: n, render: o46, tabIndex: i3, type: S2 = "button", ...l5 }) {
|
|
1617
1626
|
let { scrollToEnd: d2, scrollToStart: E, stateStore: b$1 } = X2(), C = lt(n), p3 = g.useCallback((u) => b$1.subscribe(u), [b$1]), m5 = g.useCallback(() => {
|
|
1618
1627
|
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:
|
|
1628
|
+
return r38 === "start" ? u.start : u.end;
|
|
1629
|
+
}, [r38, b$1]), L = g.useSyncExternalStore(p3, m5, m5), y = g.useCallback((u) => {
|
|
1630
|
+
L && (C.current?.(u), u.defaultPrevented || (u.currentTarget.blur(), r38 === "start" ? E({ behavior: e56 }) : d2({ behavior: e56 })));
|
|
1631
|
+
}, [e56, r38, L, C, d2, E]);
|
|
1632
|
+
return S({ defaultTagName: "button", props: d({ type: S2, inert: !L, tabIndex: L ? i3 : -1, children: t11 ?? jsxs("span", { children: ["Scroll to ", r38] }), onClick: y }, l5), render: o46, state: { active: L, direction: r38 }, stateAttributesMapping: { active: (u) => ({ "data-active": u ? "true" : "false" }) } });
|
|
1624
1633
|
}
|
|
1625
1634
|
var $t = { Provider: at, Root: it, Viewport: ut, Content: ft, Item: gt, Button: St };
|
|
1626
1635
|
|
|
@@ -1859,14 +1868,14 @@ var use = React2[" use ".trim().toString()];
|
|
|
1859
1868
|
// ../../apps/web/src/components/ui/button.tsx
|
|
1860
1869
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1861
1870
|
var buttonVariants = cva(
|
|
1862
|
-
"group/button inline-flex shrink-0 items-center justify-center rounded-
|
|
1871
|
+
"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
1872
|
{
|
|
1864
1873
|
variants: {
|
|
1865
1874
|
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
|
|
1875
|
+
default: "surface-primary bg-primary bg-clip-border text-primary-foreground hover:bg-primary/90 active:shadow-field",
|
|
1876
|
+
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",
|
|
1877
|
+
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",
|
|
1878
|
+
ghost: "text-muted-foreground hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
1870
1879
|
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
1880
|
link: "text-primary underline-offset-4 hover:underline"
|
|
1872
1881
|
},
|
|
@@ -1907,34 +1916,6 @@ function Button({
|
|
|
1907
1916
|
);
|
|
1908
1917
|
}
|
|
1909
1918
|
|
|
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
1919
|
// ../../apps/web/src/components/ui/message-scroller.tsx
|
|
1939
1920
|
import { Fragment as Fragment25, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1940
1921
|
function MessageScrollerProvider({
|
|
@@ -1969,9 +1950,12 @@ function usePinnedToEnd(viewport) {
|
|
|
1969
1950
|
const remember = () => {
|
|
1970
1951
|
wasAtEnd = node.scrollHeight - node.scrollTop - node.clientHeight <= AT_END_PX;
|
|
1971
1952
|
};
|
|
1953
|
+
let height = node.clientHeight;
|
|
1972
1954
|
const observer = new ResizeObserver(() => {
|
|
1973
1955
|
const drift = node.scrollHeight - node.scrollTop - node.clientHeight;
|
|
1974
|
-
|
|
1956
|
+
const shrank = node.clientHeight < height;
|
|
1957
|
+
height = node.clientHeight;
|
|
1958
|
+
if (wasAtEnd && shrank && drift > DRIFT_PX) {
|
|
1975
1959
|
node.scrollTo({
|
|
1976
1960
|
top: node.scrollHeight - node.clientHeight,
|
|
1977
1961
|
behavior: "instant"
|
|
@@ -1992,11 +1976,11 @@ var MAX_STEP_MS = 64;
|
|
|
1992
1976
|
function prefersReducedMotion() {
|
|
1993
1977
|
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1994
1978
|
}
|
|
1995
|
-
function useGlidingScroll(viewport,
|
|
1996
|
-
const
|
|
1979
|
+
function useGlidingScroll(viewport, hasLanded) {
|
|
1980
|
+
const landed = React3.useRef(hasLanded);
|
|
1997
1981
|
React3.useLayoutEffect(() => {
|
|
1998
|
-
|
|
1999
|
-
}, [
|
|
1982
|
+
landed.current = hasLanded;
|
|
1983
|
+
}, [hasLanded]);
|
|
2000
1984
|
React3.useEffect(() => {
|
|
2001
1985
|
const node = viewport.current;
|
|
2002
1986
|
if (!node) return;
|
|
@@ -2004,6 +1988,7 @@ function useGlidingScroll(viewport, isSettled) {
|
|
|
2004
1988
|
let target = null;
|
|
2005
1989
|
let frame = 0;
|
|
2006
1990
|
let last = 0;
|
|
1991
|
+
let box = { width: node.clientWidth, height: node.clientHeight };
|
|
2007
1992
|
const stop = () => {
|
|
2008
1993
|
if (frame !== 0) cancelAnimationFrame(frame);
|
|
2009
1994
|
frame = 0;
|
|
@@ -2012,11 +1997,12 @@ function useGlidingScroll(viewport, isSettled) {
|
|
|
2012
1997
|
const step = (now) => {
|
|
2013
1998
|
frame = 0;
|
|
2014
1999
|
if (target === null) return;
|
|
2015
|
-
const elapsed = Math.min(now - last, MAX_STEP_MS);
|
|
2000
|
+
const elapsed = Math.max(0, Math.min(now - last, MAX_STEP_MS));
|
|
2016
2001
|
last = now;
|
|
2017
|
-
const
|
|
2002
|
+
const goal = Math.min(target, node.scrollHeight - node.clientHeight);
|
|
2003
|
+
const left = goal - node.scrollTop;
|
|
2018
2004
|
if (Math.abs(left) < 0.5) {
|
|
2019
|
-
node.scrollTop =
|
|
2005
|
+
node.scrollTop = goal;
|
|
2020
2006
|
target = null;
|
|
2021
2007
|
return;
|
|
2022
2008
|
}
|
|
@@ -2025,7 +2011,10 @@ function useGlidingScroll(viewport, isSettled) {
|
|
|
2025
2011
|
};
|
|
2026
2012
|
const glide = (options, y) => {
|
|
2027
2013
|
const asked = typeof options === "number" ? { left: options, top: y } : options;
|
|
2028
|
-
const
|
|
2014
|
+
const size = { width: node.clientWidth, height: node.clientHeight };
|
|
2015
|
+
const shrank = size.width !== box.width || size.height < box.height;
|
|
2016
|
+
box = size;
|
|
2017
|
+
const glides = asked !== void 0 && typeof asked.top === "number" && asked.behavior !== "instant" && landed.current && !shrank && !prefersReducedMotion();
|
|
2029
2018
|
if (!glides) {
|
|
2030
2019
|
stop();
|
|
2031
2020
|
scrollNatively.call(node, asked);
|
|
@@ -2070,10 +2059,8 @@ function MessageScrollerViewport({
|
|
|
2070
2059
|
}) {
|
|
2071
2060
|
const viewport = React3.useRef(null);
|
|
2072
2061
|
const hasLanded = useHasLanded();
|
|
2073
|
-
const isResizing = useIsResizing(viewport);
|
|
2074
|
-
const isSettled = hasLanded && !isResizing;
|
|
2075
2062
|
usePinnedToEnd(viewport);
|
|
2076
|
-
useGlidingScroll(viewport,
|
|
2063
|
+
useGlidingScroll(viewport, hasLanded);
|
|
2077
2064
|
const holdViewport = React3.useCallback(
|
|
2078
2065
|
(node) => {
|
|
2079
2066
|
viewport.current = node;
|
|
@@ -2087,7 +2074,6 @@ function MessageScrollerViewport({
|
|
|
2087
2074
|
{
|
|
2088
2075
|
ref: holdViewport,
|
|
2089
2076
|
"data-slot": "message-scroller-viewport",
|
|
2090
|
-
"data-settled": isSettled ? "" : void 0,
|
|
2091
2077
|
className: cn(
|
|
2092
2078
|
"size-full min-h-0 min-w-0 overflow-y-auto overscroll-contain contain-content [scrollbar-gutter:stable] [scrollbar-width:thin]",
|
|
2093
2079
|
// The fade says "there is more below", so it only belongs to a
|
|
@@ -2266,9 +2252,9 @@ var SETTLE_BODY = cn(
|
|
|
2266
2252
|
|
|
2267
2253
|
// ../../apps/web/src/components/support-widget/widget-composer.tsx
|
|
2268
2254
|
import {
|
|
2269
|
-
useEffect as
|
|
2270
|
-
useRef as
|
|
2271
|
-
useState as
|
|
2255
|
+
useEffect as useEffect5,
|
|
2256
|
+
useRef as useRef8,
|
|
2257
|
+
useState as useState4
|
|
2272
2258
|
} from "react";
|
|
2273
2259
|
|
|
2274
2260
|
// src/next-image-shim.tsx
|
|
@@ -2296,7 +2282,7 @@ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
|
2296
2282
|
var KIND_ICONS = {
|
|
2297
2283
|
image: ImageSquare,
|
|
2298
2284
|
video: Play,
|
|
2299
|
-
file:
|
|
2285
|
+
file: File2
|
|
2300
2286
|
};
|
|
2301
2287
|
function AttachmentDraftChip({
|
|
2302
2288
|
draft,
|
|
@@ -2369,7 +2355,7 @@ function AttachmentDraftChip({
|
|
|
2369
2355
|
}
|
|
2370
2356
|
|
|
2371
2357
|
// ../../apps/web/src/components/attachments/use-attachment-drafts.ts
|
|
2372
|
-
import { useEffect as
|
|
2358
|
+
import { useEffect as useEffect3, useRef as useRef4, useState as useState2 } from "react";
|
|
2373
2359
|
var MAX_BYTES = 25 * 1024 * 1024;
|
|
2374
2360
|
var UNSAFE_TYPES = [
|
|
2375
2361
|
"text/html",
|
|
@@ -2410,12 +2396,12 @@ function useAttachmentDrafts({
|
|
|
2410
2396
|
accept,
|
|
2411
2397
|
max
|
|
2412
2398
|
} = {}) {
|
|
2413
|
-
const [drafts, setDrafts] =
|
|
2399
|
+
const [drafts, setDrafts] = useState2([]);
|
|
2414
2400
|
const draftsRef = useRef4(drafts);
|
|
2415
|
-
|
|
2401
|
+
useEffect3(() => {
|
|
2416
2402
|
draftsRef.current = drafts;
|
|
2417
2403
|
}, [drafts]);
|
|
2418
|
-
|
|
2404
|
+
useEffect3(() => () => draftsRef.current.forEach(release), []);
|
|
2419
2405
|
function add(files) {
|
|
2420
2406
|
const picked = Array.from(files).map((file, index) => {
|
|
2421
2407
|
const isTooBig = file.size > MAX_BYTES;
|
|
@@ -2460,12 +2446,12 @@ function useAttachmentDrafts({
|
|
|
2460
2446
|
}
|
|
2461
2447
|
|
|
2462
2448
|
// ../../apps/web/src/components/attachments/use-attachment-target.ts
|
|
2463
|
-
import { useRef as useRef5, useState as
|
|
2449
|
+
import { useRef as useRef5, useState as useState3 } from "react";
|
|
2464
2450
|
function useAttachmentTarget({
|
|
2465
2451
|
onFiles,
|
|
2466
2452
|
disabled = false
|
|
2467
2453
|
}) {
|
|
2468
|
-
const [isDropTarget, setIsDropTarget] =
|
|
2454
|
+
const [isDropTarget, setIsDropTarget] = useState3(false);
|
|
2469
2455
|
const depth = useRef5(0);
|
|
2470
2456
|
function handleDragEnter(event) {
|
|
2471
2457
|
if (disabled || !event.dataTransfer.types.includes("Files")) return;
|
|
@@ -2561,12 +2547,10 @@ function WidgetButton({
|
|
|
2561
2547
|
);
|
|
2562
2548
|
}
|
|
2563
2549
|
|
|
2564
|
-
// ../../apps/web/src/components/
|
|
2565
|
-
var
|
|
2550
|
+
// ../../apps/web/src/components/support-widget/widget-field.ts
|
|
2551
|
+
var WIDGET_TEXT_FIELD_SHELL = [
|
|
2566
2552
|
"rounded-lg border border-input bg-transparent text-sm max-sm:text-base transition-[color,box-shadow] outline-none dark:bg-input/30",
|
|
2567
2553
|
"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
2554
|
"focus-within:border-ring",
|
|
2571
2555
|
"aria-invalid:border-destructive",
|
|
2572
2556
|
"disabled:pointer-events-none disabled:opacity-50"
|
|
@@ -2591,12 +2575,12 @@ function Textarea({ className, ...props }) {
|
|
|
2591
2575
|
}
|
|
2592
2576
|
|
|
2593
2577
|
// ../../apps/web/src/hooks/use-typing-signal.ts
|
|
2594
|
-
import { useCallback as useCallback5, useEffect as
|
|
2578
|
+
import { useCallback as useCallback5, useEffect as useEffect4, useRef as useRef6 } from "react";
|
|
2595
2579
|
var REFRESH_MS = 2500;
|
|
2596
2580
|
var IDLE_MS = 8e3;
|
|
2597
2581
|
function useTypingSignal(onChange) {
|
|
2598
2582
|
const onChangeRef = useRef6(onChange);
|
|
2599
|
-
|
|
2583
|
+
useEffect4(() => {
|
|
2600
2584
|
onChangeRef.current = onChange;
|
|
2601
2585
|
}, [onChange]);
|
|
2602
2586
|
const isTypingRef = useRef6(false);
|
|
@@ -2630,10 +2614,33 @@ function useTypingSignal(onChange) {
|
|
|
2630
2614
|
send(true);
|
|
2631
2615
|
}
|
|
2632
2616
|
}, [send, stop]);
|
|
2633
|
-
|
|
2617
|
+
useEffect4(() => () => stop(), [stop]);
|
|
2634
2618
|
return { ping, stop, settle };
|
|
2635
2619
|
}
|
|
2636
2620
|
|
|
2621
|
+
// ../../apps/web/src/components/support-widget/use-eased-height.ts
|
|
2622
|
+
import { useLayoutEffect as useLayoutEffect4, useRef as useRef7 } from "react";
|
|
2623
|
+
function useEasedHeight(field) {
|
|
2624
|
+
const box = useRef7(null);
|
|
2625
|
+
useLayoutEffect4(() => {
|
|
2626
|
+
const outer = box.current;
|
|
2627
|
+
const inner = field.current;
|
|
2628
|
+
if (!outer || !inner) return;
|
|
2629
|
+
const follow = () => {
|
|
2630
|
+
outer.style.height = `${inner.offsetHeight}px`;
|
|
2631
|
+
};
|
|
2632
|
+
follow();
|
|
2633
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
2634
|
+
const observer = new ResizeObserver(follow);
|
|
2635
|
+
observer.observe(inner);
|
|
2636
|
+
return () => {
|
|
2637
|
+
observer.disconnect();
|
|
2638
|
+
outer.style.height = "";
|
|
2639
|
+
};
|
|
2640
|
+
}, [field]);
|
|
2641
|
+
return box;
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2637
2644
|
// ../../apps/web/src/components/brand-art.ts
|
|
2638
2645
|
var BRAND_INK = "#191919";
|
|
2639
2646
|
var LOGO = {
|
|
@@ -2661,7 +2668,7 @@ var LOGO_MASK_URL = `url("data:image/svg+xml,${encodeURIComponent(
|
|
|
2661
2668
|
)}")`;
|
|
2662
2669
|
|
|
2663
2670
|
// ../../apps/web/src/components/brand.tsx
|
|
2664
|
-
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2671
|
+
import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2665
2672
|
var INVERT_IN_DARK = "dark:invert";
|
|
2666
2673
|
function Wordmark({
|
|
2667
2674
|
width = 132,
|
|
@@ -2726,10 +2733,10 @@ function ShimmerLogo({
|
|
|
2726
2733
|
}
|
|
2727
2734
|
|
|
2728
2735
|
// ../../apps/web/src/components/support-widget/widget-badge.tsx
|
|
2729
|
-
import { jsx as jsx12, jsxs as
|
|
2736
|
+
import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2730
2737
|
var MEDIAN_URL = "https://median.sh";
|
|
2731
2738
|
function PoweredByMedian({ className }) {
|
|
2732
|
-
return /* @__PURE__ */
|
|
2739
|
+
return /* @__PURE__ */ jsxs5(
|
|
2733
2740
|
"a",
|
|
2734
2741
|
{
|
|
2735
2742
|
href: MEDIAN_URL,
|
|
@@ -2754,12 +2761,13 @@ function PoweredByMedian({ className }) {
|
|
|
2754
2761
|
}
|
|
2755
2762
|
|
|
2756
2763
|
// ../../apps/web/src/components/support-widget/widget-composer.tsx
|
|
2757
|
-
import { Fragment as Fragment26, jsx as jsx13, jsxs as
|
|
2764
|
+
import { Fragment as Fragment26, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2758
2765
|
var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2759
2766
|
var SWAP = "transition-[opacity,translate] duration-300 ease-out motion-reduce:transition-none";
|
|
2760
2767
|
var RISE = "transition-transform duration-450 ease-spring motion-reduce:transition-none";
|
|
2761
2768
|
var SINK = "transition-transform duration-250 ease-in motion-reduce:transition-none";
|
|
2762
2769
|
var ROLL = "transition-transform duration-350 ease-out-quint motion-reduce:transition-none";
|
|
2770
|
+
var GROW = "transition-[height] duration-200 ease-out-quint motion-reduce:transition-none";
|
|
2763
2771
|
var SAVED_MS = 1200;
|
|
2764
2772
|
function WidgetComposer({
|
|
2765
2773
|
onSend,
|
|
@@ -2773,11 +2781,12 @@ function WidgetComposer({
|
|
|
2773
2781
|
compact = false
|
|
2774
2782
|
}) {
|
|
2775
2783
|
const isStacked = variant === "stacked";
|
|
2776
|
-
const [draft, setDraft] =
|
|
2777
|
-
const [email, setEmail] =
|
|
2778
|
-
const [answer, setAnswer] =
|
|
2779
|
-
const fileInputRef =
|
|
2780
|
-
const draftRef =
|
|
2784
|
+
const [draft, setDraft] = useState4("");
|
|
2785
|
+
const [email, setEmail] = useState4("");
|
|
2786
|
+
const [answer, setAnswer] = useState4("none");
|
|
2787
|
+
const fileInputRef = useRef8(null);
|
|
2788
|
+
const draftRef = useRef8(null);
|
|
2789
|
+
const draftBoxRef = useEasedHeight(draftRef);
|
|
2781
2790
|
const attachments = useAttachmentDrafts();
|
|
2782
2791
|
const target = useAttachmentTarget({ onFiles: attachments.add });
|
|
2783
2792
|
const typing = useTypingSignal(onTypingChange);
|
|
@@ -2793,12 +2802,12 @@ function WidgetComposer({
|
|
|
2793
2802
|
setAnswer("saved");
|
|
2794
2803
|
onSubmitEmail(email.trim());
|
|
2795
2804
|
}
|
|
2796
|
-
|
|
2805
|
+
useEffect5(() => {
|
|
2797
2806
|
if (answer !== "saved") return;
|
|
2798
2807
|
const timer = setTimeout(() => setAnswer("settled"), SAVED_MS);
|
|
2799
2808
|
return () => clearTimeout(timer);
|
|
2800
2809
|
}, [answer]);
|
|
2801
|
-
|
|
2810
|
+
useEffect5(() => {
|
|
2802
2811
|
if (answer !== "saved" || askForEmail) return;
|
|
2803
2812
|
draftRef.current?.focus({ preventScroll: true });
|
|
2804
2813
|
}, [answer, askForEmail]);
|
|
@@ -2848,24 +2857,42 @@ function WidgetComposer({
|
|
|
2848
2857
|
children: /* @__PURE__ */ jsx13(Plus, { className: isStacked ? "size-5" : void 0 })
|
|
2849
2858
|
}
|
|
2850
2859
|
);
|
|
2851
|
-
const draftBox =
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2860
|
+
const draftBox = (
|
|
2861
|
+
// The field sizes itself to its words and sits at the foot of the box,
|
|
2862
|
+
// so a line that wraps stays where it was typed and the box's top edge
|
|
2863
|
+
// rises to take the first line in: the composer grows upward, and the
|
|
2864
|
+
// words hold still under the caret. The box follows the field on a
|
|
2865
|
+
// curve and clips whatever it is behind by.
|
|
2866
|
+
/* @__PURE__ */ jsx13(
|
|
2867
|
+
"div",
|
|
2868
|
+
{
|
|
2869
|
+
ref: draftBoxRef,
|
|
2870
|
+
className: cn(
|
|
2871
|
+
"flex flex-col justify-end overflow-clip",
|
|
2872
|
+
isStacked ? "w-full" : "min-w-0 flex-1",
|
|
2873
|
+
draft.length > 0 && GROW
|
|
2874
|
+
),
|
|
2875
|
+
children: /* @__PURE__ */ jsx13(
|
|
2876
|
+
Textarea,
|
|
2877
|
+
{
|
|
2878
|
+
ref: draftRef,
|
|
2879
|
+
rows: 1,
|
|
2880
|
+
value: draft,
|
|
2881
|
+
onChange: (event) => {
|
|
2882
|
+
setDraft(event.target.value);
|
|
2883
|
+
typing.ping();
|
|
2884
|
+
},
|
|
2885
|
+
onKeyDown: handleKeyDown,
|
|
2886
|
+
placeholder: target.isDropTarget ? "Drop to attach" : placeholder,
|
|
2887
|
+
"aria-label": "Message",
|
|
2888
|
+
className: cn(
|
|
2889
|
+
"max-h-40 shrink-0 max-sm:text-[16px]",
|
|
2890
|
+
isStacked ? "min-h-9 px-2 pt-1.5 pb-1 text-sm" : "min-h-10 px-2 py-2 text-base"
|
|
2891
|
+
)
|
|
2892
|
+
}
|
|
2893
|
+
)
|
|
2894
|
+
}
|
|
2895
|
+
)
|
|
2869
2896
|
);
|
|
2870
2897
|
const sendButton = /* @__PURE__ */ jsx13(
|
|
2871
2898
|
WidgetButton,
|
|
@@ -2925,7 +2952,7 @@ function WidgetComposer({
|
|
|
2925
2952
|
// anyway. Paste rides on the same element, so it is caught wherever the
|
|
2926
2953
|
// caret happens to be inside the composer. None of that while the email
|
|
2927
2954
|
// is asked for: there is no message yet to attach anything to.
|
|
2928
|
-
/* @__PURE__ */
|
|
2955
|
+
/* @__PURE__ */ jsxs6(
|
|
2929
2956
|
"div",
|
|
2930
2957
|
{
|
|
2931
2958
|
className: cn(
|
|
@@ -2941,7 +2968,7 @@ function WidgetComposer({
|
|
|
2941
2968
|
onRemove: () => attachments.remove(item.id)
|
|
2942
2969
|
}
|
|
2943
2970
|
) }, item.id)) }),
|
|
2944
|
-
/* @__PURE__ */
|
|
2971
|
+
/* @__PURE__ */ jsxs6("div", { className: "relative", children: [
|
|
2945
2972
|
/* @__PURE__ */ jsx13(
|
|
2946
2973
|
"div",
|
|
2947
2974
|
{
|
|
@@ -2958,8 +2985,8 @@ function WidgetComposer({
|
|
|
2958
2985
|
showTab ? RISE : SINK,
|
|
2959
2986
|
!showTab && "translate-y-full"
|
|
2960
2987
|
),
|
|
2961
|
-
children: /* @__PURE__ */
|
|
2962
|
-
/* @__PURE__ */
|
|
2988
|
+
children: /* @__PURE__ */ jsxs6("span", { className: "grid overflow-hidden", children: [
|
|
2989
|
+
/* @__PURE__ */ jsxs6(
|
|
2963
2990
|
"span",
|
|
2964
2991
|
{
|
|
2965
2992
|
"aria-hidden": isSaved,
|
|
@@ -2974,7 +3001,7 @@ function WidgetComposer({
|
|
|
2974
3001
|
]
|
|
2975
3002
|
}
|
|
2976
3003
|
),
|
|
2977
|
-
/* @__PURE__ */
|
|
3004
|
+
/* @__PURE__ */ jsxs6(
|
|
2978
3005
|
"span",
|
|
2979
3006
|
{
|
|
2980
3007
|
"aria-hidden": !isSaved,
|
|
@@ -2994,11 +3021,11 @@ function WidgetComposer({
|
|
|
2994
3021
|
)
|
|
2995
3022
|
}
|
|
2996
3023
|
),
|
|
2997
|
-
/* @__PURE__ */
|
|
3024
|
+
/* @__PURE__ */ jsxs6(
|
|
2998
3025
|
"div",
|
|
2999
3026
|
{
|
|
3000
3027
|
className: cn(
|
|
3001
|
-
|
|
3028
|
+
WIDGET_TEXT_FIELD_SHELL,
|
|
3002
3029
|
"relative z-10 grid bg-card p-2 transition-colors dark:bg-card",
|
|
3003
3030
|
// Half the pill's one line height, so it is a full pill at one
|
|
3004
3031
|
// line and keeps those corners as it grows. The box keeps a
|
|
@@ -3020,17 +3047,17 @@ function WidgetComposer({
|
|
|
3020
3047
|
SWAP,
|
|
3021
3048
|
isAsking && "-translate-y-1 opacity-0 pointer-events-none"
|
|
3022
3049
|
),
|
|
3023
|
-
children: isStacked ? /* @__PURE__ */
|
|
3050
|
+
children: isStacked ? /* @__PURE__ */ jsxs6(Fragment26, { children: [
|
|
3024
3051
|
draftBox,
|
|
3025
|
-
/* @__PURE__ */
|
|
3052
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5", children: [
|
|
3026
3053
|
fileInput,
|
|
3027
3054
|
addButton,
|
|
3028
|
-
/* @__PURE__ */
|
|
3055
|
+
/* @__PURE__ */ jsxs6("div", { className: "ml-auto flex items-center gap-2", children: [
|
|
3029
3056
|
badge,
|
|
3030
3057
|
sendButton
|
|
3031
3058
|
] })
|
|
3032
3059
|
] })
|
|
3033
|
-
] }) : /* @__PURE__ */
|
|
3060
|
+
] }) : /* @__PURE__ */ jsxs6(Fragment26, { children: [
|
|
3034
3061
|
fileInput,
|
|
3035
3062
|
addButton,
|
|
3036
3063
|
draftBox,
|
|
@@ -3049,13 +3076,13 @@ function WidgetComposer({
|
|
|
3049
3076
|
SWAP,
|
|
3050
3077
|
!isAsking && "pointer-events-none translate-y-1 opacity-0"
|
|
3051
3078
|
),
|
|
3052
|
-
children: isStacked ? /* @__PURE__ */
|
|
3079
|
+
children: isStacked ? /* @__PURE__ */ jsxs6(Fragment26, { children: [
|
|
3053
3080
|
emailBox,
|
|
3054
|
-
/* @__PURE__ */
|
|
3081
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-end gap-2", children: [
|
|
3055
3082
|
badge,
|
|
3056
3083
|
emailButton
|
|
3057
3084
|
] })
|
|
3058
|
-
] }) : /* @__PURE__ */
|
|
3085
|
+
] }) : /* @__PURE__ */ jsxs6(Fragment26, { children: [
|
|
3059
3086
|
emailBox,
|
|
3060
3087
|
emailButton
|
|
3061
3088
|
] })
|
|
@@ -3072,13 +3099,17 @@ function WidgetComposer({
|
|
|
3072
3099
|
);
|
|
3073
3100
|
}
|
|
3074
3101
|
|
|
3102
|
+
// ../../apps/web/src/components/support-widget/widget-corner.ts
|
|
3103
|
+
var WIDGET_RADIUS = "0.875rem";
|
|
3104
|
+
var WIDGET_CORNER = "rounded-[0.875rem]";
|
|
3105
|
+
|
|
3075
3106
|
// ../../apps/web/src/components/support-widget/widget-destination.tsx
|
|
3076
|
-
import { jsx as jsx14, jsxs as
|
|
3107
|
+
import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3077
3108
|
function WidgetDestination({
|
|
3078
3109
|
destination,
|
|
3079
3110
|
onFollow
|
|
3080
3111
|
}) {
|
|
3081
|
-
return /* @__PURE__ */
|
|
3112
|
+
return /* @__PURE__ */ jsxs7(
|
|
3082
3113
|
WidgetButton,
|
|
3083
3114
|
{
|
|
3084
3115
|
type: "button",
|
|
@@ -3100,10 +3131,24 @@ function WidgetDestination({
|
|
|
3100
3131
|
}
|
|
3101
3132
|
|
|
3102
3133
|
// ../../apps/web/src/components/avatar.tsx
|
|
3103
|
-
import { useState as
|
|
3134
|
+
import { useState as useState5 } from "react";
|
|
3104
3135
|
|
|
3105
3136
|
// ../../apps/web/src/components/initial-badge.tsx
|
|
3106
3137
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
3138
|
+
var TONES = [
|
|
3139
|
+
"bg-[var(--avatar-blue,#e0edfa)] text-[var(--avatar-blue-foreground,#37628c)]",
|
|
3140
|
+
"bg-[var(--avatar-violet,#eae4f7)] text-[var(--avatar-violet-foreground,#705894)]",
|
|
3141
|
+
"bg-[var(--avatar-amber,#f8ead6)] text-[var(--avatar-amber-foreground,#8b6434)]",
|
|
3142
|
+
"bg-[var(--avatar-teal,#dbefea)] text-[var(--avatar-teal-foreground,#3c766d)]",
|
|
3143
|
+
"bg-[var(--avatar-rose,#f5e2e8)] text-[var(--avatar-rose-foreground,#92586c)]"
|
|
3144
|
+
];
|
|
3145
|
+
function toneFor(value) {
|
|
3146
|
+
let hash = 0;
|
|
3147
|
+
for (const character of value.trim().toLowerCase()) {
|
|
3148
|
+
hash = hash * 31 + character.charCodeAt(0) >>> 0;
|
|
3149
|
+
}
|
|
3150
|
+
return TONES[hash % TONES.length];
|
|
3151
|
+
}
|
|
3107
3152
|
function InitialBadge({
|
|
3108
3153
|
value,
|
|
3109
3154
|
className
|
|
@@ -3114,7 +3159,8 @@ function InitialBadge({
|
|
|
3114
3159
|
"aria-hidden": true,
|
|
3115
3160
|
className: cn(
|
|
3116
3161
|
// 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-
|
|
3162
|
+
"surface-control grid size-4.5 shrink-0 place-items-center rounded border border-foreground/5 text-[10px] font-medium",
|
|
3163
|
+
toneFor(value),
|
|
3118
3164
|
className
|
|
3119
3165
|
),
|
|
3120
3166
|
children: value.trim().charAt(0).toUpperCase() || "?"
|
|
@@ -3131,7 +3177,7 @@ function Avatar({
|
|
|
3131
3177
|
unoptimized = false,
|
|
3132
3178
|
className
|
|
3133
3179
|
}) {
|
|
3134
|
-
const [failedSrc, setFailedSrc] =
|
|
3180
|
+
const [failedSrc, setFailedSrc] = useState5(null);
|
|
3135
3181
|
const hasFailed = failedSrc !== null && failedSrc === src;
|
|
3136
3182
|
const shape2 = "size-4.5 shrink-0 rounded-full";
|
|
3137
3183
|
if (!src || hasFailed) {
|
|
@@ -3139,7 +3185,7 @@ function Avatar({
|
|
|
3139
3185
|
InitialBadge,
|
|
3140
3186
|
{
|
|
3141
3187
|
value: name,
|
|
3142
|
-
className: cn(shape2, "border-none
|
|
3188
|
+
className: cn(shape2, "border-none text-[10px]", className)
|
|
3143
3189
|
}
|
|
3144
3190
|
);
|
|
3145
3191
|
}
|
|
@@ -3153,7 +3199,7 @@ function Avatar({
|
|
|
3153
3199
|
unoptimized,
|
|
3154
3200
|
onError: () => setFailedSrc(src),
|
|
3155
3201
|
draggable: false,
|
|
3156
|
-
className: cn(shape2, "bg-muted object-cover", className)
|
|
3202
|
+
className: cn(shape2, "bg-muted object-cover ring-1 ring-foreground/5", className)
|
|
3157
3203
|
}
|
|
3158
3204
|
);
|
|
3159
3205
|
}
|
|
@@ -3192,7 +3238,7 @@ function WidgetAvatar({
|
|
|
3192
3238
|
{
|
|
3193
3239
|
src: agent.avatarUrl,
|
|
3194
3240
|
name: agent.name,
|
|
3195
|
-
className: "size-full rounded-[inherit]"
|
|
3241
|
+
className: "size-full rounded-[inherit] bg-muted bg-none font-semibold text-muted-foreground shadow-none ring-0"
|
|
3196
3242
|
}
|
|
3197
3243
|
)
|
|
3198
3244
|
}
|
|
@@ -3215,7 +3261,7 @@ function WidgetAvatarStack({
|
|
|
3215
3261
|
}
|
|
3216
3262
|
|
|
3217
3263
|
// ../../apps/web/src/components/support-widget/widget-empty.tsx
|
|
3218
|
-
import { jsx as jsx18, jsxs as
|
|
3264
|
+
import { jsx as jsx18, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3219
3265
|
var STARTERS = [
|
|
3220
3266
|
{
|
|
3221
3267
|
label: "Ask a question",
|
|
@@ -3242,7 +3288,7 @@ function WidgetEmpty({
|
|
|
3242
3288
|
compact = false
|
|
3243
3289
|
}) {
|
|
3244
3290
|
const agent = team.find((member) => member.kind === "ai") ?? team[0];
|
|
3245
|
-
return /* @__PURE__ */
|
|
3291
|
+
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
3292
|
agent && /* @__PURE__ */ jsx18(
|
|
3247
3293
|
WidgetAvatar,
|
|
3248
3294
|
{
|
|
@@ -3253,7 +3299,7 @@ function WidgetEmpty({
|
|
|
3253
3299
|
)
|
|
3254
3300
|
}
|
|
3255
3301
|
),
|
|
3256
|
-
/* @__PURE__ */
|
|
3302
|
+
/* @__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
3303
|
agent && /* @__PURE__ */ jsx18(
|
|
3258
3304
|
"p",
|
|
3259
3305
|
{
|
|
@@ -3275,7 +3321,7 @@ function WidgetEmpty({
|
|
|
3275
3321
|
}
|
|
3276
3322
|
)
|
|
3277
3323
|
] }),
|
|
3278
|
-
onPick && /* @__PURE__ */ jsx18("div", { className: "flex w-full max-w-md flex-col gap-2 pt-1", children: STARTERS.map((starter, index) => /* @__PURE__ */
|
|
3324
|
+
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
3325
|
WidgetButton,
|
|
3280
3326
|
{
|
|
3281
3327
|
type: "button",
|
|
@@ -3316,7 +3362,7 @@ function WidgetEmpty({
|
|
|
3316
3362
|
}
|
|
3317
3363
|
|
|
3318
3364
|
// ../../apps/web/src/components/support-widget/widget-header.tsx
|
|
3319
|
-
import { jsx as jsx19, jsxs as
|
|
3365
|
+
import { jsx as jsx19, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3320
3366
|
function WidgetHeader({
|
|
3321
3367
|
presence,
|
|
3322
3368
|
onClose,
|
|
@@ -3327,7 +3373,7 @@ function WidgetHeader({
|
|
|
3327
3373
|
compact = false,
|
|
3328
3374
|
className
|
|
3329
3375
|
}) {
|
|
3330
|
-
return /* @__PURE__ */
|
|
3376
|
+
return /* @__PURE__ */ jsxs9(
|
|
3331
3377
|
"header",
|
|
3332
3378
|
{
|
|
3333
3379
|
...grabHandlers,
|
|
@@ -3344,7 +3390,7 @@ function WidgetHeader({
|
|
|
3344
3390
|
]
|
|
3345
3391
|
),
|
|
3346
3392
|
children: [
|
|
3347
|
-
/* @__PURE__ */
|
|
3393
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex min-w-0 flex-1 flex-col pt-0.5", children: [
|
|
3348
3394
|
/* @__PURE__ */ jsx19(
|
|
3349
3395
|
"h2",
|
|
3350
3396
|
{
|
|
@@ -3366,7 +3412,7 @@ function WidgetHeader({
|
|
|
3366
3412
|
}
|
|
3367
3413
|
)
|
|
3368
3414
|
] }),
|
|
3369
|
-
/* @__PURE__ */
|
|
3415
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex shrink-0 items-center gap-3", children: [
|
|
3370
3416
|
/* @__PURE__ */ jsx19(
|
|
3371
3417
|
WidgetAvatarStack,
|
|
3372
3418
|
{
|
|
@@ -3374,7 +3420,7 @@ function WidgetHeader({
|
|
|
3374
3420
|
avatarClassName: compact ? "size-8" : void 0
|
|
3375
3421
|
}
|
|
3376
3422
|
),
|
|
3377
|
-
/* @__PURE__ */
|
|
3423
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-0.5", children: [
|
|
3378
3424
|
onToggleExpanded && /* @__PURE__ */ jsx19(
|
|
3379
3425
|
WidgetButton,
|
|
3380
3426
|
{
|
|
@@ -3412,16 +3458,16 @@ function WidgetLoading() {
|
|
|
3412
3458
|
}
|
|
3413
3459
|
|
|
3414
3460
|
// ../../apps/web/src/components/support-widget/widget-locked.tsx
|
|
3415
|
-
import { jsx as jsx21, jsxs as
|
|
3461
|
+
import { jsx as jsx21, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3416
3462
|
function WidgetLocked({
|
|
3417
3463
|
orgName,
|
|
3418
3464
|
onSignIn,
|
|
3419
3465
|
showBadge = true
|
|
3420
3466
|
}) {
|
|
3421
|
-
return /* @__PURE__ */
|
|
3422
|
-
/* @__PURE__ */
|
|
3467
|
+
return /* @__PURE__ */ jsxs10("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
3468
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex min-h-0 flex-1 flex-col items-center justify-center gap-5 px-8 text-center", children: [
|
|
3423
3469
|
/* @__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__ */
|
|
3470
|
+
/* @__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
3471
|
/* @__PURE__ */ jsx21("p", { className: "text-xl font-semibold tracking-tight", children: "Sign in to chat" }),
|
|
3426
3472
|
/* @__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
3473
|
] }),
|
|
@@ -3440,7 +3486,7 @@ function WidgetLocked({
|
|
|
3440
3486
|
}
|
|
3441
3487
|
|
|
3442
3488
|
// ../../apps/web/src/components/support-widget/widget-message.tsx
|
|
3443
|
-
import { useState as
|
|
3489
|
+
import { useState as useState8 } from "react";
|
|
3444
3490
|
|
|
3445
3491
|
// ../../apps/web/src/components/ui/badge.tsx
|
|
3446
3492
|
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
@@ -3449,10 +3495,10 @@ var badgeVariants = cva(
|
|
|
3449
3495
|
{
|
|
3450
3496
|
variants: {
|
|
3451
3497
|
variant: {
|
|
3452
|
-
default: "bg-secondary text-secondary-foreground",
|
|
3453
|
-
muted: "bg-muted text-muted-foreground",
|
|
3498
|
+
default: "bg-secondary text-secondary-foreground inset-ring-1 inset-ring-foreground/5",
|
|
3499
|
+
muted: "bg-muted/70 text-muted-foreground inset-ring-1 inset-ring-foreground/5",
|
|
3454
3500
|
outline: "border border-border text-muted-foreground",
|
|
3455
|
-
solid: "bg-primary text-primary-foreground"
|
|
3501
|
+
solid: "surface-primary bg-primary text-primary-foreground"
|
|
3456
3502
|
}
|
|
3457
3503
|
},
|
|
3458
3504
|
defaultVariants: {
|
|
@@ -3479,7 +3525,7 @@ function Badge({
|
|
|
3479
3525
|
}
|
|
3480
3526
|
|
|
3481
3527
|
// ../../apps/web/src/components/ui/morph-bubble.tsx
|
|
3482
|
-
import { useLayoutEffect as
|
|
3528
|
+
import { useLayoutEffect as useLayoutEffect5, useRef as useRef9 } from "react";
|
|
3483
3529
|
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
3484
3530
|
var MORPH_MS = 350;
|
|
3485
3531
|
var MORPH_EASING = "ease-in-out";
|
|
@@ -3507,11 +3553,11 @@ function MorphBubble({
|
|
|
3507
3553
|
contentClassName,
|
|
3508
3554
|
children
|
|
3509
3555
|
}) {
|
|
3510
|
-
const box =
|
|
3511
|
-
const content =
|
|
3512
|
-
const previous =
|
|
3513
|
-
const running =
|
|
3514
|
-
|
|
3556
|
+
const box = useRef9(null);
|
|
3557
|
+
const content = useRef9(null);
|
|
3558
|
+
const previous = useRef9(null);
|
|
3559
|
+
const running = useRef9([]);
|
|
3560
|
+
useLayoutEffect5(() => {
|
|
3515
3561
|
const outer = box.current;
|
|
3516
3562
|
const inner = content.current;
|
|
3517
3563
|
if (!outer || !inner) return;
|
|
@@ -3564,8 +3610,8 @@ function MorphBubble({
|
|
|
3564
3610
|
}
|
|
3565
3611
|
|
|
3566
3612
|
// ../../apps/web/src/components/support-widget/widget-attachments.tsx
|
|
3567
|
-
import { useState as
|
|
3568
|
-
import { Fragment as Fragment27, jsx as jsx24, jsxs as
|
|
3613
|
+
import { useState as useState6 } from "react";
|
|
3614
|
+
import { Fragment as Fragment27, jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3569
3615
|
var SURFACE = "rounded-xl border border-foreground/10 bg-card/70";
|
|
3570
3616
|
function OpenAttachment({
|
|
3571
3617
|
attachment,
|
|
@@ -3593,9 +3639,9 @@ function MediaTile({
|
|
|
3593
3639
|
attachment,
|
|
3594
3640
|
className
|
|
3595
3641
|
}) {
|
|
3596
|
-
const [hasFailed, setHasFailed] =
|
|
3642
|
+
const [hasFailed, setHasFailed] = useState6(false);
|
|
3597
3643
|
if (!attachment.previewUrl || hasFailed) {
|
|
3598
|
-
return /* @__PURE__ */
|
|
3644
|
+
return /* @__PURE__ */ jsxs11(
|
|
3599
3645
|
"div",
|
|
3600
3646
|
{
|
|
3601
3647
|
className: cn(
|
|
@@ -3610,7 +3656,7 @@ function MediaTile({
|
|
|
3610
3656
|
}
|
|
3611
3657
|
);
|
|
3612
3658
|
}
|
|
3613
|
-
return /* @__PURE__ */
|
|
3659
|
+
return /* @__PURE__ */ jsxs11("figure", { className: cn(SURFACE, "relative overflow-hidden", className), children: [
|
|
3614
3660
|
/* @__PURE__ */ jsx24(
|
|
3615
3661
|
"img",
|
|
3616
3662
|
{
|
|
@@ -3634,9 +3680,9 @@ function MediaTile({
|
|
|
3634
3680
|
] });
|
|
3635
3681
|
}
|
|
3636
3682
|
function FileRow({ attachment }) {
|
|
3637
|
-
return /* @__PURE__ */ jsx24(OpenAttachment, { attachment, children: /* @__PURE__ */
|
|
3638
|
-
/* @__PURE__ */ jsx24(
|
|
3639
|
-
/* @__PURE__ */
|
|
3683
|
+
return /* @__PURE__ */ jsx24(OpenAttachment, { attachment, children: /* @__PURE__ */ jsxs11("div", { className: cn(SURFACE, "flex items-center gap-2.5 px-2.5 py-2"), children: [
|
|
3684
|
+
/* @__PURE__ */ jsx24(File2, { className: "size-5 shrink-0 text-muted-foreground" }),
|
|
3685
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 flex-1 flex-col text-left", children: [
|
|
3640
3686
|
/* @__PURE__ */ jsx24("p", { className: "truncate text-sm font-medium", children: attachment.name }),
|
|
3641
3687
|
/* @__PURE__ */ jsx24("p", { className: "truncate text-sm text-muted-foreground", children: attachment.size })
|
|
3642
3688
|
] })
|
|
@@ -3647,7 +3693,7 @@ function WidgetAttachments({
|
|
|
3647
3693
|
}) {
|
|
3648
3694
|
const media = attachments.filter((one) => one.kind !== "file");
|
|
3649
3695
|
const files = attachments.filter((one) => one.kind === "file");
|
|
3650
|
-
return /* @__PURE__ */
|
|
3696
|
+
return /* @__PURE__ */ jsxs11("div", { className: "flex w-64 max-w-full flex-col gap-2", children: [
|
|
3651
3697
|
media.length > 0 && /* @__PURE__ */ jsx24("div", { className: cn("grid gap-2", media.length > 1 && "grid-cols-2"), children: media.map((attachment) => /* @__PURE__ */ jsx24(
|
|
3652
3698
|
OpenAttachment,
|
|
3653
3699
|
{
|
|
@@ -3685,7 +3731,7 @@ function WidgetBubble({
|
|
|
3685
3731
|
import { Suspense } from "react";
|
|
3686
3732
|
|
|
3687
3733
|
// ../../apps/web/src/components/ui/line-reveal.tsx
|
|
3688
|
-
import { useLayoutEffect as
|
|
3734
|
+
import { useLayoutEffect as useLayoutEffect6, useRef as useRef10, useState as useState7 } from "react";
|
|
3689
3735
|
|
|
3690
3736
|
// ../../apps/web/src/hooks/use-media-query.ts
|
|
3691
3737
|
import { useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
@@ -3712,7 +3758,7 @@ function durationMs(token, fallback, from = document.documentElement) {
|
|
|
3712
3758
|
}
|
|
3713
3759
|
|
|
3714
3760
|
// ../../apps/web/src/components/ui/line-reveal.tsx
|
|
3715
|
-
import { jsx as jsx26, jsxs as
|
|
3761
|
+
import { jsx as jsx26, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3716
3762
|
var LAST_BEAT = 11;
|
|
3717
3763
|
function lineSlices(root) {
|
|
3718
3764
|
const host = root.getBoundingClientRect();
|
|
@@ -3748,7 +3794,7 @@ function lineSlices(root) {
|
|
|
3748
3794
|
return [{ top: 0, height: host.height }];
|
|
3749
3795
|
}
|
|
3750
3796
|
const unique = [...new Set(tops.map((top) => Math.round(top)))].sort(
|
|
3751
|
-
(
|
|
3797
|
+
(a29, b2) => a29 - b2
|
|
3752
3798
|
);
|
|
3753
3799
|
return unique.map((top, index) => {
|
|
3754
3800
|
const next = unique[index + 1] ?? Math.ceil(host.height);
|
|
@@ -3798,10 +3844,10 @@ function LineReveal({
|
|
|
3798
3844
|
children,
|
|
3799
3845
|
className
|
|
3800
3846
|
}) {
|
|
3801
|
-
const sourceRef =
|
|
3802
|
-
const stageRef =
|
|
3847
|
+
const sourceRef = useRef10(null);
|
|
3848
|
+
const stageRef = useRef10(null);
|
|
3803
3849
|
const reduce = useMediaQuery("(prefers-reduced-motion: reduce)");
|
|
3804
|
-
const [play2, setPlay] =
|
|
3850
|
+
const [play2, setPlay] = useState7({
|
|
3805
3851
|
key: contentKey,
|
|
3806
3852
|
delay,
|
|
3807
3853
|
isPlaying: !reduce
|
|
@@ -3810,19 +3856,20 @@ function LineReveal({
|
|
|
3810
3856
|
setPlay({ key: contentKey, delay, isPlaying: !reduce });
|
|
3811
3857
|
}
|
|
3812
3858
|
const { key: playKey, delay: hold, isPlaying } = play2;
|
|
3813
|
-
|
|
3859
|
+
useLayoutEffect6(() => {
|
|
3814
3860
|
if (reduce || !isPlaying) return;
|
|
3815
3861
|
const source = sourceRef.current;
|
|
3816
3862
|
const stage = stageRef.current;
|
|
3817
3863
|
if (source === null || stage === null) return;
|
|
3864
|
+
const wait = typeof hold === "number" ? hold : durationMs(hold, 0, stage);
|
|
3818
3865
|
let painted = false;
|
|
3819
3866
|
let timer = 0;
|
|
3820
3867
|
const end = () => setPlay((now) => ({ ...now, isPlaying: false }));
|
|
3821
3868
|
const paint = () => {
|
|
3822
3869
|
if (painted) return;
|
|
3823
|
-
if (!paintSlices(source, stage,
|
|
3870
|
+
if (!paintSlices(source, stage, wait)) return;
|
|
3824
3871
|
painted = true;
|
|
3825
|
-
timer = window.setTimeout(end, playMs(stage,
|
|
3872
|
+
timer = window.setTimeout(end, playMs(stage, wait));
|
|
3826
3873
|
observer.disconnect();
|
|
3827
3874
|
};
|
|
3828
3875
|
const observer = new ResizeObserver(paint);
|
|
@@ -3839,7 +3886,7 @@ function LineReveal({
|
|
|
3839
3886
|
};
|
|
3840
3887
|
}, [playKey, hold, isPlaying, reduce]);
|
|
3841
3888
|
const showSlices = isPlaying && !reduce;
|
|
3842
|
-
return /* @__PURE__ */
|
|
3889
|
+
return /* @__PURE__ */ jsxs12("div", { className: cn("relative", className), children: [
|
|
3843
3890
|
/* @__PURE__ */ jsx26("div", { className: showSlices ? "pointer-events-none opacity-0" : void 0, children: /* @__PURE__ */ jsx26("div", { ref: sourceRef, children }) }),
|
|
3844
3891
|
showSlices && /* @__PURE__ */ jsx26(
|
|
3845
3892
|
"div",
|
|
@@ -3868,10 +3915,10 @@ function WidgetMessageBody({
|
|
|
3868
3915
|
}
|
|
3869
3916
|
|
|
3870
3917
|
// ../../apps/web/src/components/support-widget/widget-typing.tsx
|
|
3871
|
-
import { jsx as jsx28, jsxs as
|
|
3918
|
+
import { jsx as jsx28, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3872
3919
|
var DOTS = [0, 160, 320];
|
|
3873
3920
|
function WidgetTyping({ label }) {
|
|
3874
|
-
return /* @__PURE__ */
|
|
3921
|
+
return /* @__PURE__ */ jsxs13("span", { className: "flex items-center gap-1.5 py-2", children: [
|
|
3875
3922
|
/* @__PURE__ */ jsx28("span", { className: "sr-only", children: label }),
|
|
3876
3923
|
DOTS.map((delay) => /* @__PURE__ */ jsx28(
|
|
3877
3924
|
"span",
|
|
@@ -3886,16 +3933,17 @@ function WidgetTyping({ label }) {
|
|
|
3886
3933
|
}
|
|
3887
3934
|
|
|
3888
3935
|
// ../../apps/web/src/components/support-widget/widget-message.tsx
|
|
3889
|
-
import { Fragment as Fragment28, jsx as jsx29, jsxs as
|
|
3936
|
+
import { Fragment as Fragment28, jsx as jsx29, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3890
3937
|
var BUBBLE = "max-w-[min(80%,36rem)] rounded-2xl px-4 py-2.5 text-base";
|
|
3891
3938
|
var COMPACT_BUBBLE = "max-w-[min(80%,36rem)] rounded-2xl px-3.5 py-2 text-sm";
|
|
3892
3939
|
var VISITOR_BUBBLE = "bg-[color-mix(in_oklch,var(--muted),var(--foreground)_12%)]";
|
|
3893
3940
|
var ARRIVES = "animate-in fade-in-0 slide-in-from-bottom-1 duration-300 ease-out-quint motion-reduce:animate-none";
|
|
3941
|
+
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
3942
|
var LADDER_DELAY_MS = Math.round(MORPH_MS * 0.7);
|
|
3895
3943
|
function WidgetDivider({ message }) {
|
|
3896
3944
|
const label = message.startsConversation ? "New conversation" : message.dayLabel;
|
|
3897
3945
|
if (!label) return null;
|
|
3898
|
-
return /* @__PURE__ */
|
|
3946
|
+
return /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-3 py-1", children: [
|
|
3899
3947
|
/* @__PURE__ */ jsx29("span", { className: "h-px flex-1 bg-border" }),
|
|
3900
3948
|
/* @__PURE__ */ jsx29("span", { className: "text-sm text-muted-foreground", children: label }),
|
|
3901
3949
|
/* @__PURE__ */ jsx29("span", { className: "h-px flex-1 bg-border" })
|
|
@@ -3908,7 +3956,7 @@ function WidgetMessage({
|
|
|
3908
3956
|
compact = false,
|
|
3909
3957
|
isLive = false
|
|
3910
3958
|
}) {
|
|
3911
|
-
return message.sender === "visitor" ? /* @__PURE__ */ jsx29(VisitorMessage, { message, compact }) : /* @__PURE__ */ jsx29(
|
|
3959
|
+
return message.sender === "visitor" ? /* @__PURE__ */ jsx29(VisitorMessage, { message, compact, isLive }) : /* @__PURE__ */ jsx29(
|
|
3912
3960
|
AgentMessage,
|
|
3913
3961
|
{
|
|
3914
3962
|
message,
|
|
@@ -3932,7 +3980,7 @@ function BubbleContent({
|
|
|
3932
3980
|
}
|
|
3933
3981
|
);
|
|
3934
3982
|
}
|
|
3935
|
-
return /* @__PURE__ */
|
|
3983
|
+
return /* @__PURE__ */ jsxs14(Fragment28, { children: [
|
|
3936
3984
|
hasAttachments && /* @__PURE__ */ jsx29(WidgetAttachments, { attachments: message.attachments ?? [] }),
|
|
3937
3985
|
message.body && /* @__PURE__ */ jsx29(
|
|
3938
3986
|
WidgetMessageBody,
|
|
@@ -3946,9 +3994,10 @@ function BubbleContent({
|
|
|
3946
3994
|
}
|
|
3947
3995
|
function VisitorMessage({
|
|
3948
3996
|
message,
|
|
3949
|
-
compact
|
|
3997
|
+
compact,
|
|
3998
|
+
isLive
|
|
3950
3999
|
}) {
|
|
3951
|
-
return /* @__PURE__ */ jsx29("div", { className: cn("flex justify-end", ARRIVES), children: /* @__PURE__ */ jsx29(
|
|
4000
|
+
return /* @__PURE__ */ jsx29("div", { className: cn("flex justify-end", isLive ? SENT : ARRIVES), children: /* @__PURE__ */ jsx29(
|
|
3952
4001
|
WidgetBubble,
|
|
3953
4002
|
{
|
|
3954
4003
|
morphKey: "settled",
|
|
@@ -3965,7 +4014,7 @@ function AgentMessage({
|
|
|
3965
4014
|
isLive
|
|
3966
4015
|
}) {
|
|
3967
4016
|
const { agent } = message;
|
|
3968
|
-
const [sawDots, setSawDots] =
|
|
4017
|
+
const [sawDots, setSawDots] = useState8(message.pending === true);
|
|
3969
4018
|
if (message.pending && !sawDots) setSawDots(true);
|
|
3970
4019
|
const arrival = isLive && !message.pending && message.body.length > 0 ? { key: message.id, delay: sawDots ? LADDER_DELAY_MS : 0 } : null;
|
|
3971
4020
|
const destination = message.navigateTo === void 0 ? null : {
|
|
@@ -3979,8 +4028,8 @@ function AgentMessage({
|
|
|
3979
4028
|
// below, which spread four small things across three rows and pushed every
|
|
3980
4029
|
// bubble in off the edge. All of it is one line now, and the bubble gets
|
|
3981
4030
|
// the full width back.
|
|
3982
|
-
/* @__PURE__ */
|
|
3983
|
-
group.isFirst && /* @__PURE__ */
|
|
4031
|
+
/* @__PURE__ */ jsxs14("div", { className: cn("flex flex-col items-start gap-1", ARRIVES), children: [
|
|
4032
|
+
group.isFirst && /* @__PURE__ */ jsxs14(
|
|
3984
4033
|
"div",
|
|
3985
4034
|
{
|
|
3986
4035
|
className: cn(
|
|
@@ -3988,7 +4037,7 @@ function AgentMessage({
|
|
|
3988
4037
|
compact ? "text-xs" : "text-sm"
|
|
3989
4038
|
),
|
|
3990
4039
|
children: [
|
|
3991
|
-
agent && /* @__PURE__ */
|
|
4040
|
+
agent && /* @__PURE__ */ jsxs14(Fragment28, { children: [
|
|
3992
4041
|
/* @__PURE__ */ jsx29(
|
|
3993
4042
|
WidgetAvatar,
|
|
3994
4043
|
{
|
|
@@ -3997,7 +4046,7 @@ function AgentMessage({
|
|
|
3997
4046
|
}
|
|
3998
4047
|
),
|
|
3999
4048
|
/* @__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" })
|
|
4049
|
+
agent.kind === "ai" && /* @__PURE__ */ jsx29(Badge, { variant: "muted", className: "shrink-0 rounded-md bg-muted px-1 inset-ring-0", children: "AI" })
|
|
4001
4050
|
] }),
|
|
4002
4051
|
!message.pending && /* @__PURE__ */ jsx29("span", { className: "shrink-0 text-muted-foreground tabular-nums", children: message.time })
|
|
4003
4052
|
]
|
|
@@ -4035,21 +4084,21 @@ var TYPING_TTL_MS = 12e3;
|
|
|
4035
4084
|
var SNOOZE_MAX_MS = 365 * 24 * 60 * 6e4;
|
|
4036
4085
|
|
|
4037
4086
|
// ../../apps/web/src/components/support-widget/widget-rating.tsx
|
|
4038
|
-
import { useEffect as
|
|
4039
|
-
import { jsx as jsx30, jsxs as
|
|
4087
|
+
import { useEffect as useEffect6, useRef as useRef11, useState as useState9 } from "react";
|
|
4088
|
+
import { jsx as jsx30, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4040
4089
|
var STARS = Array.from({ length: RATING_MAX_STARS }, (_, index) => index + 1);
|
|
4041
4090
|
var THANKS_MS = 1400;
|
|
4042
4091
|
var STAR_STAGGER_MS = 40;
|
|
4043
4092
|
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
|
-
|
|
4093
|
+
const [isOpen, setIsOpen] = useState9(false);
|
|
4094
|
+
const [picked, setPicked] = useState9(rating.stars);
|
|
4095
|
+
const [hovered, setHovered] = useState9(null);
|
|
4096
|
+
const [feedback, setFeedback] = useState9("");
|
|
4097
|
+
const [isSending, setIsSending] = useState9(false);
|
|
4098
|
+
const [error, setError] = useState9(null);
|
|
4099
|
+
const [isDone, setIsDone] = useState9(false);
|
|
4100
|
+
const timers = useRef11([]);
|
|
4101
|
+
useEffect6(() => {
|
|
4053
4102
|
const frame = requestAnimationFrame(() => setIsOpen(true));
|
|
4054
4103
|
const pending = timers.current;
|
|
4055
4104
|
return () => {
|
|
@@ -4090,9 +4139,9 @@ function WidgetRating({ rating }) {
|
|
|
4090
4139
|
setIsDone(true);
|
|
4091
4140
|
later(THANKS_MS, leave);
|
|
4092
4141
|
}
|
|
4093
|
-
return /* @__PURE__ */ jsx30(Collapse, { isOpen, className: "shrink-0", children: /* @__PURE__ */
|
|
4094
|
-
/* @__PURE__ */ jsx30(Collapse, { isOpen: !isDone, children: /* @__PURE__ */
|
|
4095
|
-
/* @__PURE__ */
|
|
4142
|
+
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: [
|
|
4143
|
+
/* @__PURE__ */ jsx30(Collapse, { isOpen: !isDone, children: /* @__PURE__ */ jsxs15("div", { className: "py-3", children: [
|
|
4144
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-start justify-between gap-2", children: [
|
|
4096
4145
|
/* @__PURE__ */ jsx30("p", { className: "text-base font-medium", children: picked === null ? "How did we do?" : "Anything we could improve?" }),
|
|
4097
4146
|
/* @__PURE__ */ jsx30(
|
|
4098
4147
|
WidgetButton,
|
|
@@ -4149,7 +4198,7 @@ function WidgetRating({ rating }) {
|
|
|
4149
4198
|
))
|
|
4150
4199
|
}
|
|
4151
4200
|
),
|
|
4152
|
-
/* @__PURE__ */ jsx30(Collapse, { isOpen: picked !== null, children: /* @__PURE__ */
|
|
4201
|
+
/* @__PURE__ */ jsx30(Collapse, { isOpen: picked !== null, children: /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-2 pt-2", children: [
|
|
4153
4202
|
/* @__PURE__ */ jsx30(
|
|
4154
4203
|
Textarea,
|
|
4155
4204
|
{
|
|
@@ -4161,7 +4210,7 @@ function WidgetRating({ rating }) {
|
|
|
4161
4210
|
maxLength: RATING_FEEDBACK_MAX_LENGTH,
|
|
4162
4211
|
disabled: isSending,
|
|
4163
4212
|
className: cn(
|
|
4164
|
-
|
|
4213
|
+
WIDGET_TEXT_FIELD_SHELL,
|
|
4165
4214
|
"max-h-28 min-h-20 bg-card px-3 py-2.5 text-base"
|
|
4166
4215
|
)
|
|
4167
4216
|
}
|
|
@@ -4184,16 +4233,16 @@ function WidgetRating({ rating }) {
|
|
|
4184
4233
|
}
|
|
4185
4234
|
|
|
4186
4235
|
// ../../apps/web/src/components/support-widget/widget-status.tsx
|
|
4187
|
-
import { jsx as jsx31, jsxs as
|
|
4236
|
+
import { jsx as jsx31, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4188
4237
|
function WidgetAwaitingHuman() {
|
|
4189
|
-
return /* @__PURE__ */
|
|
4238
|
+
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
4239
|
/* @__PURE__ */ jsx31(UserCircle, { "aria-hidden": true, className: "size-4" }),
|
|
4191
4240
|
"Waiting for the support team"
|
|
4192
4241
|
] });
|
|
4193
4242
|
}
|
|
4194
4243
|
|
|
4195
4244
|
// ../../apps/web/src/components/support-widget/support-widget.tsx
|
|
4196
|
-
import { jsx as jsx32, jsxs as
|
|
4245
|
+
import { jsx as jsx32, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
4197
4246
|
function joinsPreviousTurn(message, previous) {
|
|
4198
4247
|
return !message.dayLabel && !message.startsConversation && message.sender === previous.sender && message.agent?.id === previous.agent?.id && withinRun(previous.sentAt, message.sentAt);
|
|
4199
4248
|
}
|
|
@@ -4223,7 +4272,7 @@ function SupportWidget({
|
|
|
4223
4272
|
className
|
|
4224
4273
|
}) {
|
|
4225
4274
|
const stack = useStackShift(messages.length);
|
|
4226
|
-
return /* @__PURE__ */
|
|
4275
|
+
return /* @__PURE__ */ jsxs17(
|
|
4227
4276
|
"section",
|
|
4228
4277
|
{
|
|
4229
4278
|
"aria-label": `${presence.name} support`,
|
|
@@ -4231,7 +4280,7 @@ function SupportWidget({
|
|
|
4231
4280
|
// The widget keeps its own radius scale. The app's token can climb as
|
|
4232
4281
|
// the chrome gets rounder without the widget changing shape under the
|
|
4233
4282
|
// hosts embedding it.
|
|
4234
|
-
|
|
4283
|
+
`flex h-full w-full flex-col overflow-hidden ${WIDGET_CORNER} border bg-card text-card-foreground [--radius:0.625rem]`,
|
|
4235
4284
|
// And its own pace for a reply arriving a line at a time: a step
|
|
4236
4285
|
// quicker than the palette's ladder, since a support answer is a
|
|
4237
4286
|
// few short lines in a bubble rather than an essay in a column.
|
|
@@ -4305,14 +4354,14 @@ function Conversation({
|
|
|
4305
4354
|
stackRef
|
|
4306
4355
|
}) {
|
|
4307
4356
|
const groups = groupMessages(messages, joinsPreviousTurn);
|
|
4308
|
-
const [openedWith] =
|
|
4357
|
+
const [openedWith] = useState10(
|
|
4309
4358
|
() => new Set(messages.map((message) => message.id))
|
|
4310
4359
|
);
|
|
4311
|
-
const [heldOffer, setHeldOffer] =
|
|
4360
|
+
const [heldOffer, setHeldOffer] = useState10(offer);
|
|
4312
4361
|
if (offer !== null && offer.key !== heldOffer?.key) setHeldOffer(offer);
|
|
4313
|
-
const [heldNotice, setHeldNotice] =
|
|
4362
|
+
const [heldNotice, setHeldNotice] = useState10(notice ?? null);
|
|
4314
4363
|
if (notice && notice !== heldNotice) setHeldNotice(notice);
|
|
4315
|
-
return /* @__PURE__ */
|
|
4364
|
+
return /* @__PURE__ */ jsxs17(
|
|
4316
4365
|
"div",
|
|
4317
4366
|
{
|
|
4318
4367
|
className: cn(
|
|
@@ -4340,7 +4389,7 @@ function Conversation({
|
|
|
4340
4389
|
so a scroller left alone slides the newest message under the
|
|
4341
4390
|
composer and has to catch up afterwards. Following it is what the
|
|
4342
4391
|
scroller stops easing for, so this tracks frame by frame. */
|
|
4343
|
-
/* @__PURE__ */ jsx32(MessageScrollerProvider, { children: /* @__PURE__ */
|
|
4392
|
+
/* @__PURE__ */ jsx32(MessageScrollerProvider, { children: /* @__PURE__ */ jsxs17(MessageScroller, { className: "h-auto min-h-0 flex-1", children: [
|
|
4344
4393
|
/* @__PURE__ */ jsx32(
|
|
4345
4394
|
MessageScrollerViewport,
|
|
4346
4395
|
{
|
|
@@ -4354,7 +4403,7 @@ function Conversation({
|
|
|
4354
4403
|
{
|
|
4355
4404
|
ref: stackRef,
|
|
4356
4405
|
className: "justify-end gap-0",
|
|
4357
|
-
children: messages.map((message, index) => /* @__PURE__ */
|
|
4406
|
+
children: messages.map((message, index) => /* @__PURE__ */ jsxs17(
|
|
4358
4407
|
MessageScrollerItem,
|
|
4359
4408
|
{
|
|
4360
4409
|
messageId: message.id,
|
|
@@ -4417,10 +4466,10 @@ function Conversation({
|
|
|
4417
4466
|
// ../../apps/web/src/components/support-widget/use-launcher-drag.ts
|
|
4418
4467
|
import {
|
|
4419
4468
|
useCallback as useCallback6,
|
|
4420
|
-
useEffect as
|
|
4421
|
-
useLayoutEffect as
|
|
4422
|
-
useRef as
|
|
4423
|
-
useState as
|
|
4469
|
+
useEffect as useEffect7,
|
|
4470
|
+
useLayoutEffect as useLayoutEffect7,
|
|
4471
|
+
useRef as useRef12,
|
|
4472
|
+
useState as useState11,
|
|
4424
4473
|
useSyncExternalStore as useSyncExternalStore4
|
|
4425
4474
|
} from "react";
|
|
4426
4475
|
import { flushSync } from "react-dom";
|
|
@@ -4439,9 +4488,9 @@ function useLauncherDrag({
|
|
|
4439
4488
|
subject
|
|
4440
4489
|
}) {
|
|
4441
4490
|
const spot = useSyncExternalStore4(subscribeSpot, getSpot, getDefaultSpot);
|
|
4442
|
-
const [isMoving, setIsMoving] =
|
|
4443
|
-
const grip =
|
|
4444
|
-
const justDragged =
|
|
4491
|
+
const [isMoving, setIsMoving] = useState11(false);
|
|
4492
|
+
const grip = useRef12(null);
|
|
4493
|
+
const justDragged = useRef12(false);
|
|
4445
4494
|
const measure = useCallback6(() => {
|
|
4446
4495
|
const box = boxRef.current;
|
|
4447
4496
|
const button = buttonRef.current;
|
|
@@ -4492,12 +4541,12 @@ function useLauncherDrag({
|
|
|
4492
4541
|
box.style.top = `${metrics.boxTop - taken.bounds.top}px`;
|
|
4493
4542
|
box.style.setProperty(BUTTON_Y, `${metrics.buttonInBox}px`);
|
|
4494
4543
|
}, [boxRef, measure, spot]);
|
|
4495
|
-
|
|
4496
|
-
|
|
4544
|
+
useLayoutEffect7(place, [place]);
|
|
4545
|
+
useEffect7(() => {
|
|
4497
4546
|
window.addEventListener("resize", place);
|
|
4498
4547
|
return () => window.removeEventListener("resize", place);
|
|
4499
4548
|
}, [place]);
|
|
4500
|
-
|
|
4549
|
+
useEffect7(() => {
|
|
4501
4550
|
const box = boxRef.current;
|
|
4502
4551
|
if (!box || typeof ResizeObserver === "undefined") return;
|
|
4503
4552
|
const observer = new ResizeObserver(place);
|
|
@@ -4625,7 +4674,7 @@ function useLauncherDrag({
|
|
|
4625
4674
|
},
|
|
4626
4675
|
[finishDrag]
|
|
4627
4676
|
);
|
|
4628
|
-
|
|
4677
|
+
useEffect7(() => {
|
|
4629
4678
|
if (!isMoving) return;
|
|
4630
4679
|
const end = () => finishDrag();
|
|
4631
4680
|
window.addEventListener("pointerup", end);
|
|
@@ -4643,7 +4692,7 @@ function useLauncherDrag({
|
|
|
4643
4692
|
onPointerUp: handlePointerUp,
|
|
4644
4693
|
onPointerCancel: handlePointerUp
|
|
4645
4694
|
};
|
|
4646
|
-
|
|
4695
|
+
useEffect7(() => {
|
|
4647
4696
|
function abandon() {
|
|
4648
4697
|
if (grip.current === null) return;
|
|
4649
4698
|
grip.current = null;
|
|
@@ -4682,15 +4731,15 @@ function clamp2(value, low, high) {
|
|
|
4682
4731
|
}
|
|
4683
4732
|
|
|
4684
4733
|
// ../../apps/web/src/components/support-widget/use-teaser-placement.ts
|
|
4685
|
-
import { useLayoutEffect as
|
|
4734
|
+
import { useLayoutEffect as useLayoutEffect8, useState as useState12 } from "react";
|
|
4686
4735
|
var ROOM_ABOVE_PX = 128;
|
|
4687
4736
|
function useTeaserPlacement({
|
|
4688
4737
|
buttonRef,
|
|
4689
4738
|
enabled: enabled2,
|
|
4690
4739
|
isMoving
|
|
4691
4740
|
}) {
|
|
4692
|
-
const [placement, setPlacement] =
|
|
4693
|
-
|
|
4741
|
+
const [placement, setPlacement] = useState12("above");
|
|
4742
|
+
useLayoutEffect8(() => {
|
|
4694
4743
|
if (!enabled2 || isMoving) return;
|
|
4695
4744
|
const measure = () => {
|
|
4696
4745
|
const button = buttonRef.current;
|
|
@@ -4706,15 +4755,15 @@ function useTeaserPlacement({
|
|
|
4706
4755
|
|
|
4707
4756
|
// ../../apps/web/src/components/support-widget/use-widget-sheet.ts
|
|
4708
4757
|
import {
|
|
4709
|
-
useLayoutEffect as
|
|
4710
|
-
useState as
|
|
4758
|
+
useLayoutEffect as useLayoutEffect9,
|
|
4759
|
+
useState as useState13,
|
|
4711
4760
|
useSyncExternalStore as useSyncExternalStore5
|
|
4712
4761
|
} from "react";
|
|
4713
4762
|
|
|
4714
4763
|
// ../../apps/web/src/components/support-widget/use-page-lock.ts
|
|
4715
|
-
import { useEffect as
|
|
4764
|
+
import { useEffect as useEffect8 } from "react";
|
|
4716
4765
|
function usePageLock(isLocked) {
|
|
4717
|
-
|
|
4766
|
+
useEffect8(() => {
|
|
4718
4767
|
if (!isLocked) return;
|
|
4719
4768
|
const { style } = document.body;
|
|
4720
4769
|
const held = {
|
|
@@ -4743,7 +4792,7 @@ function usePageLock(isLocked) {
|
|
|
4743
4792
|
|
|
4744
4793
|
// ../../apps/web/src/components/support-widget/use-widget-sheet.ts
|
|
4745
4794
|
var PHONE = "(max-width: 40rem)";
|
|
4746
|
-
var
|
|
4795
|
+
var SETTLE_MS = 400;
|
|
4747
4796
|
var KEYBOARD_PX = 96;
|
|
4748
4797
|
function subscribePhone(onChange) {
|
|
4749
4798
|
const media = window.matchMedia(PHONE);
|
|
@@ -4762,13 +4811,13 @@ function useWidgetSheet({
|
|
|
4762
4811
|
isPhoneNow,
|
|
4763
4812
|
isPhoneOnServer
|
|
4764
4813
|
);
|
|
4765
|
-
const [isFramed, setIsFramed] =
|
|
4766
|
-
|
|
4814
|
+
const [isFramed, setIsFramed] = useState13(false);
|
|
4815
|
+
useLayoutEffect9(() => {
|
|
4767
4816
|
setIsFramed(boxRef.current?.offsetParent != null);
|
|
4768
4817
|
}, [boxRef, isPhone]);
|
|
4769
4818
|
const isSheet = isPhone && !isFramed;
|
|
4770
4819
|
const isUp = isSheet && isOpen;
|
|
4771
|
-
|
|
4820
|
+
useLayoutEffect9(() => {
|
|
4772
4821
|
if (!isUp) return;
|
|
4773
4822
|
const panel = panelRef.current;
|
|
4774
4823
|
const viewport = window.visualViewport;
|
|
@@ -4797,7 +4846,7 @@ function useWidgetSheet({
|
|
|
4797
4846
|
frame = performance.now() < until ? requestAnimationFrame(follow) : 0;
|
|
4798
4847
|
};
|
|
4799
4848
|
const track = () => {
|
|
4800
|
-
until = performance.now() +
|
|
4849
|
+
until = performance.now() + SETTLE_MS;
|
|
4801
4850
|
if (frame === 0) frame = requestAnimationFrame(follow);
|
|
4802
4851
|
};
|
|
4803
4852
|
fit();
|
|
@@ -4820,7 +4869,7 @@ function useWidgetSheet({
|
|
|
4820
4869
|
}
|
|
4821
4870
|
|
|
4822
4871
|
// ../../apps/web/src/components/support-widget/widget-modal.tsx
|
|
4823
|
-
import { useRef as
|
|
4872
|
+
import { useRef as useRef13 } from "react";
|
|
4824
4873
|
import { createPortal } from "react-dom";
|
|
4825
4874
|
|
|
4826
4875
|
// ../../apps/web/src/components/support-widget/use-hydrated.ts
|
|
@@ -4834,9 +4883,9 @@ function useHydrated() {
|
|
|
4834
4883
|
}
|
|
4835
4884
|
|
|
4836
4885
|
// ../../apps/web/src/components/support-widget/use-scroll-lock.ts
|
|
4837
|
-
import { useEffect as
|
|
4886
|
+
import { useEffect as useEffect9 } from "react";
|
|
4838
4887
|
function useScrollLock(isLocked) {
|
|
4839
|
-
|
|
4888
|
+
useEffect9(() => {
|
|
4840
4889
|
if (!isLocked) return;
|
|
4841
4890
|
const { body } = document;
|
|
4842
4891
|
const held = {
|
|
@@ -4857,7 +4906,7 @@ function useScrollLock(isLocked) {
|
|
|
4857
4906
|
}
|
|
4858
4907
|
|
|
4859
4908
|
// ../../apps/web/src/components/support-widget/widget-modal.tsx
|
|
4860
|
-
import { jsx as jsx33, jsxs as
|
|
4909
|
+
import { jsx as jsx33, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
4861
4910
|
var LAYER = 2147483e3;
|
|
4862
4911
|
var WIDTH = "50rem";
|
|
4863
4912
|
var HEIGHT = "40rem";
|
|
@@ -4873,13 +4922,13 @@ function SupportModal({
|
|
|
4873
4922
|
label,
|
|
4874
4923
|
children
|
|
4875
4924
|
}) {
|
|
4876
|
-
const layerRef =
|
|
4925
|
+
const layerRef = useRef13(null);
|
|
4877
4926
|
const isHydrated = useHydrated();
|
|
4878
4927
|
const isSheet = useWidgetSheet({ boxRef: layerRef, panelRef, isOpen });
|
|
4879
4928
|
useScrollLock(isOpen && !isSheet);
|
|
4880
4929
|
if (!isHydrated) return null;
|
|
4881
4930
|
return createPortal(
|
|
4882
|
-
/* @__PURE__ */
|
|
4931
|
+
/* @__PURE__ */ jsxs18(
|
|
4883
4932
|
"div",
|
|
4884
4933
|
{
|
|
4885
4934
|
ref: layerRef,
|
|
@@ -4924,7 +4973,7 @@ function SupportModal({
|
|
|
4924
4973
|
isOpen ? "translate-y-0 opacity-100" : "translate-y-8 opacity-0"
|
|
4925
4974
|
] : [
|
|
4926
4975
|
// Never past the layer's padding, whatever the size says.
|
|
4927
|
-
|
|
4976
|
+
`relative max-h-full max-w-full ${WIDGET_CORNER} shadow-2xl`,
|
|
4928
4977
|
MOTION,
|
|
4929
4978
|
isOpen ? [OPEN, "scale-100 opacity-100 translate-y-0"] : [SHUT, "scale-[0.96] opacity-0 translate-y-2"]
|
|
4930
4979
|
]
|
|
@@ -4947,7 +4996,7 @@ var SHEET_PANEL = cn(
|
|
|
4947
4996
|
);
|
|
4948
4997
|
|
|
4949
4998
|
// ../../apps/web/src/components/support-widget/widget-teaser.tsx
|
|
4950
|
-
import { useState as
|
|
4999
|
+
import { useState as useState14 } from "react";
|
|
4951
5000
|
|
|
4952
5001
|
// ../../apps/web/src/components/support-widget/plain-text.ts
|
|
4953
5002
|
function plainTextOf(markdown) {
|
|
@@ -4955,7 +5004,7 @@ function plainTextOf(markdown) {
|
|
|
4955
5004
|
}
|
|
4956
5005
|
|
|
4957
5006
|
// ../../apps/web/src/components/support-widget/widget-teaser.tsx
|
|
4958
|
-
import { Fragment as Fragment29, jsx as jsx34, jsxs as
|
|
5007
|
+
import { Fragment as Fragment29, jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
4959
5008
|
var WIDTH2 = "min(20rem, 100%)";
|
|
4960
5009
|
var GAP = "0.5rem";
|
|
4961
5010
|
function WidgetTeaser({
|
|
@@ -4968,13 +5017,13 @@ function WidgetTeaser({
|
|
|
4968
5017
|
onOpen,
|
|
4969
5018
|
onDismiss
|
|
4970
5019
|
}) {
|
|
4971
|
-
const [held, setHeld] =
|
|
5020
|
+
const [held, setHeld] = useState14(message);
|
|
4972
5021
|
if (message !== null && message !== held) setHeld(message);
|
|
4973
5022
|
const shown = message ?? held;
|
|
4974
5023
|
if (shown === null) return null;
|
|
4975
5024
|
const agent = shown.agent;
|
|
4976
5025
|
const text = plainTextOf(shown.body);
|
|
4977
|
-
return /* @__PURE__ */
|
|
5026
|
+
return /* @__PURE__ */ jsxs19(
|
|
4978
5027
|
"div",
|
|
4979
5028
|
{
|
|
4980
5029
|
inert: !isShown,
|
|
@@ -4999,7 +5048,7 @@ function WidgetTeaser({
|
|
|
4999
5048
|
] : "pointer-events-none scale-95 opacity-0 duration-150 ease-out-quint"
|
|
5000
5049
|
),
|
|
5001
5050
|
children: [
|
|
5002
|
-
/* @__PURE__ */
|
|
5051
|
+
/* @__PURE__ */ jsxs19(
|
|
5003
5052
|
"button",
|
|
5004
5053
|
{
|
|
5005
5054
|
type: "button",
|
|
@@ -5008,17 +5057,17 @@ function WidgetTeaser({
|
|
|
5008
5057
|
className: cn(
|
|
5009
5058
|
// Its own radius scale, like the panel, so the app's token cannot
|
|
5010
5059
|
// reshape a card that sits on somebody else's site.
|
|
5011
|
-
|
|
5060
|
+
`block w-full ${WIDGET_CORNER} border bg-card p-3.5 pr-10 text-left text-card-foreground shadow-lg [--radius:0.625rem]`,
|
|
5012
5061
|
"transition-[background-color,box-shadow] outline-none",
|
|
5013
5062
|
"hover:bg-muted/50 focus-visible:ring-3 focus-visible:ring-ring/50",
|
|
5014
5063
|
"cursor-pointer select-none"
|
|
5015
5064
|
),
|
|
5016
5065
|
children: [
|
|
5017
|
-
/* @__PURE__ */
|
|
5018
|
-
agent && /* @__PURE__ */
|
|
5066
|
+
/* @__PURE__ */ jsxs19("span", { className: "flex items-center gap-2", children: [
|
|
5067
|
+
agent && /* @__PURE__ */ jsxs19(Fragment29, { children: [
|
|
5019
5068
|
/* @__PURE__ */ jsx34(WidgetAvatar, { agent, className: "size-6 rounded-md" }),
|
|
5020
5069
|
/* @__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" })
|
|
5070
|
+
agent.kind === "ai" && /* @__PURE__ */ jsx34(Badge, { variant: "muted", className: "shrink-0 rounded-md bg-muted px-1 inset-ring-0", children: "AI" })
|
|
5022
5071
|
] }),
|
|
5023
5072
|
/* @__PURE__ */ jsx34("span", { className: "ml-auto shrink-0 text-sm text-muted-foreground tabular-nums", children: shown.time })
|
|
5024
5073
|
] }),
|
|
@@ -5048,14 +5097,13 @@ function WidgetTeaser({
|
|
|
5048
5097
|
}
|
|
5049
5098
|
|
|
5050
5099
|
// ../../apps/web/src/components/support-widget/widget-launcher.tsx
|
|
5051
|
-
import { Fragment as Fragment30, jsx as jsx35, jsxs as
|
|
5100
|
+
import { Fragment as Fragment30, jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
5052
5101
|
var DEFAULT_WIDTH = "28rem";
|
|
5053
5102
|
var DEFAULT_HEIGHT = "40rem";
|
|
5054
5103
|
var DEFAULT_BUTTON_SIZE = "3rem";
|
|
5055
5104
|
var EXPANDED_WIDTH = "34rem";
|
|
5056
5105
|
var EXPANDED_HEIGHT = "52rem";
|
|
5057
|
-
var
|
|
5058
|
-
var OPEN_CLIP = `inset(0px 0px 0px 0px round ${PANEL_RADIUS})`;
|
|
5106
|
+
var OPEN_CLIP = `inset(0px 0px 0px 0px round ${WIDGET_RADIUS})`;
|
|
5059
5107
|
var buttonY = (buttonSize) => `var(${BUTTON_Y}, calc(100% - ${buttonSize}))`;
|
|
5060
5108
|
var MARGIN = "1rem";
|
|
5061
5109
|
var CLOSED_SCALE = "scale(0.94)";
|
|
@@ -5105,14 +5153,14 @@ function SupportLauncher({
|
|
|
5105
5153
|
onOpenChange,
|
|
5106
5154
|
className
|
|
5107
5155
|
}) {
|
|
5108
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
5156
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState15(defaultOpen);
|
|
5109
5157
|
const isOpen = open ?? uncontrolledOpen;
|
|
5110
5158
|
const hasBubble = launcher === "bubble";
|
|
5111
5159
|
const isModal = presentation === "modal";
|
|
5112
|
-
const [isExpanded, setExpanded] =
|
|
5113
|
-
const launcherRef =
|
|
5114
|
-
const panelRef =
|
|
5115
|
-
const boxRef =
|
|
5160
|
+
const [isExpanded, setExpanded] = useState15(false);
|
|
5161
|
+
const launcherRef = useRef14(null);
|
|
5162
|
+
const panelRef = useRef14(null);
|
|
5163
|
+
const boxRef = useRef14(null);
|
|
5116
5164
|
const drag = useLauncherDrag({
|
|
5117
5165
|
boxRef,
|
|
5118
5166
|
buttonRef: launcherRef,
|
|
@@ -5132,8 +5180,8 @@ function SupportLauncher({
|
|
|
5132
5180
|
enabled: hasTeaser,
|
|
5133
5181
|
isMoving: drag.isMoving
|
|
5134
5182
|
});
|
|
5135
|
-
const opener =
|
|
5136
|
-
const wasOpen =
|
|
5183
|
+
const opener = useRef14(null);
|
|
5184
|
+
const wasOpen = useRef14(isOpen);
|
|
5137
5185
|
const setOpen = useCallback7(
|
|
5138
5186
|
(next) => {
|
|
5139
5187
|
if (open === void 0) setUncontrolledOpen(next);
|
|
@@ -5149,10 +5197,10 @@ function SupportLauncher({
|
|
|
5149
5197
|
},
|
|
5150
5198
|
[onFollow, isSheet, isModal, close]
|
|
5151
5199
|
);
|
|
5152
|
-
|
|
5200
|
+
useEffect10(() => {
|
|
5153
5201
|
if (isOpen) warmMarkdown();
|
|
5154
5202
|
}, [isOpen]);
|
|
5155
|
-
|
|
5203
|
+
useEffect10(() => {
|
|
5156
5204
|
if (!isOpen) return;
|
|
5157
5205
|
function handleKeyDown(event) {
|
|
5158
5206
|
if (event.key === "Escape") close();
|
|
@@ -5160,7 +5208,7 @@ function SupportLauncher({
|
|
|
5160
5208
|
document.addEventListener("keydown", handleKeyDown);
|
|
5161
5209
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
5162
5210
|
}, [isOpen, close]);
|
|
5163
|
-
|
|
5211
|
+
useEffect10(() => {
|
|
5164
5212
|
if (wasOpen.current === isOpen) return;
|
|
5165
5213
|
wasOpen.current = isOpen;
|
|
5166
5214
|
if (isOpen) {
|
|
@@ -5201,8 +5249,8 @@ function SupportLauncher({
|
|
|
5201
5249
|
compact: isModal
|
|
5202
5250
|
}
|
|
5203
5251
|
);
|
|
5204
|
-
return /* @__PURE__ */
|
|
5205
|
-
/* @__PURE__ */
|
|
5252
|
+
return /* @__PURE__ */ jsxs20(Fragment30, { children: [
|
|
5253
|
+
/* @__PURE__ */ jsxs20(
|
|
5206
5254
|
"div",
|
|
5207
5255
|
{
|
|
5208
5256
|
ref: boxRef,
|
|
@@ -5271,7 +5319,7 @@ function SupportLauncher({
|
|
|
5271
5319
|
children: widget(isSheet)
|
|
5272
5320
|
}
|
|
5273
5321
|
),
|
|
5274
|
-
hasBubble && /* @__PURE__ */
|
|
5322
|
+
hasBubble && /* @__PURE__ */ jsxs20(
|
|
5275
5323
|
"button",
|
|
5276
5324
|
{
|
|
5277
5325
|
ref: launcherRef,
|
|
@@ -5386,9 +5434,9 @@ function SupportLauncher({
|
|
|
5386
5434
|
}
|
|
5387
5435
|
|
|
5388
5436
|
// ../../apps/web/src/components/support-widget/widget-spotlight.tsx
|
|
5389
|
-
import { useEffect as
|
|
5437
|
+
import { useEffect as useEffect11, useRef as useRef15, useState as useState16 } from "react";
|
|
5390
5438
|
import { createPortal as createPortal2 } from "react-dom";
|
|
5391
|
-
import { jsx as jsx36, jsxs as
|
|
5439
|
+
import { jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
5392
5440
|
var FIND_TIMEOUT_MS = 4e3;
|
|
5393
5441
|
var HOLD_MS = 2600;
|
|
5394
5442
|
var FADE_MS = 300;
|
|
@@ -5397,10 +5445,10 @@ function prefersReducedMotion4() {
|
|
|
5397
5445
|
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
5398
5446
|
}
|
|
5399
5447
|
function WidgetSpotlight({ selector }) {
|
|
5400
|
-
const [isShown, setIsShown] =
|
|
5401
|
-
const [isLeaving, setIsLeaving] =
|
|
5402
|
-
const ring =
|
|
5403
|
-
|
|
5448
|
+
const [isShown, setIsShown] = useState16(false);
|
|
5449
|
+
const [isLeaving, setIsLeaving] = useState16(false);
|
|
5450
|
+
const ring = useRef15(null);
|
|
5451
|
+
useEffect11(() => {
|
|
5404
5452
|
let target = null;
|
|
5405
5453
|
let frame = 0;
|
|
5406
5454
|
let startedAt = 0;
|
|
@@ -5459,7 +5507,7 @@ function WidgetSpotlight({ selector }) {
|
|
|
5459
5507
|
}, [selector]);
|
|
5460
5508
|
if (!isShown || typeof document === "undefined") return null;
|
|
5461
5509
|
return createPortal2(
|
|
5462
|
-
/* @__PURE__ */
|
|
5510
|
+
/* @__PURE__ */ jsxs21(
|
|
5463
5511
|
"div",
|
|
5464
5512
|
{
|
|
5465
5513
|
ref: ring,
|
|
@@ -5497,7 +5545,7 @@ function WidgetSpotlight({ selector }) {
|
|
|
5497
5545
|
}
|
|
5498
5546
|
|
|
5499
5547
|
// ../../apps/web/src/components/support-widget/sdk/control.ts
|
|
5500
|
-
import { useSyncExternalStore as
|
|
5548
|
+
import { useSyncExternalStore as useSyncExternalStore12 } from "react";
|
|
5501
5549
|
|
|
5502
5550
|
// ../backend/convex/shared/customData.ts
|
|
5503
5551
|
var MAX_CUSTOM_ENTRIES = 8;
|
|
@@ -5562,23 +5610,23 @@ function restoreCustomData(entries) {
|
|
|
5562
5610
|
}
|
|
5563
5611
|
|
|
5564
5612
|
// ../../apps/web/src/components/support-widget/sdk/open-store.ts
|
|
5565
|
-
import { useCallback as useCallback8, useEffect as
|
|
5613
|
+
import { useCallback as useCallback8, useEffect as useEffect12, useSyncExternalStore as useSyncExternalStore7 } from "react";
|
|
5566
5614
|
var isDevelopment = typeof process !== "undefined" && process.env.NODE_ENV === "development";
|
|
5567
5615
|
function createOpenStore(component) {
|
|
5568
5616
|
let requested = null;
|
|
5569
5617
|
let effective = false;
|
|
5570
5618
|
let mounted = 0;
|
|
5571
|
-
const
|
|
5619
|
+
const listeners7 = /* @__PURE__ */ new Set();
|
|
5572
5620
|
function emit() {
|
|
5573
|
-
for (const listener of
|
|
5621
|
+
for (const listener of listeners7) listener();
|
|
5574
5622
|
}
|
|
5575
5623
|
return {
|
|
5576
5624
|
/** The component a warning should name, so it reads like the host's code. */
|
|
5577
5625
|
component,
|
|
5578
5626
|
subscribe(listener) {
|
|
5579
|
-
|
|
5627
|
+
listeners7.add(listener);
|
|
5580
5628
|
return () => {
|
|
5581
|
-
|
|
5629
|
+
listeners7.delete(listener);
|
|
5582
5630
|
};
|
|
5583
5631
|
},
|
|
5584
5632
|
readRequested: () => requested,
|
|
@@ -5642,7 +5690,7 @@ function useOpenState(store3, {
|
|
|
5642
5690
|
store3.readServerRequested
|
|
5643
5691
|
);
|
|
5644
5692
|
const isOpen = open ?? asked ?? defaultOpen;
|
|
5645
|
-
|
|
5693
|
+
useEffect12(() => {
|
|
5646
5694
|
store3.settle(isOpen);
|
|
5647
5695
|
}, [store3, isOpen]);
|
|
5648
5696
|
const setOpen = useCallback8(
|
|
@@ -5655,7 +5703,7 @@ function useOpenState(store3, {
|
|
|
5655
5703
|
return [isOpen, setOpen];
|
|
5656
5704
|
}
|
|
5657
5705
|
function useRegister(store3) {
|
|
5658
|
-
|
|
5706
|
+
useEffect12(() => {
|
|
5659
5707
|
if (store3.countMounted() > 1 && isDevelopment) {
|
|
5660
5708
|
console.warn(
|
|
5661
5709
|
`Median: more than one <${store3.component}> is mounted. They share one open state and open together. Mount it once, near the root of your app.`
|
|
@@ -5665,6 +5713,30 @@ function useRegister(store3) {
|
|
|
5665
5713
|
}, [store3]);
|
|
5666
5714
|
}
|
|
5667
5715
|
|
|
5716
|
+
// ../backend/convex/shared/auditResult.ts
|
|
5717
|
+
import { ConvexError } from "convex/values";
|
|
5718
|
+
function unwrapAuditResult(result) {
|
|
5719
|
+
if (result.auditResult === "error") throw new ConvexError(result.data);
|
|
5720
|
+
return result.value;
|
|
5721
|
+
}
|
|
5722
|
+
|
|
5723
|
+
// ../backend/client/auditedMutation.ts
|
|
5724
|
+
function unwrapMutationResult(result) {
|
|
5725
|
+
if (result && typeof result === "object" && "auditResult" in result && (result.auditResult === "ok" && "value" in result || result.auditResult === "error" && "data" in result)) {
|
|
5726
|
+
return unwrapAuditResult(
|
|
5727
|
+
result
|
|
5728
|
+
);
|
|
5729
|
+
}
|
|
5730
|
+
return result;
|
|
5731
|
+
}
|
|
5732
|
+
function auditedClientMutation(mutation) {
|
|
5733
|
+
const invoke = async (...args) => {
|
|
5734
|
+
return unwrapMutationResult(await mutation(...args));
|
|
5735
|
+
};
|
|
5736
|
+
invoke.withOptimisticUpdate = (update) => auditedClientMutation(mutation.withOptimisticUpdate(update));
|
|
5737
|
+
return invoke;
|
|
5738
|
+
}
|
|
5739
|
+
|
|
5668
5740
|
// ../backend/convex/_generated/api.js
|
|
5669
5741
|
import { anyApi, componentsGeneric } from "convex/server";
|
|
5670
5742
|
var api = anyApi;
|
|
@@ -5702,6 +5774,33 @@ function cleanCrash(input) {
|
|
|
5702
5774
|
import { ConvexHttpClient } from "convex/browser";
|
|
5703
5775
|
import { useSyncExternalStore as useSyncExternalStore10 } from "react";
|
|
5704
5776
|
|
|
5777
|
+
// ../../apps/web/src/lib/upload.ts
|
|
5778
|
+
async function uploadFile(getUploadUrl, file) {
|
|
5779
|
+
const url = await getUploadUrl();
|
|
5780
|
+
const response = await fetch(url, {
|
|
5781
|
+
method: "POST",
|
|
5782
|
+
headers: { "Content-Type": file.type || "application/octet-stream" },
|
|
5783
|
+
body: file
|
|
5784
|
+
});
|
|
5785
|
+
if (!response.ok) {
|
|
5786
|
+
throw new Error(`Uploading ${file.name} failed with ${response.status}`);
|
|
5787
|
+
}
|
|
5788
|
+
const { storageId } = await response.json();
|
|
5789
|
+
return storageId;
|
|
5790
|
+
}
|
|
5791
|
+
async function uploadAttachments(getUploadUrl, files) {
|
|
5792
|
+
const attachments = [];
|
|
5793
|
+
for (const file of files) {
|
|
5794
|
+
attachments.push({
|
|
5795
|
+
storageId: await uploadFile(getUploadUrl, file),
|
|
5796
|
+
name: file.name,
|
|
5797
|
+
size: file.size,
|
|
5798
|
+
type: file.type || "application/octet-stream"
|
|
5799
|
+
});
|
|
5800
|
+
}
|
|
5801
|
+
return attachments;
|
|
5802
|
+
}
|
|
5803
|
+
|
|
5705
5804
|
// ../../apps/web/src/components/support-widget/sdk/context.ts
|
|
5706
5805
|
var BROWSERS = [
|
|
5707
5806
|
{ name: "Edge", token: /Edg(?:e|A|iOS)?\/(\d+)/ },
|
|
@@ -5867,7 +5966,7 @@ function cleanClientDiagnostics(input) {
|
|
|
5867
5966
|
}
|
|
5868
5967
|
|
|
5869
5968
|
// ../../apps/web/src/components/support-widget/sdk/diagnostics.ts
|
|
5870
|
-
import { useCallback as useCallback9, useEffect as
|
|
5969
|
+
import { useCallback as useCallback9, useEffect as useEffect13, useRef as useRef16 } from "react";
|
|
5871
5970
|
function settingsOf(option) {
|
|
5872
5971
|
if (option === void 0 || option === false) return null;
|
|
5873
5972
|
if (option === true) return { errors: true, network: false, console: false };
|
|
@@ -6003,13 +6102,13 @@ function snapshotNow(extraState) {
|
|
|
6003
6102
|
function useDiagnostics(option, appState) {
|
|
6004
6103
|
const settings = settingsOf(option);
|
|
6005
6104
|
const key = settings === null ? null : JSON.stringify(settings);
|
|
6006
|
-
const stateRef =
|
|
6007
|
-
|
|
6105
|
+
const stateRef = useRef16(appState);
|
|
6106
|
+
useEffect13(() => {
|
|
6008
6107
|
stateRef.current = appState;
|
|
6009
6108
|
latestState = appState;
|
|
6010
6109
|
});
|
|
6011
|
-
const sentAt =
|
|
6012
|
-
|
|
6110
|
+
const sentAt = useRef16(null);
|
|
6111
|
+
useEffect13(() => {
|
|
6013
6112
|
if (key === null) return;
|
|
6014
6113
|
return collect(JSON.parse(key));
|
|
6015
6114
|
}, [key]);
|
|
@@ -6023,7 +6122,7 @@ function useDiagnostics(option, appState) {
|
|
|
6023
6122
|
}
|
|
6024
6123
|
|
|
6025
6124
|
// ../../apps/web/src/components/support-widget/sdk/install.ts
|
|
6026
|
-
import { useEffect as
|
|
6125
|
+
import { useEffect as useEffect14 } from "react";
|
|
6027
6126
|
var install = null;
|
|
6028
6127
|
var listeners3 = /* @__PURE__ */ new Set();
|
|
6029
6128
|
function rememberInstall(next) {
|
|
@@ -6045,12 +6144,115 @@ function hasInstall() {
|
|
|
6045
6144
|
return install !== null;
|
|
6046
6145
|
}
|
|
6047
6146
|
function useRememberInstall(apiKey, user) {
|
|
6048
|
-
|
|
6147
|
+
useEffect14(() => {
|
|
6049
6148
|
if (apiKey === void 0) return;
|
|
6050
6149
|
rememberInstall({ apiKey, ...user ? { user } : {} });
|
|
6051
6150
|
});
|
|
6052
6151
|
}
|
|
6053
6152
|
|
|
6153
|
+
// ../../apps/web/src/components/support-widget/sdk/screenshot.ts
|
|
6154
|
+
var MAX_WIDTH = 1440;
|
|
6155
|
+
var TIMEOUT_MS = 6e3;
|
|
6156
|
+
var TYPE = "image/jpeg";
|
|
6157
|
+
var QUALITY = 0.85;
|
|
6158
|
+
var SCREENSHOT_NAME = "screenshot.jpg";
|
|
6159
|
+
var PIN_ATTRIBUTE = "data-median-pin";
|
|
6160
|
+
async function capturePage() {
|
|
6161
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
6162
|
+
return null;
|
|
6163
|
+
}
|
|
6164
|
+
const page = document.documentElement;
|
|
6165
|
+
if (page === null) return null;
|
|
6166
|
+
try {
|
|
6167
|
+
const blob = await Promise.race([
|
|
6168
|
+
draw(page),
|
|
6169
|
+
new Promise((resolve) => setTimeout(() => resolve(null), TIMEOUT_MS))
|
|
6170
|
+
]);
|
|
6171
|
+
if (blob === null) return null;
|
|
6172
|
+
return new File([blob], SCREENSHOT_NAME, { type: TYPE });
|
|
6173
|
+
} catch (caught) {
|
|
6174
|
+
console.warn("Median: taking a screenshot for this report failed", caught);
|
|
6175
|
+
return null;
|
|
6176
|
+
}
|
|
6177
|
+
}
|
|
6178
|
+
async function draw(page) {
|
|
6179
|
+
const { domToBlob } = await import("./dist-VC6ZVTA2.js");
|
|
6180
|
+
const width = page.clientWidth || window.innerWidth;
|
|
6181
|
+
const height = page.clientHeight || window.innerHeight;
|
|
6182
|
+
const unpin = pinFixed();
|
|
6183
|
+
try {
|
|
6184
|
+
return await domToBlob(page, {
|
|
6185
|
+
width,
|
|
6186
|
+
height,
|
|
6187
|
+
// Their view, not the whole document: the page is drawn in full and
|
|
6188
|
+
// the part they are looking at is what the frame is put around. A page
|
|
6189
|
+
// held still by `usePageLock` has already been scrolled to nothing,
|
|
6190
|
+
// and is shifted by nothing here.
|
|
6191
|
+
style: {
|
|
6192
|
+
transform: `translate(${-window.scrollX}px, ${-window.scrollY}px)`,
|
|
6193
|
+
transformOrigin: "top left"
|
|
6194
|
+
},
|
|
6195
|
+
scale: Math.min(1, MAX_WIDTH / Math.max(width, 1)),
|
|
6196
|
+
type: TYPE,
|
|
6197
|
+
quality: QUALITY,
|
|
6198
|
+
// JPEG has no transparency, so anything clear would come out black.
|
|
6199
|
+
backgroundColor: pageBackground(),
|
|
6200
|
+
filter: notOurs,
|
|
6201
|
+
onCloneNode: placePinned,
|
|
6202
|
+
timeout: TIMEOUT_MS,
|
|
6203
|
+
features: { copyScrollbar: false }
|
|
6204
|
+
});
|
|
6205
|
+
} finally {
|
|
6206
|
+
unpin();
|
|
6207
|
+
}
|
|
6208
|
+
}
|
|
6209
|
+
function pinFixed() {
|
|
6210
|
+
const pinned = [];
|
|
6211
|
+
for (const element of document.body.querySelectorAll("*")) {
|
|
6212
|
+
if (window.getComputedStyle(element).position !== "fixed") continue;
|
|
6213
|
+
const box = element.getBoundingClientRect();
|
|
6214
|
+
if (box.width === 0 || box.height === 0) continue;
|
|
6215
|
+
element.setAttribute(
|
|
6216
|
+
PIN_ATTRIBUTE,
|
|
6217
|
+
[box.left, box.top, box.width, box.height].join(",")
|
|
6218
|
+
);
|
|
6219
|
+
pinned.push(element);
|
|
6220
|
+
}
|
|
6221
|
+
return () => {
|
|
6222
|
+
for (const element of pinned) element.removeAttribute(PIN_ATTRIBUTE);
|
|
6223
|
+
};
|
|
6224
|
+
}
|
|
6225
|
+
function placePinned(clone) {
|
|
6226
|
+
if (!(clone instanceof Element)) return;
|
|
6227
|
+
for (const element of clone.querySelectorAll(`[${PIN_ATTRIBUTE}]`)) {
|
|
6228
|
+
const [left, top, width, height] = (element.getAttribute(PIN_ATTRIBUTE) ?? "").split(",").map(Number);
|
|
6229
|
+
element.removeAttribute(PIN_ATTRIBUTE);
|
|
6230
|
+
if (!(element instanceof HTMLElement) || Number.isNaN(top)) continue;
|
|
6231
|
+
element.style.setProperty("left", `${left + window.scrollX}px`, "important");
|
|
6232
|
+
element.style.setProperty("top", `${top + window.scrollY}px`, "important");
|
|
6233
|
+
element.style.setProperty("right", "auto", "important");
|
|
6234
|
+
element.style.setProperty("bottom", "auto", "important");
|
|
6235
|
+
element.style.setProperty("width", `${width}px`, "important");
|
|
6236
|
+
element.style.setProperty("height", `${height}px`, "important");
|
|
6237
|
+
element.style.setProperty("margin", "0", "important");
|
|
6238
|
+
}
|
|
6239
|
+
}
|
|
6240
|
+
function notOurs(node) {
|
|
6241
|
+
return !(node instanceof Element && node.hasAttribute("data-median-widget"));
|
|
6242
|
+
}
|
|
6243
|
+
function pageBackground() {
|
|
6244
|
+
for (const element of [document.body, document.documentElement]) {
|
|
6245
|
+
if (element === null) continue;
|
|
6246
|
+
const color = window.getComputedStyle(element).backgroundColor;
|
|
6247
|
+
if (color && !isClear(color)) return color;
|
|
6248
|
+
}
|
|
6249
|
+
return "#ffffff";
|
|
6250
|
+
}
|
|
6251
|
+
function isClear(color) {
|
|
6252
|
+
const clear = color.replace(/\s/g, "");
|
|
6253
|
+
return clear === "transparent" || clear === "rgba(0,0,0,0)";
|
|
6254
|
+
}
|
|
6255
|
+
|
|
6054
6256
|
// ../../apps/web/src/components/support-widget/sdk/session.ts
|
|
6055
6257
|
var STORAGE_PREFIX = "median:session:";
|
|
6056
6258
|
var inMemorySessions = /* @__PURE__ */ new Map();
|
|
@@ -6093,20 +6295,30 @@ function resetSessions() {
|
|
|
6093
6295
|
}
|
|
6094
6296
|
|
|
6095
6297
|
// ../../apps/web/src/components/support-widget/sdk/use-median-thread.ts
|
|
6096
|
-
import {
|
|
6298
|
+
import { useQuery } from "convex/react";
|
|
6299
|
+
|
|
6300
|
+
// ../../apps/web/src/hooks/use-audited-mutation.ts
|
|
6301
|
+
import { useMemo as useMemo2 } from "react";
|
|
6302
|
+
import { useMutation } from "convex/react";
|
|
6303
|
+
function useAuditedMutation(reference) {
|
|
6304
|
+
const mutation = useMutation(reference);
|
|
6305
|
+
return useMemo2(() => auditedClientMutation(mutation), [mutation]);
|
|
6306
|
+
}
|
|
6307
|
+
|
|
6308
|
+
// ../../apps/web/src/components/support-widget/sdk/use-median-thread.ts
|
|
6097
6309
|
import {
|
|
6098
6310
|
useCallback as useCallback11,
|
|
6099
6311
|
useEffect as useEffect17,
|
|
6100
|
-
useMemo as
|
|
6101
|
-
useState as
|
|
6312
|
+
useMemo as useMemo3,
|
|
6313
|
+
useState as useState18,
|
|
6102
6314
|
useSyncExternalStore as useSyncExternalStore9
|
|
6103
6315
|
} from "react";
|
|
6104
6316
|
|
|
6105
6317
|
// ../../apps/web/src/hooks/use-now.ts
|
|
6106
|
-
import { useEffect as
|
|
6318
|
+
import { useEffect as useEffect15, useState as useState17 } from "react";
|
|
6107
6319
|
function useNow(intervalMs = 3e4) {
|
|
6108
|
-
const [now, setNow] =
|
|
6109
|
-
|
|
6320
|
+
const [now, setNow] = useState17(() => Date.now());
|
|
6321
|
+
useEffect15(() => {
|
|
6110
6322
|
const timer = setInterval(() => setNow(Date.now()), intervalMs);
|
|
6111
6323
|
return () => clearInterval(timer);
|
|
6112
6324
|
}, [intervalMs]);
|
|
@@ -6114,13 +6326,13 @@ function useNow(intervalMs = 3e4) {
|
|
|
6114
6326
|
}
|
|
6115
6327
|
|
|
6116
6328
|
// ../../apps/web/src/lib/errors.ts
|
|
6117
|
-
import { ConvexError } from "convex/values";
|
|
6329
|
+
import { ConvexError as ConvexError2 } from "convex/values";
|
|
6118
6330
|
var FALLBACK = "Something went wrong on our end. Please try again.";
|
|
6119
6331
|
function isErrorPayload(data) {
|
|
6120
6332
|
return typeof data === "object" && data !== null && "message" in data && typeof data.message === "string";
|
|
6121
6333
|
}
|
|
6122
6334
|
function errorMessage(error) {
|
|
6123
|
-
if (error instanceof
|
|
6335
|
+
if (error instanceof ConvexError2) {
|
|
6124
6336
|
if (typeof error.data === "string") return error.data;
|
|
6125
6337
|
if (isErrorPayload(error.data)) return error.data.message;
|
|
6126
6338
|
}
|
|
@@ -6161,33 +6373,6 @@ function isNewDay(previous, next) {
|
|
|
6161
6373
|
return startOfDay(previous) !== startOfDay(next);
|
|
6162
6374
|
}
|
|
6163
6375
|
|
|
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
6376
|
// ../../apps/web/src/components/support-widget/sdk/rating-skips.ts
|
|
6192
6377
|
var STORAGE_PREFIX2 = "median:rating-skips:";
|
|
6193
6378
|
var MAX_REMEMBERED = 20;
|
|
@@ -6222,45 +6407,56 @@ function writeSkippedRating(apiKey, conversationId) {
|
|
|
6222
6407
|
}
|
|
6223
6408
|
}
|
|
6224
6409
|
|
|
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
|
-
}
|
|
6410
|
+
// ../../apps/web/src/components/support-widget/sdk/read-state.ts
|
|
6411
|
+
function isUnreadReply(message) {
|
|
6412
|
+
return message.sender === "agent" && !message.pending && !message.isRead;
|
|
6240
6413
|
}
|
|
6241
|
-
function
|
|
6242
|
-
|
|
6243
|
-
const
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6414
|
+
function widgetReadReceipts(messages, now) {
|
|
6415
|
+
const receipts = /* @__PURE__ */ new Map();
|
|
6416
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
6417
|
+
for (const message of messages) {
|
|
6418
|
+
const { conversationId } = message;
|
|
6419
|
+
if (!receipts.has(conversationId)) {
|
|
6420
|
+
receipts.set(conversationId, { conversationId });
|
|
6421
|
+
}
|
|
6422
|
+
if (blocked.has(conversationId)) continue;
|
|
6423
|
+
if (message.pending) {
|
|
6424
|
+
if (message.typingAt === null || now - message.typingAt <= TYPING_TTL_MS) {
|
|
6425
|
+
blocked.add(conversationId);
|
|
6426
|
+
}
|
|
6427
|
+
continue;
|
|
6428
|
+
}
|
|
6429
|
+
if (message.sender === "agent" && (message.body.trim() || message.attachments.length > 0)) {
|
|
6430
|
+
receipts.set(conversationId, { conversationId, messageId: message._id });
|
|
6431
|
+
}
|
|
6248
6432
|
}
|
|
6433
|
+
return [...receipts.values()];
|
|
6249
6434
|
}
|
|
6250
6435
|
|
|
6251
|
-
// ../../apps/web/src/components/support-widget/sdk/
|
|
6252
|
-
|
|
6253
|
-
function
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6436
|
+
// ../../apps/web/src/components/support-widget/sdk/use-screenshot-ask.ts
|
|
6437
|
+
import { useEffect as useEffect16, useRef as useRef17 } from "react";
|
|
6438
|
+
function useScreenshotAsk({
|
|
6439
|
+
ask,
|
|
6440
|
+
enabled: enabled2,
|
|
6441
|
+
answer
|
|
6442
|
+
}) {
|
|
6443
|
+
const answered = useRef17(/* @__PURE__ */ new Set());
|
|
6444
|
+
useEffect16(() => {
|
|
6445
|
+
if (ask === null || answered.current.has(ask.key)) return;
|
|
6446
|
+
answered.current.add(ask.key);
|
|
6447
|
+
void (async () => {
|
|
6448
|
+
const shot = enabled2 ? await capturePage() : null;
|
|
6449
|
+
await answer(ask.key, shot);
|
|
6450
|
+
})().catch((caught) => {
|
|
6451
|
+
console.warn("Median: answering the agent's request for a picture failed", caught);
|
|
6452
|
+
});
|
|
6453
|
+
}, [ask, enabled2, answer]);
|
|
6258
6454
|
}
|
|
6259
6455
|
|
|
6260
6456
|
// ../../apps/web/src/components/support-widget/sdk/visitor-email.ts
|
|
6261
6457
|
import { useCallback as useCallback10, useSyncExternalStore as useSyncExternalStore8 } from "react";
|
|
6262
6458
|
var STORAGE_PREFIX3 = "median:email:";
|
|
6263
|
-
var
|
|
6459
|
+
var inMemory2 = /* @__PURE__ */ new Map();
|
|
6264
6460
|
var listeners5 = /* @__PURE__ */ new Set();
|
|
6265
6461
|
function subscribeVisitorEmail(listener) {
|
|
6266
6462
|
listeners5.add(listener);
|
|
@@ -6274,11 +6470,11 @@ function readVisitorEmail(apiKey) {
|
|
|
6274
6470
|
const stored = window.localStorage.getItem(`${STORAGE_PREFIX3}${apiKey}`);
|
|
6275
6471
|
return stored && stored.length > 0 ? stored : null;
|
|
6276
6472
|
} catch {
|
|
6277
|
-
return
|
|
6473
|
+
return inMemory2.get(apiKey) ?? null;
|
|
6278
6474
|
}
|
|
6279
6475
|
}
|
|
6280
6476
|
function writeVisitorEmail(apiKey, email) {
|
|
6281
|
-
|
|
6477
|
+
inMemory2.set(apiKey, email);
|
|
6282
6478
|
try {
|
|
6283
6479
|
window.localStorage.setItem(`${STORAGE_PREFIX3}${apiKey}`, email);
|
|
6284
6480
|
} catch {
|
|
@@ -6286,7 +6482,7 @@ function writeVisitorEmail(apiKey, email) {
|
|
|
6286
6482
|
for (const listener of listeners5) listener();
|
|
6287
6483
|
}
|
|
6288
6484
|
function resetVisitorEmails() {
|
|
6289
|
-
|
|
6485
|
+
inMemory2.clear();
|
|
6290
6486
|
if (typeof window !== "undefined") {
|
|
6291
6487
|
try {
|
|
6292
6488
|
const stale = [];
|
|
@@ -6333,7 +6529,17 @@ var IDENTITY_COMPLAINTS = {
|
|
|
6333
6529
|
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
6530
|
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
6531
|
};
|
|
6336
|
-
function useMedianThread(
|
|
6532
|
+
function useMedianThread({
|
|
6533
|
+
apiKey,
|
|
6534
|
+
user,
|
|
6535
|
+
telemetry = true,
|
|
6536
|
+
screenshot = true,
|
|
6537
|
+
isLocked = false,
|
|
6538
|
+
diagnostics,
|
|
6539
|
+
appState,
|
|
6540
|
+
requireEmail = true,
|
|
6541
|
+
messagePreview = true
|
|
6542
|
+
}) {
|
|
6337
6543
|
const sessionId = useSyncExternalStore9(
|
|
6338
6544
|
subscribeSession,
|
|
6339
6545
|
useCallback11(() => getOrCreateSessionId(apiKey), [apiKey]),
|
|
@@ -6346,14 +6552,41 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6346
6552
|
api.widget.thread,
|
|
6347
6553
|
sessionId === null || isLocked ? "skip" : { apiKey, sessionId }
|
|
6348
6554
|
);
|
|
6349
|
-
const send =
|
|
6350
|
-
const sendTyping =
|
|
6351
|
-
const sendPresence =
|
|
6352
|
-
const rateConversation =
|
|
6353
|
-
const identify =
|
|
6354
|
-
const generateUploadUrl =
|
|
6555
|
+
const send = useAuditedMutation(api.widget.sendV2);
|
|
6556
|
+
const sendTyping = useAuditedMutation(api.widget.setTyping);
|
|
6557
|
+
const sendPresence = useAuditedMutation(api.widget.presence);
|
|
6558
|
+
const rateConversation = useAuditedMutation(api.widget.rateV2);
|
|
6559
|
+
const identify = useAuditedMutation(api.widget.identifyV2);
|
|
6560
|
+
const generateUploadUrl = useAuditedMutation(api.widget.generateUploadUrlV2);
|
|
6561
|
+
const answerScreenshot = useAuditedMutation(api.widget.answerScreenshotV2);
|
|
6562
|
+
const answerAsk = useCallback11(
|
|
6563
|
+
async (key, shot) => {
|
|
6564
|
+
if (sessionId === null) return;
|
|
6565
|
+
let attachment;
|
|
6566
|
+
if (shot !== null) {
|
|
6567
|
+
try {
|
|
6568
|
+
[attachment] = await uploadAttachments(
|
|
6569
|
+
() => generateUploadUrl({ apiKey, sessionId }),
|
|
6570
|
+
[shot]
|
|
6571
|
+
);
|
|
6572
|
+
} catch (caught) {
|
|
6573
|
+
console.warn(
|
|
6574
|
+
"Median: the picture the agent asked for could not be uploaded",
|
|
6575
|
+
caught
|
|
6576
|
+
);
|
|
6577
|
+
}
|
|
6578
|
+
}
|
|
6579
|
+
await answerScreenshot({
|
|
6580
|
+
apiKey,
|
|
6581
|
+
sessionId,
|
|
6582
|
+
key,
|
|
6583
|
+
...attachment === void 0 ? {} : { attachment }
|
|
6584
|
+
});
|
|
6585
|
+
},
|
|
6586
|
+
[apiKey, sessionId, generateUploadUrl, answerScreenshot]
|
|
6587
|
+
);
|
|
6355
6588
|
const identityKey = user ? JSON.stringify(user) : null;
|
|
6356
|
-
const identity =
|
|
6589
|
+
const identity = useMemo3(
|
|
6357
6590
|
() => identityKey === null ? null : JSON.parse(identityKey),
|
|
6358
6591
|
[identityKey]
|
|
6359
6592
|
);
|
|
@@ -6376,9 +6609,9 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6376
6609
|
) ?? false;
|
|
6377
6610
|
const now = useNow(hasLiveDots ? 1e3 : 6e4);
|
|
6378
6611
|
const takeDiagnostics = useDiagnostics(diagnostics, appState);
|
|
6379
|
-
const [isSending, setIsSending] =
|
|
6380
|
-
const [sendError, setSendError] =
|
|
6381
|
-
const agent =
|
|
6612
|
+
const [isSending, setIsSending] = useState18(false);
|
|
6613
|
+
const [sendError, setSendError] = useState18(null);
|
|
6614
|
+
const agent = useMemo3(
|
|
6382
6615
|
() => config === void 0 ? null : {
|
|
6383
6616
|
id: "median-agent",
|
|
6384
6617
|
name: config.agent.name,
|
|
@@ -6387,7 +6620,7 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6387
6620
|
},
|
|
6388
6621
|
[config]
|
|
6389
6622
|
);
|
|
6390
|
-
const messages =
|
|
6623
|
+
const messages = useMemo3(() => {
|
|
6391
6624
|
if (!thread || agent === null) return [];
|
|
6392
6625
|
const out = [];
|
|
6393
6626
|
let previousAt;
|
|
@@ -6436,7 +6669,7 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6436
6669
|
}
|
|
6437
6670
|
return out;
|
|
6438
6671
|
}, [thread, agent, now]);
|
|
6439
|
-
const presence =
|
|
6672
|
+
const presence = useMemo3(() => {
|
|
6440
6673
|
if (config === void 0 || agent === null) return null;
|
|
6441
6674
|
const humans = /* @__PURE__ */ new Map();
|
|
6442
6675
|
for (const message of messages) {
|
|
@@ -6450,17 +6683,16 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6450
6683
|
team: [...[...humans.values()].slice(-2), agent]
|
|
6451
6684
|
};
|
|
6452
6685
|
}, [config, agent, messages]);
|
|
6453
|
-
const
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
)
|
|
6458
|
-
|
|
6459
|
-
);
|
|
6686
|
+
const unread = useMemo3(() => {
|
|
6687
|
+
const unreadIds = new Set(
|
|
6688
|
+
thread?.messages.filter(isUnreadReply).map((message) => message._id)
|
|
6689
|
+
);
|
|
6690
|
+
return messages.filter((message) => unreadIds.has(message.id));
|
|
6691
|
+
}, [messages, thread]);
|
|
6460
6692
|
const unreadCount = unread.length;
|
|
6461
6693
|
const latestUnread = messagePreview && (config?.messagePreview ?? true) ? unread[unread.length - 1] ?? null : null;
|
|
6462
|
-
const [picked, setPicked] =
|
|
6463
|
-
const [skipped, setSkipped] =
|
|
6694
|
+
const [picked, setPicked] = useState18(null);
|
|
6695
|
+
const [skipped, setSkipped] = useState18(
|
|
6464
6696
|
() => readSkippedRatings(apiKey)
|
|
6465
6697
|
);
|
|
6466
6698
|
const conversationId = thread?.conversationId ?? null;
|
|
@@ -6484,15 +6716,6 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6484
6716
|
setSkipped((current2) => new Set(current2).add(conversationId));
|
|
6485
6717
|
}
|
|
6486
6718
|
} : 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
6719
|
async function handleSend(body, files) {
|
|
6497
6720
|
if (sessionId === null || isSending) return;
|
|
6498
6721
|
setSendError(null);
|
|
@@ -6534,12 +6757,29 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6534
6757
|
sendTyping({ apiKey, sessionId, isTyping }).catch(() => {
|
|
6535
6758
|
});
|
|
6536
6759
|
}
|
|
6760
|
+
const readsKey = JSON.stringify(
|
|
6761
|
+
widgetReadReceipts(thread?.messages ?? [], now)
|
|
6762
|
+
);
|
|
6763
|
+
const reads = useMemo3(
|
|
6764
|
+
() => JSON.parse(readsKey),
|
|
6765
|
+
[readsKey]
|
|
6766
|
+
);
|
|
6537
6767
|
const reportPresence = useCallback11(() => {
|
|
6538
6768
|
if (sessionId === null || isLocked) return;
|
|
6539
|
-
sendPresence({
|
|
6769
|
+
sendPresence({
|
|
6770
|
+
apiKey,
|
|
6771
|
+
sessionId,
|
|
6772
|
+
reads
|
|
6773
|
+
}).catch((caught) => {
|
|
6774
|
+
console.warn("Median: support read status could not be synced", caught);
|
|
6540
6775
|
});
|
|
6541
|
-
}, [apiKey, sessionId, isLocked, sendPresence]);
|
|
6776
|
+
}, [apiKey, sessionId, isLocked, sendPresence, reads]);
|
|
6542
6777
|
const ask = thread?.direction ?? null;
|
|
6778
|
+
useScreenshotAsk({
|
|
6779
|
+
ask: thread?.screenshotAsk ?? null,
|
|
6780
|
+
enabled: screenshot,
|
|
6781
|
+
answer: answerAsk
|
|
6782
|
+
});
|
|
6543
6783
|
return {
|
|
6544
6784
|
presence,
|
|
6545
6785
|
messages,
|
|
@@ -6574,7 +6814,6 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
6574
6814
|
unreadCount,
|
|
6575
6815
|
/** The newest of those, for the card on the closed button. */
|
|
6576
6816
|
latestUnread,
|
|
6577
|
-
markSeen,
|
|
6578
6817
|
/** Say the panel is on screen, so replies are not also emailed. */
|
|
6579
6818
|
reportPresence,
|
|
6580
6819
|
sendError,
|
|
@@ -6649,17 +6888,19 @@ async function reportError(error, options = {}) {
|
|
|
6649
6888
|
const diagnostics = snapshotNow({ ...factsOf(crash), ...options.state });
|
|
6650
6889
|
try {
|
|
6651
6890
|
client ??= new ConvexHttpClient(MEDIAN_DEPLOYMENT_URL);
|
|
6652
|
-
const
|
|
6891
|
+
const images = options.screenshot === false ? [] : await screenshotOf(client, apiKey, sessionId);
|
|
6892
|
+
const outcome = await client.mutation(api.feedback.reportErrorV2, {
|
|
6653
6893
|
apiKey,
|
|
6654
6894
|
sessionId,
|
|
6655
6895
|
error: crash,
|
|
6896
|
+
...images.length > 0 ? { images } : {},
|
|
6656
6897
|
...user ? { user: facts } : {},
|
|
6657
6898
|
...claim ? { identity: claim } : {},
|
|
6658
6899
|
...context ? { context } : {},
|
|
6659
6900
|
...page ? { page } : {},
|
|
6660
6901
|
...diagnostics ? { diagnostics } : {},
|
|
6661
6902
|
...custom ? { customData: custom } : {}
|
|
6662
|
-
});
|
|
6903
|
+
}).then(unwrapMutationResult);
|
|
6663
6904
|
if (outcome === "off") {
|
|
6664
6905
|
if (custom) restoreCustomData(custom);
|
|
6665
6906
|
return { reported: false, reason: REASONS.off };
|
|
@@ -6671,6 +6912,22 @@ async function reportError(error, options = {}) {
|
|
|
6671
6912
|
return { reported: false, reason: REASONS.failed };
|
|
6672
6913
|
}
|
|
6673
6914
|
}
|
|
6915
|
+
async function screenshotOf(client3, apiKey, sessionId) {
|
|
6916
|
+
try {
|
|
6917
|
+
const shot = await capturePage();
|
|
6918
|
+
if (shot === null) return [];
|
|
6919
|
+
return await uploadAttachments(
|
|
6920
|
+
() => client3.mutation(api.widget.generateUploadUrlV2, { apiKey, sessionId }).then(unwrapMutationResult),
|
|
6921
|
+
[shot]
|
|
6922
|
+
);
|
|
6923
|
+
} catch (caught) {
|
|
6924
|
+
console.warn(
|
|
6925
|
+
"Median: the crash report's screenshot could not be sent",
|
|
6926
|
+
caught
|
|
6927
|
+
);
|
|
6928
|
+
return [];
|
|
6929
|
+
}
|
|
6930
|
+
}
|
|
6674
6931
|
function useCanReportError() {
|
|
6675
6932
|
const isInstalled = useSyncExternalStore10(
|
|
6676
6933
|
subscribeInstall,
|
|
@@ -6683,6 +6940,34 @@ function useCanReportError() {
|
|
|
6683
6940
|
return isInstalled && Boolean(MEDIAN_DEPLOYMENT_URL);
|
|
6684
6941
|
}
|
|
6685
6942
|
|
|
6943
|
+
// ../../apps/web/src/components/support-widget/sdk/unread-store.ts
|
|
6944
|
+
import { useSyncExternalStore as useSyncExternalStore11 } from "react";
|
|
6945
|
+
var count = 0;
|
|
6946
|
+
var listeners6 = /* @__PURE__ */ new Set();
|
|
6947
|
+
var unreadStore = {
|
|
6948
|
+
subscribe(listener) {
|
|
6949
|
+
listeners6.add(listener);
|
|
6950
|
+
return () => {
|
|
6951
|
+
listeners6.delete(listener);
|
|
6952
|
+
};
|
|
6953
|
+
},
|
|
6954
|
+
read: () => count,
|
|
6955
|
+
/** The server has no thread to count, and neither does the first paint. */
|
|
6956
|
+
readServer: () => 0,
|
|
6957
|
+
set(next) {
|
|
6958
|
+
if (count === next) return;
|
|
6959
|
+
count = next;
|
|
6960
|
+
for (const listener of listeners6) listener();
|
|
6961
|
+
}
|
|
6962
|
+
};
|
|
6963
|
+
function useUnreadCount() {
|
|
6964
|
+
return useSyncExternalStore11(
|
|
6965
|
+
unreadStore.subscribe,
|
|
6966
|
+
unreadStore.read,
|
|
6967
|
+
unreadStore.readServer
|
|
6968
|
+
);
|
|
6969
|
+
}
|
|
6970
|
+
|
|
6686
6971
|
// ../../apps/web/src/components/support-widget/sdk/control.ts
|
|
6687
6972
|
var store = createOpenStore("MedianSupport");
|
|
6688
6973
|
var medianSupport = {
|
|
@@ -6690,6 +6975,10 @@ var medianSupport = {
|
|
|
6690
6975
|
get isOpen() {
|
|
6691
6976
|
return store.readEffective();
|
|
6692
6977
|
},
|
|
6978
|
+
/** Replies the visitor has not read. Zero while nothing is mounted. */
|
|
6979
|
+
get unreadCount() {
|
|
6980
|
+
return unreadStore.read();
|
|
6981
|
+
},
|
|
6693
6982
|
open() {
|
|
6694
6983
|
store.request(true);
|
|
6695
6984
|
store.warnIfNothingIsMounted("the widget was asked to open");
|
|
@@ -6743,13 +7032,15 @@ var medianSupport = {
|
|
|
6743
7032
|
}
|
|
6744
7033
|
};
|
|
6745
7034
|
function useMedianSupport() {
|
|
6746
|
-
const isOpen =
|
|
7035
|
+
const isOpen = useSyncExternalStore12(
|
|
6747
7036
|
store.subscribe,
|
|
6748
7037
|
store.readEffective,
|
|
6749
7038
|
store.readServerEffective
|
|
6750
7039
|
);
|
|
7040
|
+
const unreadCount = useUnreadCount();
|
|
6751
7041
|
return {
|
|
6752
7042
|
isOpen,
|
|
7043
|
+
unreadCount,
|
|
6753
7044
|
open: medianSupport.open,
|
|
6754
7045
|
close: medianSupport.close,
|
|
6755
7046
|
toggle: medianSupport.toggle,
|
|
@@ -6766,10 +7057,10 @@ function useRegisterMedianSupport() {
|
|
|
6766
7057
|
}
|
|
6767
7058
|
|
|
6768
7059
|
// ../../apps/web/src/components/support-widget/sdk/error-boundary.tsx
|
|
6769
|
-
import { ConvexError as
|
|
7060
|
+
import { ConvexError as ConvexError3 } from "convex/values";
|
|
6770
7061
|
import { Component } from "react";
|
|
6771
7062
|
function adviceFor(error) {
|
|
6772
|
-
if (error instanceof
|
|
7063
|
+
if (error instanceof ConvexError3 && typeof error.data === "object" && error.data !== null && error.data.code === "invalid_api_key") {
|
|
6773
7064
|
return "Median did not recognize the apiKey passed to <MedianSupport>, so the widget has been hidden. Derive it from an active MEDIAN_KEY with publicKeyFromMedianKey.";
|
|
6774
7065
|
}
|
|
6775
7066
|
return "The Median support widget hit an error and has been hidden. Your page is unaffected.";
|
|
@@ -6788,7 +7079,7 @@ var MedianErrorBoundary = class extends Component {
|
|
|
6788
7079
|
};
|
|
6789
7080
|
|
|
6790
7081
|
// ../../apps/web/src/components/support-widget/sdk/use-identity.ts
|
|
6791
|
-
import { useEffect as useEffect18, useState as
|
|
7082
|
+
import { useEffect as useEffect18, useState as useState19 } from "react";
|
|
6792
7083
|
var NOTHING = {
|
|
6793
7084
|
apiKey: void 0,
|
|
6794
7085
|
user: void 0,
|
|
@@ -6825,7 +7116,7 @@ function useMissingCredentials(component, apiKey, endpoint) {
|
|
|
6825
7116
|
}, [component, apiKey, endpoint]);
|
|
6826
7117
|
}
|
|
6827
7118
|
function useMedianIdentity(endpoint) {
|
|
6828
|
-
const [answered, setAnswered] =
|
|
7119
|
+
const [answered, setAnswered] = useState19(null);
|
|
6829
7120
|
useEffect18(() => {
|
|
6830
7121
|
if (endpoint === void 0) return;
|
|
6831
7122
|
let listening = true;
|
|
@@ -6861,6 +7152,45 @@ function useMedianIdentity(endpoint) {
|
|
|
6861
7152
|
return WAITING;
|
|
6862
7153
|
}
|
|
6863
7154
|
|
|
7155
|
+
// ../../apps/web/src/components/support-widget/sdk/use-median-branding.ts
|
|
7156
|
+
import { ConvexHttpClient as ConvexHttpClient2 } from "convex/browser";
|
|
7157
|
+
import { useEffect as useEffect19, useState as useState20 } from "react";
|
|
7158
|
+
function useMedianBranding(apiKey) {
|
|
7159
|
+
const [state, setState] = useState20({ key: apiKey, show: true });
|
|
7160
|
+
useEffect19(() => {
|
|
7161
|
+
if (!apiKey || !MEDIAN_DEPLOYMENT_URL) return;
|
|
7162
|
+
const client3 = new ConvexHttpClient2(MEDIAN_DEPLOYMENT_URL);
|
|
7163
|
+
let active = true;
|
|
7164
|
+
let expiry;
|
|
7165
|
+
async function refresh() {
|
|
7166
|
+
try {
|
|
7167
|
+
const result = await client3.action(api.billingAccess.branding, {
|
|
7168
|
+
apiKey
|
|
7169
|
+
});
|
|
7170
|
+
if (!active) return;
|
|
7171
|
+
clearTimeout(expiry);
|
|
7172
|
+
const expired = result.expiresAt !== null && result.expiresAt <= Date.now();
|
|
7173
|
+
setState({ key: apiKey, show: result.showBranding || expired });
|
|
7174
|
+
if (!result.showBranding && result.expiresAt !== null)
|
|
7175
|
+
expiry = setTimeout(
|
|
7176
|
+
() => setState({ key: apiKey, show: true }),
|
|
7177
|
+
Math.min(2147483647, Math.max(0, result.expiresAt - Date.now()))
|
|
7178
|
+
);
|
|
7179
|
+
} catch {
|
|
7180
|
+
if (active) setState({ key: apiKey, show: true });
|
|
7181
|
+
}
|
|
7182
|
+
}
|
|
7183
|
+
void refresh();
|
|
7184
|
+
const timer = setInterval(() => void refresh(), 6e4);
|
|
7185
|
+
return () => {
|
|
7186
|
+
active = false;
|
|
7187
|
+
clearInterval(timer);
|
|
7188
|
+
clearTimeout(expiry);
|
|
7189
|
+
};
|
|
7190
|
+
}, [apiKey]);
|
|
7191
|
+
return state.key === apiKey ? state.show : true;
|
|
7192
|
+
}
|
|
7193
|
+
|
|
6864
7194
|
// ../../apps/web/src/components/support-widget/sdk/median-connection.tsx
|
|
6865
7195
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
|
6866
7196
|
import { useState as useState21 } from "react";
|
|
@@ -6881,9 +7211,9 @@ function MedianConnection({
|
|
|
6881
7211
|
}
|
|
6882
7212
|
|
|
6883
7213
|
// ../../apps/web/src/components/support-widget/sdk/use-api-key-warning.ts
|
|
6884
|
-
import { useEffect as
|
|
7214
|
+
import { useEffect as useEffect20 } from "react";
|
|
6885
7215
|
function useApiKeyShapeWarning(component, apiKey) {
|
|
6886
|
-
|
|
7216
|
+
useEffect20(() => {
|
|
6887
7217
|
if (apiKey === void 0 || hasPrefix(apiKey, API_KEY_PREFIX)) return;
|
|
6888
7218
|
const shown = apiKey === "" ? "an empty string" : `"${apiKey.length > 16 ? `${apiKey.slice(0, 16)}\u2026` : apiKey}"`;
|
|
6889
7219
|
console.error(
|
|
@@ -7210,16 +7540,16 @@ function play(sound = "chime", options) {
|
|
|
7210
7540
|
}
|
|
7211
7541
|
|
|
7212
7542
|
// ../../apps/web/src/components/support-widget/sdk/use-message-sound.ts
|
|
7213
|
-
import { useEffect as
|
|
7543
|
+
import { useEffect as useEffect21, useRef as useRef18 } from "react";
|
|
7214
7544
|
var ARRIVAL_VOLUME = 0.45;
|
|
7215
7545
|
function useMessageSound({
|
|
7216
7546
|
messages,
|
|
7217
7547
|
conversationId = null,
|
|
7218
7548
|
isLoading
|
|
7219
7549
|
}) {
|
|
7220
|
-
const heard =
|
|
7221
|
-
const watching =
|
|
7222
|
-
|
|
7550
|
+
const heard = useRef18(null);
|
|
7551
|
+
const watching = useRef18(null);
|
|
7552
|
+
useEffect21(() => {
|
|
7223
7553
|
if (isLoading) {
|
|
7224
7554
|
heard.current = null;
|
|
7225
7555
|
return;
|
|
@@ -7243,7 +7573,7 @@ function useMessageSound({
|
|
|
7243
7573
|
}
|
|
7244
7574
|
|
|
7245
7575
|
// ../../apps/web/src/components/support-widget/sdk/use-navigation.ts
|
|
7246
|
-
import { useCallback as useCallback12, useEffect as
|
|
7576
|
+
import { useCallback as useCallback12, useEffect as useEffect22, useLayoutEffect as useLayoutEffect10, useRef as useRef19, useState as useState22 } from "react";
|
|
7247
7577
|
var isDevelopment2 = typeof process !== "undefined" && process.env.NODE_ENV === "development";
|
|
7248
7578
|
var STALE_AFTER_MS = 5 * 60 * 1e3;
|
|
7249
7579
|
function isFresh(at2) {
|
|
@@ -7287,10 +7617,10 @@ function useSupportNavigation({
|
|
|
7287
7617
|
isLoading,
|
|
7288
7618
|
onNavigate
|
|
7289
7619
|
}) {
|
|
7290
|
-
const seen =
|
|
7291
|
-
const watching =
|
|
7620
|
+
const seen = useRef19(null);
|
|
7621
|
+
const watching = useRef19(null);
|
|
7292
7622
|
const [spotlight, setSpotlight] = useState22(null);
|
|
7293
|
-
const drawn =
|
|
7623
|
+
const drawn = useRef19(0);
|
|
7294
7624
|
const [taken, setTaken] = useState22(null);
|
|
7295
7625
|
const follow = useCallback12(
|
|
7296
7626
|
(destination) => {
|
|
@@ -7314,7 +7644,7 @@ function useSupportNavigation({
|
|
|
7314
7644
|
},
|
|
7315
7645
|
[onNavigate]
|
|
7316
7646
|
);
|
|
7317
|
-
|
|
7647
|
+
useLayoutEffect10(() => {
|
|
7318
7648
|
if (isLoading) return;
|
|
7319
7649
|
const asked = ringing(messages, ask);
|
|
7320
7650
|
if (seen.current === null || watching.current !== conversationId) {
|
|
@@ -7332,8 +7662,8 @@ function useSupportNavigation({
|
|
|
7332
7662
|
}
|
|
7333
7663
|
if (latest !== null) setSpotlight(latest);
|
|
7334
7664
|
}, [messages, ask, conversationId, isLoading]);
|
|
7335
|
-
const warned =
|
|
7336
|
-
|
|
7665
|
+
const warned = useRef19(false);
|
|
7666
|
+
useEffect22(() => {
|
|
7337
7667
|
if (!isDevelopment2 || onNavigate !== void 0 || warned.current) return;
|
|
7338
7668
|
const offered = messages.some((message) => message.navigateTo !== void 0) || ask?.navigateTo != null;
|
|
7339
7669
|
if (!offered) return;
|
|
@@ -7343,11 +7673,11 @@ function useSupportNavigation({
|
|
|
7343
7673
|
);
|
|
7344
7674
|
}, [messages, ask, onNavigate]);
|
|
7345
7675
|
const [, expire] = useState22(0);
|
|
7346
|
-
|
|
7676
|
+
useEffect22(() => {
|
|
7347
7677
|
if (ask === null || ask.navigateTo === null) return;
|
|
7348
7678
|
const left = ask.at + STALE_AFTER_MS - Date.now();
|
|
7349
7679
|
if (left <= 0) return;
|
|
7350
|
-
const timer = setTimeout(() => expire((
|
|
7680
|
+
const timer = setTimeout(() => expire((count2) => count2 + 1), left);
|
|
7351
7681
|
return () => clearTimeout(timer);
|
|
7352
7682
|
}, [ask]);
|
|
7353
7683
|
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;
|
|
@@ -7357,6 +7687,32 @@ function useSupportNavigation({
|
|
|
7357
7687
|
// ../../apps/web/src/components/support-widget/sdk/use-teaser.ts
|
|
7358
7688
|
import { useCallback as useCallback13, useState as useState23 } from "react";
|
|
7359
7689
|
|
|
7690
|
+
// ../../apps/web/src/components/support-widget/sdk/stamps.ts
|
|
7691
|
+
var inMemory3 = /* @__PURE__ */ new Map();
|
|
7692
|
+
function keyOf(name, apiKey) {
|
|
7693
|
+
return `median:${name}:${apiKey}`;
|
|
7694
|
+
}
|
|
7695
|
+
function readStamp(name, apiKey) {
|
|
7696
|
+
if (typeof window === "undefined") return 0;
|
|
7697
|
+
const key = keyOf(name, apiKey);
|
|
7698
|
+
try {
|
|
7699
|
+
const stored = window.localStorage.getItem(key);
|
|
7700
|
+
const at2 = stored === null ? Number.NaN : Number(stored);
|
|
7701
|
+
return Number.isFinite(at2) ? at2 : 0;
|
|
7702
|
+
} catch {
|
|
7703
|
+
return inMemory3.get(key) ?? 0;
|
|
7704
|
+
}
|
|
7705
|
+
}
|
|
7706
|
+
function writeStamp(name, apiKey, at2) {
|
|
7707
|
+
if (typeof window === "undefined") return;
|
|
7708
|
+
const key = keyOf(name, apiKey);
|
|
7709
|
+
inMemory3.set(key, at2);
|
|
7710
|
+
try {
|
|
7711
|
+
window.localStorage.setItem(key, String(at2));
|
|
7712
|
+
} catch {
|
|
7713
|
+
}
|
|
7714
|
+
}
|
|
7715
|
+
|
|
7360
7716
|
// ../../apps/web/src/components/support-widget/sdk/teaser-state.ts
|
|
7361
7717
|
var TEASER = "teaser";
|
|
7362
7718
|
function readTeaserDismissedAt(apiKey) {
|
|
@@ -7381,8 +7737,38 @@ function useTeaser(apiKey, latestUnread) {
|
|
|
7381
7737
|
return { teaser, dismiss };
|
|
7382
7738
|
}
|
|
7383
7739
|
|
|
7740
|
+
// ../../apps/web/src/components/support-widget/sdk/use-unread-title.ts
|
|
7741
|
+
import { useEffect as useEffect23 } from "react";
|
|
7742
|
+
function badged(count2, title) {
|
|
7743
|
+
return `(${count2}) ${title}`.trim();
|
|
7744
|
+
}
|
|
7745
|
+
function useUnreadTitle(unreadCount) {
|
|
7746
|
+
useEffect23(() => {
|
|
7747
|
+
if (unreadCount === 0 || typeof document === "undefined") return;
|
|
7748
|
+
let plain = document.title;
|
|
7749
|
+
let shown = badged(unreadCount, plain);
|
|
7750
|
+
document.title = shown;
|
|
7751
|
+
const observer = new MutationObserver(() => {
|
|
7752
|
+
const current2 = document.title;
|
|
7753
|
+
if (current2 === shown) return;
|
|
7754
|
+
plain = current2;
|
|
7755
|
+
shown = badged(unreadCount, plain);
|
|
7756
|
+
document.title = shown;
|
|
7757
|
+
});
|
|
7758
|
+
observer.observe(document.head, {
|
|
7759
|
+
childList: true,
|
|
7760
|
+
subtree: true,
|
|
7761
|
+
characterData: true
|
|
7762
|
+
});
|
|
7763
|
+
return () => {
|
|
7764
|
+
observer.disconnect();
|
|
7765
|
+
if (document.title === shown) document.title = plain;
|
|
7766
|
+
};
|
|
7767
|
+
}, [unreadCount]);
|
|
7768
|
+
}
|
|
7769
|
+
|
|
7384
7770
|
// ../../apps/web/src/components/support-widget/sdk/median-support.tsx
|
|
7385
|
-
import { Fragment as Fragment31, jsx as jsx38, jsxs as
|
|
7771
|
+
import { Fragment as Fragment31, jsx as jsx38, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
7386
7772
|
var PRESENCE_BEAT_MS = 45e3;
|
|
7387
7773
|
function MedianSupport(props) {
|
|
7388
7774
|
return /* @__PURE__ */ jsx38(MedianSupportPreview, { ...props });
|
|
@@ -7422,12 +7808,14 @@ function MedianLauncher({
|
|
|
7422
7808
|
apiKey,
|
|
7423
7809
|
user,
|
|
7424
7810
|
telemetry,
|
|
7811
|
+
screenshot,
|
|
7425
7812
|
diagnostics,
|
|
7426
7813
|
appState,
|
|
7427
7814
|
requireSignIn = false,
|
|
7428
7815
|
onSignIn,
|
|
7429
7816
|
requireEmail = true,
|
|
7430
7817
|
messagePreview = true,
|
|
7818
|
+
titleCount = true,
|
|
7431
7819
|
launcher,
|
|
7432
7820
|
presentation,
|
|
7433
7821
|
defaultOpen,
|
|
@@ -7443,6 +7831,7 @@ function MedianLauncher({
|
|
|
7443
7831
|
apiKey
|
|
7444
7832
|
);
|
|
7445
7833
|
useRememberInstall(apiKey, user);
|
|
7834
|
+
const showBranding = useMedianBranding(apiKey);
|
|
7446
7835
|
const [isOpen, setOpen] = useMedianOpenState({
|
|
7447
7836
|
open,
|
|
7448
7837
|
defaultOpen,
|
|
@@ -7462,31 +7851,28 @@ function MedianLauncher({
|
|
|
7462
7851
|
rating,
|
|
7463
7852
|
unreadCount,
|
|
7464
7853
|
latestUnread,
|
|
7465
|
-
markSeen,
|
|
7466
7854
|
reportPresence,
|
|
7467
7855
|
sendError,
|
|
7468
7856
|
send,
|
|
7469
7857
|
setTyping
|
|
7470
|
-
} = useMedianThread(
|
|
7858
|
+
} = useMedianThread({
|
|
7471
7859
|
apiKey,
|
|
7472
7860
|
user,
|
|
7473
7861
|
telemetry,
|
|
7862
|
+
screenshot,
|
|
7474
7863
|
isLocked,
|
|
7475
7864
|
diagnostics,
|
|
7476
7865
|
appState,
|
|
7477
7866
|
requireEmail,
|
|
7478
7867
|
messagePreview
|
|
7479
|
-
);
|
|
7868
|
+
});
|
|
7480
7869
|
const { teaser, dismiss: dismissTeaser } = useTeaser(apiKey, latestUnread);
|
|
7481
7870
|
const isSettling = isLoading || isResolvingIdentity;
|
|
7482
|
-
|
|
7483
|
-
if (isOpen) markSeen();
|
|
7484
|
-
}, [isOpen, markSeen]);
|
|
7485
|
-
useEffect22(() => {
|
|
7871
|
+
useEffect24(() => {
|
|
7486
7872
|
if (!threadRendersMarkdown(messages)) return;
|
|
7487
7873
|
return warmMarkdownWhenIdle();
|
|
7488
7874
|
}, [messages]);
|
|
7489
|
-
|
|
7875
|
+
useEffect24(() => {
|
|
7490
7876
|
if (!isOpen) return;
|
|
7491
7877
|
const beat = () => {
|
|
7492
7878
|
if (document.visibilityState === "visible") reportPresence();
|
|
@@ -7519,16 +7905,22 @@ function MedianLauncher({
|
|
|
7519
7905
|
conversationId,
|
|
7520
7906
|
isLoading: isSettling || isLocked
|
|
7521
7907
|
});
|
|
7908
|
+
useUnreadTitle(titleCount ? unreadCount : 0);
|
|
7909
|
+
useEffect24(() => {
|
|
7910
|
+
unreadStore.set(unreadCount);
|
|
7911
|
+
}, [unreadCount]);
|
|
7912
|
+
useEffect24(() => () => unreadStore.set(0), []);
|
|
7522
7913
|
const resolvedPresence = presence ?? {
|
|
7523
7914
|
name: "Support",
|
|
7524
7915
|
status: "Connecting",
|
|
7525
7916
|
team: []
|
|
7526
7917
|
};
|
|
7527
|
-
return /* @__PURE__ */
|
|
7918
|
+
return /* @__PURE__ */ jsxs22(Fragment31, { children: [
|
|
7528
7919
|
spotlight !== null && /* @__PURE__ */ jsx38(WidgetSpotlight, { selector: spotlight.selector }, spotlight.key),
|
|
7529
7920
|
/* @__PURE__ */ jsx38(
|
|
7530
7921
|
SupportLauncher,
|
|
7531
7922
|
{
|
|
7923
|
+
showBadge: showBranding,
|
|
7532
7924
|
presence: resolvedPresence,
|
|
7533
7925
|
messages,
|
|
7534
7926
|
onSend: send,
|
|
@@ -7644,7 +8036,12 @@ function mountMedianSupportModal(options) {
|
|
|
7644
8036
|
}
|
|
7645
8037
|
|
|
7646
8038
|
// ../../apps/web/src/components/support-widget/sdk/median-feedback.tsx
|
|
7647
|
-
import {
|
|
8039
|
+
import {
|
|
8040
|
+
useCallback as useCallback15,
|
|
8041
|
+
useEffect as useEffect27,
|
|
8042
|
+
useRef as useRef22,
|
|
8043
|
+
useState as useState27
|
|
8044
|
+
} from "react";
|
|
7648
8045
|
|
|
7649
8046
|
// ../backend/convex/shared/feedback.ts
|
|
7650
8047
|
var NOTE_MAX_LENGTH = 2e3;
|
|
@@ -7654,17 +8051,17 @@ var MAX_REPORT_IMAGES = 6;
|
|
|
7654
8051
|
|
|
7655
8052
|
// ../../apps/web/src/components/support-widget/feedback/feedback-panel.tsx
|
|
7656
8053
|
import {
|
|
7657
|
-
useEffect as
|
|
7658
|
-
useRef as
|
|
8054
|
+
useEffect as useEffect26,
|
|
8055
|
+
useRef as useRef21,
|
|
7659
8056
|
useState as useState25
|
|
7660
8057
|
} from "react";
|
|
7661
8058
|
|
|
7662
8059
|
// ../../apps/web/src/components/support-widget/feedback/feedback-popover.tsx
|
|
7663
|
-
import { useEffect as
|
|
8060
|
+
import { useEffect as useEffect25, useRef as useRef20 } from "react";
|
|
7664
8061
|
import { createPortal as createPortal3 } from "react-dom";
|
|
7665
8062
|
|
|
7666
8063
|
// ../../apps/web/src/components/support-widget/feedback/use-anchor.ts
|
|
7667
|
-
import { useLayoutEffect as
|
|
8064
|
+
import { useLayoutEffect as useLayoutEffect11, useState as useState24 } from "react";
|
|
7668
8065
|
var GAP2 = 8;
|
|
7669
8066
|
var MARGIN2 = 16;
|
|
7670
8067
|
function findAnchor(selector) {
|
|
@@ -7685,7 +8082,7 @@ function useAnchor({
|
|
|
7685
8082
|
isOpen
|
|
7686
8083
|
}) {
|
|
7687
8084
|
const [side, setSide] = useState24("bottom");
|
|
7688
|
-
|
|
8085
|
+
useLayoutEffect11(() => {
|
|
7689
8086
|
if (!isOpen) return;
|
|
7690
8087
|
let frame = 0;
|
|
7691
8088
|
function place() {
|
|
@@ -7753,12 +8150,12 @@ function FeedbackPopover({
|
|
|
7753
8150
|
width,
|
|
7754
8151
|
children
|
|
7755
8152
|
}) {
|
|
7756
|
-
const panelRef =
|
|
8153
|
+
const panelRef = useRef20(null);
|
|
7757
8154
|
const side = useAnchor({ triggerRef, anchor, panelRef, isOpen });
|
|
7758
8155
|
const isHydrated = useHydrated();
|
|
7759
|
-
const opener =
|
|
7760
|
-
const wasOpen =
|
|
7761
|
-
|
|
8156
|
+
const opener = useRef20(null);
|
|
8157
|
+
const wasOpen = useRef20(isOpen);
|
|
8158
|
+
useEffect25(() => {
|
|
7762
8159
|
if (!isOpen) return;
|
|
7763
8160
|
function handleKeyDown(event) {
|
|
7764
8161
|
if (event.key === "Escape") onClose();
|
|
@@ -7766,7 +8163,7 @@ function FeedbackPopover({
|
|
|
7766
8163
|
document.addEventListener("keydown", handleKeyDown);
|
|
7767
8164
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
7768
8165
|
}, [isOpen, onClose]);
|
|
7769
|
-
|
|
8166
|
+
useEffect25(() => {
|
|
7770
8167
|
if (!isOpen) return;
|
|
7771
8168
|
function handlePointerDown(event) {
|
|
7772
8169
|
const target = event.target;
|
|
@@ -7778,7 +8175,7 @@ function FeedbackPopover({
|
|
|
7778
8175
|
document.addEventListener("pointerdown", handlePointerDown);
|
|
7779
8176
|
return () => document.removeEventListener("pointerdown", handlePointerDown);
|
|
7780
8177
|
}, [isOpen, onClose, triggerRef]);
|
|
7781
|
-
|
|
8178
|
+
useEffect25(() => {
|
|
7782
8179
|
if (wasOpen.current === isOpen) return;
|
|
7783
8180
|
wasOpen.current = isOpen;
|
|
7784
8181
|
if (isOpen) {
|
|
@@ -7834,7 +8231,7 @@ function FeedbackPopover({
|
|
|
7834
8231
|
}
|
|
7835
8232
|
|
|
7836
8233
|
// ../../apps/web/src/components/support-widget/feedback/feedback-panel.tsx
|
|
7837
|
-
import { Fragment as Fragment32, jsx as jsx43, jsxs as
|
|
8234
|
+
import { Fragment as Fragment32, jsx as jsx43, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
7838
8235
|
var THANKS_MS2 = 1600;
|
|
7839
8236
|
function FeedbackPanel({
|
|
7840
8237
|
onSubmit,
|
|
@@ -7843,21 +8240,21 @@ function FeedbackPanel({
|
|
|
7843
8240
|
notice,
|
|
7844
8241
|
showBadge = true,
|
|
7845
8242
|
title = "Share feedback",
|
|
7846
|
-
description = "
|
|
8243
|
+
description = "Bugs, ideas, anything.",
|
|
7847
8244
|
placeholder = "Tell us what could be better.",
|
|
7848
8245
|
className
|
|
7849
8246
|
}) {
|
|
7850
8247
|
const [draft, setDraft] = useState25("");
|
|
7851
8248
|
const [isSending, setSending] = useState25(false);
|
|
7852
8249
|
const [isSent, setSent] = useState25(false);
|
|
7853
|
-
const fileInputRef =
|
|
8250
|
+
const fileInputRef = useRef21(null);
|
|
7854
8251
|
const images = useAttachmentDrafts({
|
|
7855
8252
|
accept: "image",
|
|
7856
8253
|
max: MAX_REPORT_IMAGES
|
|
7857
8254
|
});
|
|
7858
8255
|
const target = useAttachmentTarget({ onFiles: images.add });
|
|
7859
8256
|
const canSend = draft.trim().length > 0 && !images.hasBlocker && !isSending && !isSent;
|
|
7860
|
-
|
|
8257
|
+
useEffect26(() => {
|
|
7861
8258
|
if (!isSent) return;
|
|
7862
8259
|
const timer = setTimeout(() => onSent?.(), THANKS_MS2);
|
|
7863
8260
|
return () => clearTimeout(timer);
|
|
@@ -7885,7 +8282,7 @@ function FeedbackPanel({
|
|
|
7885
8282
|
event.preventDefault();
|
|
7886
8283
|
void send();
|
|
7887
8284
|
}
|
|
7888
|
-
return /* @__PURE__ */
|
|
8285
|
+
return /* @__PURE__ */ jsxs23(
|
|
7889
8286
|
"section",
|
|
7890
8287
|
{
|
|
7891
8288
|
"aria-label": title,
|
|
@@ -7893,12 +8290,12 @@ function FeedbackPanel({
|
|
|
7893
8290
|
className: cn(
|
|
7894
8291
|
// The widget's own radius scale, so the app's token can climb as the
|
|
7895
8292
|
// chrome gets rounder without this changing shape under its hosts.
|
|
7896
|
-
|
|
8293
|
+
`flex w-full flex-col gap-2 overflow-hidden ${WIDGET_CORNER} border bg-card p-3 text-card-foreground [--radius:0.625rem]`,
|
|
7897
8294
|
className
|
|
7898
8295
|
),
|
|
7899
8296
|
children: [
|
|
7900
|
-
/* @__PURE__ */
|
|
7901
|
-
/* @__PURE__ */
|
|
8297
|
+
/* @__PURE__ */ jsxs23("header", { className: "flex items-start gap-2", children: [
|
|
8298
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
7902
8299
|
/* @__PURE__ */ jsx43("h2", { className: "truncate text-sm font-semibold tracking-tight", children: title }),
|
|
7903
8300
|
/* @__PURE__ */ jsx43("p", { className: "text-xs text-muted-foreground", children: description })
|
|
7904
8301
|
] }),
|
|
@@ -7915,8 +8312,8 @@ function FeedbackPanel({
|
|
|
7915
8312
|
}
|
|
7916
8313
|
)
|
|
7917
8314
|
] }),
|
|
7918
|
-
/* @__PURE__ */
|
|
7919
|
-
/* @__PURE__ */ jsx43(Collapse, { isOpen: !isSent, children: /* @__PURE__ */
|
|
8315
|
+
/* @__PURE__ */ jsxs23("div", { className: "grid", children: [
|
|
8316
|
+
/* @__PURE__ */ jsx43(Collapse, { isOpen: !isSent, children: /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-1.5", children: [
|
|
7920
8317
|
/* @__PURE__ */ jsx43(
|
|
7921
8318
|
Textarea,
|
|
7922
8319
|
{
|
|
@@ -7929,7 +8326,7 @@ function FeedbackPanel({
|
|
|
7929
8326
|
"aria-label": title,
|
|
7930
8327
|
...{ [AUTOFOCUS_ATTRIBUTE]: "" },
|
|
7931
8328
|
className: cn(
|
|
7932
|
-
|
|
8329
|
+
WIDGET_TEXT_FIELD_SHELL,
|
|
7933
8330
|
"max-h-40 min-h-18 px-2.5 py-2",
|
|
7934
8331
|
// 16px on phones, in pixels: any focused field smaller than
|
|
7935
8332
|
// that makes iOS zoom the host's whole page in.
|
|
@@ -7947,14 +8344,14 @@ function FeedbackPanel({
|
|
|
7947
8344
|
)) }),
|
|
7948
8345
|
notice && /* @__PURE__ */ jsx43("p", { className: "animate-in px-0.5 text-xs text-destructive fade-in duration-150", children: notice })
|
|
7949
8346
|
] }) }),
|
|
7950
|
-
/* @__PURE__ */ jsx43(Collapse, { isOpen: isSent, children: /* @__PURE__ */
|
|
8347
|
+
/* @__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
8348
|
/* @__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
8349
|
"Thanks for your feedback."
|
|
7953
8350
|
] }) })
|
|
7954
8351
|
] }),
|
|
7955
|
-
/* @__PURE__ */
|
|
8352
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex min-h-8 items-center gap-2", children: [
|
|
7956
8353
|
showBadge && /* @__PURE__ */ jsx43(PoweredByMedian, { className: "justify-start" }),
|
|
7957
|
-
!isSent && /* @__PURE__ */
|
|
8354
|
+
!isSent && /* @__PURE__ */ jsxs23(Fragment32, { children: [
|
|
7958
8355
|
/* @__PURE__ */ jsx43(
|
|
7959
8356
|
"input",
|
|
7960
8357
|
{
|
|
@@ -7980,7 +8377,7 @@ function FeedbackPanel({
|
|
|
7980
8377
|
children: /* @__PURE__ */ jsx43(ImageSquare, {})
|
|
7981
8378
|
}
|
|
7982
8379
|
),
|
|
7983
|
-
/* @__PURE__ */
|
|
8380
|
+
/* @__PURE__ */ jsxs23(
|
|
7984
8381
|
WidgetButton,
|
|
7985
8382
|
{
|
|
7986
8383
|
type: "button",
|
|
@@ -8017,7 +8414,7 @@ function FeedbackPanel({
|
|
|
8017
8414
|
}
|
|
8018
8415
|
|
|
8019
8416
|
// ../../apps/web/src/components/support-widget/sdk/feedback-control.ts
|
|
8020
|
-
import { useSyncExternalStore as
|
|
8417
|
+
import { useSyncExternalStore as useSyncExternalStore13 } from "react";
|
|
8021
8418
|
var store2 = createOpenStore("MedianFeedback");
|
|
8022
8419
|
var medianFeedback = {
|
|
8023
8420
|
/** What the panel is doing right now. */
|
|
@@ -8040,7 +8437,7 @@ var medianFeedback = {
|
|
|
8040
8437
|
}
|
|
8041
8438
|
};
|
|
8042
8439
|
function useMedianFeedback() {
|
|
8043
|
-
const isOpen =
|
|
8440
|
+
const isOpen = useSyncExternalStore13(
|
|
8044
8441
|
store2.subscribe,
|
|
8045
8442
|
store2.readEffective,
|
|
8046
8443
|
store2.readServerEffective
|
|
@@ -8060,8 +8457,7 @@ function useRegisterMedianFeedback() {
|
|
|
8060
8457
|
}
|
|
8061
8458
|
|
|
8062
8459
|
// ../../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";
|
|
8460
|
+
import { useCallback as useCallback14, useState as useState26, useSyncExternalStore as useSyncExternalStore14 } from "react";
|
|
8065
8461
|
var REFUSALS = {
|
|
8066
8462
|
off: "Feedback is currently unavailable. Try again later.",
|
|
8067
8463
|
empty: "Enter your feedback before sending."
|
|
@@ -8070,16 +8466,17 @@ function useFeedbackNote({
|
|
|
8070
8466
|
apiKey,
|
|
8071
8467
|
user,
|
|
8072
8468
|
telemetry = true,
|
|
8469
|
+
screenshot = true,
|
|
8073
8470
|
diagnostics,
|
|
8074
8471
|
appState
|
|
8075
8472
|
}) {
|
|
8076
|
-
const sessionId =
|
|
8473
|
+
const sessionId = useSyncExternalStore14(
|
|
8077
8474
|
subscribeSession,
|
|
8078
8475
|
useCallback14(() => getOrCreateSessionId(apiKey), [apiKey]),
|
|
8079
8476
|
() => null
|
|
8080
8477
|
);
|
|
8081
|
-
const submitNote =
|
|
8082
|
-
const getUploadUrl =
|
|
8478
|
+
const submitNote = useAuditedMutation(api.feedback.submitV2);
|
|
8479
|
+
const getUploadUrl = useAuditedMutation(api.widget.generateUploadUrlV2);
|
|
8083
8480
|
const takeDiagnostics = useDiagnostics(diagnostics, appState);
|
|
8084
8481
|
const [notice, setNotice] = useState26(null);
|
|
8085
8482
|
const submit = useCallback14(
|
|
@@ -8096,9 +8493,10 @@ function useFeedbackNote({
|
|
|
8096
8493
|
const page = telemetry ? collectPage() : void 0;
|
|
8097
8494
|
const collected = takeDiagnostics();
|
|
8098
8495
|
const { facts, claim } = splitIdentity(user ?? null);
|
|
8496
|
+
const shot = screenshot && images.length < MAX_REPORT_IMAGES ? await capturePage() : null;
|
|
8099
8497
|
const attached = await uploadAttachments(
|
|
8100
8498
|
() => getUploadUrl({ apiKey, sessionId }),
|
|
8101
|
-
images
|
|
8499
|
+
shot === null ? images : [...images, shot]
|
|
8102
8500
|
);
|
|
8103
8501
|
const outcome = await submitNote({
|
|
8104
8502
|
apiKey,
|
|
@@ -8114,13 +8512,18 @@ function useFeedbackNote({
|
|
|
8114
8512
|
});
|
|
8115
8513
|
if (outcome !== "taken") {
|
|
8116
8514
|
explained = true;
|
|
8117
|
-
setNotice(
|
|
8515
|
+
setNotice(
|
|
8516
|
+
REFUSALS[outcome] ?? "Could not send your feedback. Try again."
|
|
8517
|
+
);
|
|
8118
8518
|
throw new Error(outcome);
|
|
8119
8519
|
}
|
|
8120
8520
|
} catch (caught) {
|
|
8121
8521
|
if (custom) restoreCustomData(custom);
|
|
8122
8522
|
if (!explained) {
|
|
8123
|
-
console.error(
|
|
8523
|
+
console.error(
|
|
8524
|
+
"Sending feedback from the Median panel failed",
|
|
8525
|
+
caught
|
|
8526
|
+
);
|
|
8124
8527
|
setNotice(errorMessage(caught));
|
|
8125
8528
|
}
|
|
8126
8529
|
throw caught;
|
|
@@ -8131,6 +8534,7 @@ function useFeedbackNote({
|
|
|
8131
8534
|
sessionId,
|
|
8132
8535
|
user,
|
|
8133
8536
|
telemetry,
|
|
8537
|
+
screenshot,
|
|
8134
8538
|
takeDiagnostics,
|
|
8135
8539
|
submitNote,
|
|
8136
8540
|
getUploadUrl
|
|
@@ -8140,7 +8544,7 @@ function useFeedbackNote({
|
|
|
8140
8544
|
}
|
|
8141
8545
|
|
|
8142
8546
|
// ../../apps/web/src/components/support-widget/sdk/median-feedback.tsx
|
|
8143
|
-
import { Fragment as Fragment33, jsx as jsx44, jsxs as
|
|
8547
|
+
import { Fragment as Fragment33, jsx as jsx44, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
8144
8548
|
var DEFAULT_WIDTH2 = "20rem";
|
|
8145
8549
|
function MedianFeedback(props) {
|
|
8146
8550
|
return /* @__PURE__ */ jsx44(MedianErrorBoundary, { children: /* @__PURE__ */ jsx44(FeedbackIdentity, { ...props }) });
|
|
@@ -8156,14 +8560,7 @@ function FeedbackIdentity({
|
|
|
8156
8560
|
const key = apiKey ?? resolved.apiKey;
|
|
8157
8561
|
const person = user ?? resolved.user;
|
|
8158
8562
|
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
|
-
) });
|
|
8563
|
+
return /* @__PURE__ */ jsx44(MedianConnection, { what: "feedback panel", children: /* @__PURE__ */ jsx44(Feedback, { ...rest, apiKey: key, ...person ? { user: person } : {} }) });
|
|
8167
8564
|
}
|
|
8168
8565
|
function Feedback({
|
|
8169
8566
|
apiKey,
|
|
@@ -8171,6 +8568,7 @@ function Feedback({
|
|
|
8171
8568
|
anchor,
|
|
8172
8569
|
user,
|
|
8173
8570
|
telemetry,
|
|
8571
|
+
screenshot,
|
|
8174
8572
|
diagnostics,
|
|
8175
8573
|
appState,
|
|
8176
8574
|
open,
|
|
@@ -8183,7 +8581,7 @@ function Feedback({
|
|
|
8183
8581
|
useRegisterMedianFeedback();
|
|
8184
8582
|
useApiKeyShapeWarning("MedianFeedback", apiKey);
|
|
8185
8583
|
useRememberInstall(apiKey, user);
|
|
8186
|
-
const triggerRef =
|
|
8584
|
+
const triggerRef = useRef22(null);
|
|
8187
8585
|
const [isOpen, setOpen] = useMedianFeedbackOpenState({
|
|
8188
8586
|
...open !== void 0 ? { open } : {},
|
|
8189
8587
|
...onOpenChange ? { onOpenChange } : {}
|
|
@@ -8192,18 +8590,20 @@ function Feedback({
|
|
|
8192
8590
|
apiKey,
|
|
8193
8591
|
...user ? { user } : {},
|
|
8194
8592
|
...telemetry !== void 0 ? { telemetry } : {},
|
|
8593
|
+
...screenshot !== void 0 ? { screenshot } : {},
|
|
8195
8594
|
...diagnostics !== void 0 ? { diagnostics } : {},
|
|
8196
8595
|
...appState ? { appState } : {}
|
|
8197
8596
|
});
|
|
8597
|
+
const showBranding = useMedianBranding(apiKey);
|
|
8198
8598
|
const close = useCallback15(() => setOpen(false), [setOpen]);
|
|
8199
8599
|
const [attempt, setAttempt] = useState27(0);
|
|
8200
|
-
const hasSent =
|
|
8201
|
-
|
|
8600
|
+
const hasSent = useRef22(false);
|
|
8601
|
+
useEffect27(() => {
|
|
8202
8602
|
if (!isOpen || !hasSent.current) return;
|
|
8203
8603
|
hasSent.current = false;
|
|
8204
|
-
setAttempt((
|
|
8604
|
+
setAttempt((count2) => count2 + 1);
|
|
8205
8605
|
}, [isOpen]);
|
|
8206
|
-
return /* @__PURE__ */
|
|
8606
|
+
return /* @__PURE__ */ jsxs24(Fragment33, { children: [
|
|
8207
8607
|
children !== void 0 && // An inline span rather than a clone of whatever was passed: the
|
|
8208
8608
|
// host's trigger keeps its own props, its own ref and its own
|
|
8209
8609
|
// styles, and the click is caught on the way past. `display:
|
|
@@ -8228,6 +8628,7 @@ function Feedback({
|
|
|
8228
8628
|
children: /* @__PURE__ */ jsx44(
|
|
8229
8629
|
FeedbackPanel,
|
|
8230
8630
|
{
|
|
8631
|
+
showBadge: showBranding,
|
|
8231
8632
|
onSubmit: note.submit,
|
|
8232
8633
|
onClose: close,
|
|
8233
8634
|
onSent: () => {
|
|
@@ -8260,23 +8661,23 @@ function mountMedianFeedback(options) {
|
|
|
8260
8661
|
}
|
|
8261
8662
|
|
|
8262
8663
|
// ../../apps/web/src/components/support-widget/sdk/median-contact-form.tsx
|
|
8263
|
-
import { useEffect as
|
|
8664
|
+
import { useEffect as useEffect29, useMemo as useMemo6 } from "react";
|
|
8264
8665
|
|
|
8265
8666
|
// ../../apps/web/src/components/support-widget/contact/contact-form.tsx
|
|
8266
8667
|
import {
|
|
8267
|
-
useEffect as
|
|
8668
|
+
useEffect as useEffect28,
|
|
8268
8669
|
useId,
|
|
8269
|
-
useMemo as
|
|
8270
|
-
useRef as
|
|
8670
|
+
useMemo as useMemo4,
|
|
8671
|
+
useRef as useRef24,
|
|
8271
8672
|
useState as useState29
|
|
8272
8673
|
} from "react";
|
|
8273
8674
|
|
|
8274
8675
|
// ../../apps/web/src/components/support-widget/contact/contact-field.tsx
|
|
8275
8676
|
import { useState as useState28 } from "react";
|
|
8276
|
-
import { jsx as jsx46, jsxs as
|
|
8677
|
+
import { jsx as jsx46, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
8277
8678
|
var LINE_MAX_LENGTH = 200;
|
|
8278
8679
|
var SHELL = cn(
|
|
8279
|
-
|
|
8680
|
+
WIDGET_TEXT_FIELD_SHELL,
|
|
8280
8681
|
"w-full bg-card text-base max-sm:text-[16px] dark:bg-card"
|
|
8281
8682
|
);
|
|
8282
8683
|
var LINE = "h-11 rounded-full px-4";
|
|
@@ -8308,8 +8709,8 @@ function ContactField({
|
|
|
8308
8709
|
event.preventDefault();
|
|
8309
8710
|
onSubmit?.();
|
|
8310
8711
|
}
|
|
8311
|
-
return /* @__PURE__ */
|
|
8312
|
-
/* @__PURE__ */
|
|
8712
|
+
return /* @__PURE__ */ jsxs25("div", { className: "flex flex-col", children: [
|
|
8713
|
+
/* @__PURE__ */ jsxs25(
|
|
8313
8714
|
"label",
|
|
8314
8715
|
{
|
|
8315
8716
|
htmlFor: id,
|
|
@@ -8331,8 +8732,8 @@ function ContactField({
|
|
|
8331
8732
|
onKeyDown: handleKeyDown,
|
|
8332
8733
|
className: cn(SHELL, PARAGRAPH)
|
|
8333
8734
|
}
|
|
8334
|
-
) : field.type === "select" ? /* @__PURE__ */
|
|
8335
|
-
/* @__PURE__ */
|
|
8735
|
+
) : field.type === "select" ? /* @__PURE__ */ jsxs25("div", { className: "relative", children: [
|
|
8736
|
+
/* @__PURE__ */ jsxs25(
|
|
8336
8737
|
"select",
|
|
8337
8738
|
{
|
|
8338
8739
|
...control,
|
|
@@ -8498,8 +8899,8 @@ function fieldComplaints(fields) {
|
|
|
8498
8899
|
}
|
|
8499
8900
|
|
|
8500
8901
|
// ../../apps/web/src/components/support-widget/contact/sent-mark.tsx
|
|
8501
|
-
import { useLayoutEffect as
|
|
8502
|
-
import { jsx as jsx47, jsxs as
|
|
8902
|
+
import { useLayoutEffect as useLayoutEffect12, useRef as useRef23 } from "react";
|
|
8903
|
+
import { jsx as jsx47, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
8503
8904
|
var EASE_OUT = "cubic-bezier(0.22, 1, 0.36, 1)";
|
|
8504
8905
|
var TRAVEL_MS = 550;
|
|
8505
8906
|
var DRAW_LEAD_MS = 150;
|
|
@@ -8512,11 +8913,11 @@ function SentMark({
|
|
|
8512
8913
|
from = null,
|
|
8513
8914
|
className
|
|
8514
8915
|
}) {
|
|
8515
|
-
const frame =
|
|
8516
|
-
const square =
|
|
8517
|
-
const tick =
|
|
8518
|
-
const ring =
|
|
8519
|
-
|
|
8916
|
+
const frame = useRef23(null);
|
|
8917
|
+
const square = useRef23(null);
|
|
8918
|
+
const tick = useRef23(null);
|
|
8919
|
+
const ring = useRef23(null);
|
|
8920
|
+
useLayoutEffect12(() => {
|
|
8520
8921
|
const rest = frame.current;
|
|
8521
8922
|
const box = square.current;
|
|
8522
8923
|
const path = tick.current;
|
|
@@ -8574,7 +8975,7 @@ function SentMark({
|
|
|
8574
8975
|
for (const animation of animations) animation.cancel();
|
|
8575
8976
|
};
|
|
8576
8977
|
}, [from]);
|
|
8577
|
-
return /* @__PURE__ */
|
|
8978
|
+
return /* @__PURE__ */ jsxs26(
|
|
8578
8979
|
"span",
|
|
8579
8980
|
{
|
|
8580
8981
|
ref: frame,
|
|
@@ -8618,7 +9019,7 @@ function SentMark({
|
|
|
8618
9019
|
}
|
|
8619
9020
|
|
|
8620
9021
|
// ../../apps/web/src/components/support-widget/contact/contact-form.tsx
|
|
8621
|
-
import { jsx as jsx48, jsxs as
|
|
9022
|
+
import { jsx as jsx48, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
8622
9023
|
var EMAIL_PATTERN2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
8623
9024
|
var FORM_SWAP = "transition-[opacity,translate] duration-250 ease-out-quint motion-reduce:transition-none";
|
|
8624
9025
|
var THANKS_SWAP = "transition-opacity ease-out motion-reduce:transition-none";
|
|
@@ -8661,10 +9062,10 @@ function ContactForm({
|
|
|
8661
9062
|
showBadge = true,
|
|
8662
9063
|
className
|
|
8663
9064
|
}) {
|
|
8664
|
-
const fields =
|
|
9065
|
+
const fields = useMemo4(() => resolveFields(hostFields), [hostFields]);
|
|
8665
9066
|
const prefix = useId();
|
|
8666
|
-
const formRef =
|
|
8667
|
-
const sendRef =
|
|
9067
|
+
const formRef = useRef24(null);
|
|
9068
|
+
const sendRef = useRef24(null);
|
|
8668
9069
|
const [values, setValues] = useState29(
|
|
8669
9070
|
() => startingValues(fields, initialValues)
|
|
8670
9071
|
);
|
|
@@ -8685,7 +9086,7 @@ function ContactForm({
|
|
|
8685
9086
|
});
|
|
8686
9087
|
}
|
|
8687
9088
|
const [focusRequest, setFocusRequest] = useState29(0);
|
|
8688
|
-
|
|
9089
|
+
useEffect28(() => {
|
|
8689
9090
|
if (focusRequest === 0) return;
|
|
8690
9091
|
formRef.current?.querySelector('[aria-invalid="true"]')?.focus({ preventScroll: false });
|
|
8691
9092
|
}, [focusRequest]);
|
|
@@ -8707,7 +9108,7 @@ function ContactForm({
|
|
|
8707
9108
|
}
|
|
8708
9109
|
if (Object.keys(found).length > 0) {
|
|
8709
9110
|
setErrors(found);
|
|
8710
|
-
setFocusRequest((
|
|
9111
|
+
setFocusRequest((count2) => count2 + 1);
|
|
8711
9112
|
return;
|
|
8712
9113
|
}
|
|
8713
9114
|
const message = composeMessage(fields, values);
|
|
@@ -8736,22 +9137,22 @@ function ContactForm({
|
|
|
8736
9137
|
event.preventDefault();
|
|
8737
9138
|
void send();
|
|
8738
9139
|
}
|
|
8739
|
-
return /* @__PURE__ */
|
|
9140
|
+
return /* @__PURE__ */ jsxs27(
|
|
8740
9141
|
"section",
|
|
8741
9142
|
{
|
|
8742
9143
|
"aria-label": title,
|
|
8743
9144
|
"data-median-widget": "",
|
|
8744
9145
|
className: cn(
|
|
8745
|
-
|
|
9146
|
+
`flex w-full flex-col overflow-hidden ${WIDGET_CORNER} border bg-card p-5 text-card-foreground [--radius:0.625rem]`,
|
|
8746
9147
|
className
|
|
8747
9148
|
),
|
|
8748
9149
|
children: [
|
|
8749
|
-
/* @__PURE__ */
|
|
9150
|
+
/* @__PURE__ */ jsxs27("header", { className: "flex flex-col gap-0.5 pb-4", children: [
|
|
8750
9151
|
/* @__PURE__ */ jsx48("h2", { className: "text-lg font-semibold tracking-tight", children: title }),
|
|
8751
9152
|
/* @__PURE__ */ jsx48("p", { className: "text-sm text-muted-foreground", children: description })
|
|
8752
9153
|
] }),
|
|
8753
|
-
/* @__PURE__ */
|
|
8754
|
-
/* @__PURE__ */
|
|
9154
|
+
/* @__PURE__ */ jsxs27("div", { className: "grid", children: [
|
|
9155
|
+
/* @__PURE__ */ jsxs27(
|
|
8755
9156
|
"form",
|
|
8756
9157
|
{
|
|
8757
9158
|
ref: formRef,
|
|
@@ -8778,9 +9179,9 @@ function ContactForm({
|
|
|
8778
9179
|
field.name
|
|
8779
9180
|
)),
|
|
8780
9181
|
notice && /* @__PURE__ */ jsx48("p", { className: "animate-in px-1 text-sm text-destructive fade-in duration-150", children: notice }),
|
|
8781
|
-
/* @__PURE__ */
|
|
9182
|
+
/* @__PURE__ */ jsxs27("div", { className: "flex min-h-10 flex-wrap items-center gap-3 pt-1", children: [
|
|
8782
9183
|
showBadge && /* @__PURE__ */ jsx48(PoweredByMedian, { className: "justify-start" }),
|
|
8783
|
-
/* @__PURE__ */
|
|
9184
|
+
/* @__PURE__ */ jsxs27(
|
|
8784
9185
|
WidgetButton,
|
|
8785
9186
|
{
|
|
8786
9187
|
ref: sendRef,
|
|
@@ -8832,15 +9233,15 @@ function ContactForm({
|
|
|
8832
9233
|
THANKS_SWAP,
|
|
8833
9234
|
isSent ? "duration-0" : "pointer-events-none opacity-0 duration-200"
|
|
8834
9235
|
),
|
|
8835
|
-
children: sent !== null && /* @__PURE__ */
|
|
9236
|
+
children: sent !== null && /* @__PURE__ */ jsxs27("div", { className: "contents", children: [
|
|
8836
9237
|
/* @__PURE__ */ jsx48(SentMark, { from: sent.from }),
|
|
8837
|
-
/* @__PURE__ */
|
|
9238
|
+
/* @__PURE__ */ jsxs27(
|
|
8838
9239
|
"div",
|
|
8839
9240
|
{
|
|
8840
9241
|
className: cn("flex max-w-72 flex-col gap-1", ARRIVES2, "delay-[400ms]"),
|
|
8841
9242
|
children: [
|
|
8842
9243
|
/* @__PURE__ */ jsx48("p", { className: "text-xl font-semibold tracking-tight", children: "Message sent" }),
|
|
8843
|
-
/* @__PURE__ */
|
|
9244
|
+
/* @__PURE__ */ jsxs27("p", { className: "text-base text-balance text-muted-foreground", children: [
|
|
8844
9245
|
"Replies go to ",
|
|
8845
9246
|
sent.email,
|
|
8846
9247
|
"."
|
|
@@ -8848,7 +9249,7 @@ function ContactForm({
|
|
|
8848
9249
|
]
|
|
8849
9250
|
}
|
|
8850
9251
|
),
|
|
8851
|
-
/* @__PURE__ */
|
|
9252
|
+
/* @__PURE__ */ jsxs27(
|
|
8852
9253
|
"div",
|
|
8853
9254
|
{
|
|
8854
9255
|
className: cn(
|
|
@@ -8882,10 +9283,10 @@ function ContactForm({
|
|
|
8882
9283
|
}
|
|
8883
9284
|
|
|
8884
9285
|
// ../../apps/web/src/components/support-widget/sdk/use-median-contact.ts
|
|
8885
|
-
import { useCallback as useCallback16, useMemo as
|
|
9286
|
+
import { useCallback as useCallback16, useMemo as useMemo5, useState as useState30, useSyncExternalStore as useSyncExternalStore15 } from "react";
|
|
8886
9287
|
|
|
8887
9288
|
// ../../apps/web/src/components/support-widget/sdk/contact.ts
|
|
8888
|
-
import { ConvexHttpClient as
|
|
9289
|
+
import { ConvexHttpClient as ConvexHttpClient3 } from "convex/browser";
|
|
8889
9290
|
var client2 = null;
|
|
8890
9291
|
async function deliverContact(options, message) {
|
|
8891
9292
|
const { apiKey, sessionId, user, telemetry = true } = options;
|
|
@@ -8898,11 +9299,11 @@ async function deliverContact(options, message) {
|
|
|
8898
9299
|
"The Median SDK was built without a deployment URL. Set NEXT_PUBLIC_CONVEX_URL."
|
|
8899
9300
|
);
|
|
8900
9301
|
}
|
|
8901
|
-
client2 ??= new
|
|
9302
|
+
client2 ??= new ConvexHttpClient3(MEDIAN_DEPLOYMENT_URL);
|
|
8902
9303
|
const context = telemetry ? collectContext() : void 0;
|
|
8903
9304
|
const page = telemetry ? collectPage() : void 0;
|
|
8904
9305
|
const { facts, claim } = splitIdentity(user ?? null);
|
|
8905
|
-
await client2.mutation(api.widget.
|
|
9306
|
+
await client2.mutation(api.widget.sendV2, {
|
|
8906
9307
|
apiKey,
|
|
8907
9308
|
sessionId,
|
|
8908
9309
|
body: composeBody(message),
|
|
@@ -8914,7 +9315,7 @@ async function deliverContact(options, message) {
|
|
|
8914
9315
|
...page ? { page } : {},
|
|
8915
9316
|
...options.diagnostics ? { diagnostics: options.diagnostics } : {},
|
|
8916
9317
|
...custom ? { customData: custom } : {}
|
|
8917
|
-
});
|
|
9318
|
+
}).then(unwrapMutationResult);
|
|
8918
9319
|
} catch (caught) {
|
|
8919
9320
|
if (custom) restoreCustomData(custom);
|
|
8920
9321
|
console.error("Median: sending a contact message failed", caught);
|
|
@@ -8938,12 +9339,16 @@ function useMedianContact(options) {
|
|
|
8938
9339
|
const resolved = useMedianIdentity(identity);
|
|
8939
9340
|
useMissingCredentials("useMedianContact", apiKey, identity);
|
|
8940
9341
|
const key = apiKey ?? resolved.apiKey;
|
|
9342
|
+
const showBranding = useMedianBranding(key);
|
|
8941
9343
|
useApiKeyShapeWarning("useMedianContact", key);
|
|
8942
9344
|
const person = user ?? resolved.user;
|
|
8943
9345
|
useRememberInstall(key, person);
|
|
8944
|
-
const sessionId =
|
|
9346
|
+
const sessionId = useSyncExternalStore15(
|
|
8945
9347
|
subscribeSession,
|
|
8946
|
-
useCallback16(
|
|
9348
|
+
useCallback16(
|
|
9349
|
+
() => key === void 0 ? null : getOrCreateSessionId(key),
|
|
9350
|
+
[key]
|
|
9351
|
+
),
|
|
8947
9352
|
() => null
|
|
8948
9353
|
);
|
|
8949
9354
|
const takeDiagnostics = useDiagnostics(diagnostics, appState);
|
|
@@ -8980,13 +9385,14 @@ function useMedianContact(options) {
|
|
|
8980
9385
|
},
|
|
8981
9386
|
[key, sessionId, person, telemetry, takeDiagnostics]
|
|
8982
9387
|
);
|
|
8983
|
-
const known =
|
|
9388
|
+
const known = useMemo5(() => {
|
|
8984
9389
|
const email = person?.email || knownEmail || void 0;
|
|
8985
9390
|
if (person === void 0 && email === void 0) return void 0;
|
|
8986
9391
|
return { ...person, ...email ? { email } : {} };
|
|
8987
9392
|
}, [person, knownEmail]);
|
|
8988
9393
|
return {
|
|
8989
9394
|
send,
|
|
9395
|
+
showBranding,
|
|
8990
9396
|
isSending,
|
|
8991
9397
|
error,
|
|
8992
9398
|
isReady: key !== void 0 && sessionId !== null,
|
|
@@ -9001,10 +9407,12 @@ function MedianContactForm(props) {
|
|
|
9001
9407
|
}
|
|
9002
9408
|
function useFieldComplaints(fields) {
|
|
9003
9409
|
const key = fields === void 0 ? null : JSON.stringify(fields);
|
|
9004
|
-
|
|
9410
|
+
useEffect29(() => {
|
|
9005
9411
|
if (key === null) return;
|
|
9006
9412
|
for (const complaint of fieldComplaints(JSON.parse(key))) {
|
|
9007
|
-
console.error(
|
|
9413
|
+
console.error(
|
|
9414
|
+
`Median: in the fields passed to <MedianContactForm>, ${complaint}`
|
|
9415
|
+
);
|
|
9008
9416
|
}
|
|
9009
9417
|
}, [key]);
|
|
9010
9418
|
}
|
|
@@ -9019,7 +9427,7 @@ function ConnectedContactForm({
|
|
|
9019
9427
|
useFieldComplaints(fields);
|
|
9020
9428
|
const knownEmail = contact.user?.email || void 0;
|
|
9021
9429
|
const knownName = contact.user?.name || void 0;
|
|
9022
|
-
const initialValues =
|
|
9430
|
+
const initialValues = useMemo6(
|
|
9023
9431
|
() => ({
|
|
9024
9432
|
...knownEmail ? { email: knownEmail } : {},
|
|
9025
9433
|
...knownName ? { name: knownName } : {}
|
|
@@ -9029,6 +9437,7 @@ function ConnectedContactForm({
|
|
|
9029
9437
|
return /* @__PURE__ */ jsx49(
|
|
9030
9438
|
ContactForm,
|
|
9031
9439
|
{
|
|
9440
|
+
showBadge: contact.showBranding,
|
|
9032
9441
|
fields,
|
|
9033
9442
|
onSubmit: async (message) => {
|
|
9034
9443
|
await contact.send(message);
|