@mediansh/widget 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +16 -0
- package/dist/index.js +844 -545
- package/dist/index.js.map +1 -1
- package/dist/{message-markdown-5ZZ6COCL.js → message-markdown-LOE74LBE.js} +4 -2
- package/dist/{message-markdown-5ZZ6COCL.js.map → message-markdown-LOE74LBE.js.map} +1 -1
- package/dist/widget.css +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25,11 +25,11 @@ var SNOOZE_MAX_MS = 365 * 24 * 60 * 6e4;
|
|
|
25
25
|
|
|
26
26
|
// ../../apps/web/src/components/support-widget/sdk/median-support.tsx
|
|
27
27
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
|
28
|
-
import { useEffect as useEffect20, useState as
|
|
28
|
+
import { useEffect as useEffect20, useState as useState21 } from "react";
|
|
29
29
|
|
|
30
30
|
// ../../apps/web/src/components/support-widget/markdown-chunk.tsx
|
|
31
31
|
import { lazy, useSyncExternalStore } from "react";
|
|
32
|
-
var load = () => import("./message-markdown-
|
|
32
|
+
var load = () => import("./message-markdown-LOE74LBE.js");
|
|
33
33
|
var MessageMarkdown = lazy(async () => ({
|
|
34
34
|
default: (await load()).MessageMarkdown
|
|
35
35
|
}));
|
|
@@ -78,16 +78,16 @@ function useMarkdownReady() {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// ../../apps/web/src/components/support-widget/widget-launcher.tsx
|
|
81
|
-
import { useCallback as useCallback7, useEffect as useEffect10, useRef as useRef11, useState as
|
|
81
|
+
import { useCallback as useCallback7, useEffect as useEffect10, useRef as useRef11, useState as useState13 } from "react";
|
|
82
82
|
|
|
83
83
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/lib/SSRBase.es.js
|
|
84
84
|
import * as e from "react";
|
|
85
85
|
var w = e.forwardRef((l5, s4) => {
|
|
86
86
|
const {
|
|
87
|
-
alt:
|
|
88
|
-
color:
|
|
89
|
-
size:
|
|
90
|
-
weight:
|
|
87
|
+
alt: r31,
|
|
88
|
+
color: a27 = "currentColor",
|
|
89
|
+
size: t9 = "1em",
|
|
90
|
+
weight: o41 = "regular",
|
|
91
91
|
mirrored: i3 = false,
|
|
92
92
|
children: n,
|
|
93
93
|
weights: c6,
|
|
@@ -98,16 +98,16 @@ var w = e.forwardRef((l5, s4) => {
|
|
|
98
98
|
{
|
|
99
99
|
ref: s4,
|
|
100
100
|
xmlns: "http://www.w3.org/2000/svg",
|
|
101
|
-
width:
|
|
102
|
-
height:
|
|
103
|
-
fill:
|
|
101
|
+
width: t9,
|
|
102
|
+
height: t9,
|
|
103
|
+
fill: a27,
|
|
104
104
|
viewBox: "0 0 256 256",
|
|
105
105
|
transform: i3 ? "scale(-1, 1)" : void 0,
|
|
106
106
|
...m5
|
|
107
107
|
},
|
|
108
|
-
!!
|
|
108
|
+
!!r31 && /* @__PURE__ */ e.createElement("title", null, r31),
|
|
109
109
|
n,
|
|
110
|
-
c6.get(
|
|
110
|
+
c6.get(o41)
|
|
111
111
|
);
|
|
112
112
|
});
|
|
113
113
|
w.displayName = "SSRBase";
|
|
@@ -145,7 +145,7 @@ var a = /* @__PURE__ */ new Map([
|
|
|
145
145
|
]);
|
|
146
146
|
|
|
147
147
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowDown.es.js
|
|
148
|
-
var r = o.forwardRef((e53,
|
|
148
|
+
var r = o.forwardRef((e53, t9) => /* @__PURE__ */ o.createElement(w, { ref: t9, ...e53, weights: a }));
|
|
149
149
|
r.displayName = "ArrowDownIcon";
|
|
150
150
|
|
|
151
151
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowUp.es.js
|
|
@@ -181,7 +181,7 @@ var a2 = /* @__PURE__ */ new Map([
|
|
|
181
181
|
]);
|
|
182
182
|
|
|
183
183
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowUp.es.js
|
|
184
|
-
var o2 = r2.forwardRef((e53,
|
|
184
|
+
var o2 = r2.forwardRef((e53, t9) => /* @__PURE__ */ r2.createElement(w, { ref: t9, ...e53, weights: a2 }));
|
|
185
185
|
o2.displayName = "ArrowUpIcon";
|
|
186
186
|
|
|
187
187
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsClockwise.es.js
|
|
@@ -295,7 +295,7 @@ var e6 = /* @__PURE__ */ new Map([
|
|
|
295
295
|
]);
|
|
296
296
|
|
|
297
297
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsOut.es.js
|
|
298
|
-
var o5 = r5.forwardRef((
|
|
298
|
+
var o5 = r5.forwardRef((t9, e53) => /* @__PURE__ */ r5.createElement(w, { ref: e53, ...t9, weights: e6 }));
|
|
299
299
|
o5.displayName = "ArrowsOutIcon";
|
|
300
300
|
|
|
301
301
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Bug.es.js
|
|
@@ -331,7 +331,7 @@ var e7 = /* @__PURE__ */ new Map([
|
|
|
331
331
|
]);
|
|
332
332
|
|
|
333
333
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Bug.es.js
|
|
334
|
-
var e8 = o6.forwardRef((
|
|
334
|
+
var e8 = o6.forwardRef((r31, t9) => /* @__PURE__ */ o6.createElement(w, { ref: t9, ...r31, weights: e7 }));
|
|
335
335
|
e8.displayName = "BugIcon";
|
|
336
336
|
|
|
337
337
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/CaretRight.es.js
|
|
@@ -367,7 +367,7 @@ var t = /* @__PURE__ */ new Map([
|
|
|
367
367
|
]);
|
|
368
368
|
|
|
369
369
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/CaretRight.es.js
|
|
370
|
-
var e10 = t2.forwardRef((
|
|
370
|
+
var e10 = t2.forwardRef((r31, o41) => /* @__PURE__ */ t2.createElement(w, { ref: o41, ...r31, weights: t }));
|
|
371
371
|
e10.displayName = "CaretRightIcon";
|
|
372
372
|
|
|
373
373
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ChatCircleDots.es.js
|
|
@@ -409,7 +409,7 @@ var e11 = /* @__PURE__ */ new Map([
|
|
|
409
409
|
]);
|
|
410
410
|
|
|
411
411
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ChatCircleDots.es.js
|
|
412
|
-
var o7 = t3.forwardRef((e53,
|
|
412
|
+
var o7 = t3.forwardRef((e53, r31) => /* @__PURE__ */ t3.createElement(w, { ref: r31, ...e53, weights: e11 }));
|
|
413
413
|
o7.displayName = "ChatCircleDotsIcon";
|
|
414
414
|
|
|
415
415
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Check.es.js
|
|
@@ -451,7 +451,7 @@ var a8 = /* @__PURE__ */ new Map([
|
|
|
451
451
|
]);
|
|
452
452
|
|
|
453
453
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Check.es.js
|
|
454
|
-
var o8 = e13.forwardRef((
|
|
454
|
+
var o8 = e13.forwardRef((r31, t9) => /* @__PURE__ */ e13.createElement(w, { ref: t9, ...r31, weights: a8 }));
|
|
455
455
|
o8.displayName = "CheckIcon";
|
|
456
456
|
|
|
457
457
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/EnvelopeSimple.es.js
|
|
@@ -523,7 +523,7 @@ var a10 = /* @__PURE__ */ new Map([
|
|
|
523
523
|
]);
|
|
524
524
|
|
|
525
525
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/File.es.js
|
|
526
|
-
var o10 = e17.forwardRef((
|
|
526
|
+
var o10 = e17.forwardRef((r31, t9) => /* @__PURE__ */ e17.createElement(w, { ref: t9, ...r31, weights: a10 }));
|
|
527
527
|
o10.displayName = "FileIcon";
|
|
528
528
|
|
|
529
529
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ImageSquare.es.js
|
|
@@ -565,7 +565,7 @@ var e18 = /* @__PURE__ */ new Map([
|
|
|
565
565
|
]);
|
|
566
566
|
|
|
567
567
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ImageSquare.es.js
|
|
568
|
-
var a12 = e19.forwardRef((
|
|
568
|
+
var a12 = e19.forwardRef((r31, o41) => /* @__PURE__ */ e19.createElement(w, { ref: o41, ...r31, weights: e18 }));
|
|
569
569
|
a12.displayName = "ImageSquareIcon";
|
|
570
570
|
|
|
571
571
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Lightbulb.es.js
|
|
@@ -607,7 +607,7 @@ var e20 = /* @__PURE__ */ new Map([
|
|
|
607
607
|
]);
|
|
608
608
|
|
|
609
609
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Lightbulb.es.js
|
|
610
|
-
var o11 = t4.forwardRef((e53,
|
|
610
|
+
var o11 = t4.forwardRef((e53, r31) => /* @__PURE__ */ t4.createElement(w, { ref: r31, ...e53, weights: e20 }));
|
|
611
611
|
o11.displayName = "LightbulbIcon";
|
|
612
612
|
|
|
613
613
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/LockSimple.es.js
|
|
@@ -649,7 +649,7 @@ var e21 = /* @__PURE__ */ new Map([
|
|
|
649
649
|
]);
|
|
650
650
|
|
|
651
651
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/LockSimple.es.js
|
|
652
|
-
var e22 = o12.forwardRef((m5,
|
|
652
|
+
var e22 = o12.forwardRef((m5, r31) => /* @__PURE__ */ o12.createElement(w, { ref: r31, ...m5, weights: e21 }));
|
|
653
653
|
e22.displayName = "LockSimpleIcon";
|
|
654
654
|
|
|
655
655
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Play.es.js
|
|
@@ -691,7 +691,7 @@ var a15 = /* @__PURE__ */ new Map([
|
|
|
691
691
|
]);
|
|
692
692
|
|
|
693
693
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Play.es.js
|
|
694
|
-
var a16 = o13.forwardRef((e53,
|
|
694
|
+
var a16 = o13.forwardRef((e53, r31) => /* @__PURE__ */ o13.createElement(w, { ref: r31, ...e53, weights: a15 }));
|
|
695
695
|
a16.displayName = "PlayIcon";
|
|
696
696
|
|
|
697
697
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Plus.es.js
|
|
@@ -733,7 +733,7 @@ var a17 = /* @__PURE__ */ new Map([
|
|
|
733
733
|
]);
|
|
734
734
|
|
|
735
735
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Plus.es.js
|
|
736
|
-
var e25 = o14.forwardRef((
|
|
736
|
+
var e25 = o14.forwardRef((r31, s4) => /* @__PURE__ */ o14.createElement(w, { ref: s4, ...r31, weights: a17 }));
|
|
737
737
|
e25.displayName = "PlusIcon";
|
|
738
738
|
|
|
739
739
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Sparkle.es.js
|
|
@@ -775,7 +775,7 @@ var l = /* @__PURE__ */ new Map([
|
|
|
775
775
|
]);
|
|
776
776
|
|
|
777
777
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Sparkle.es.js
|
|
778
|
-
var r6 = e26.forwardRef((
|
|
778
|
+
var r6 = e26.forwardRef((o41, a27) => /* @__PURE__ */ e26.createElement(w, { ref: a27, ...o41, weights: l }));
|
|
779
779
|
r6.displayName = "SparkleIcon";
|
|
780
780
|
|
|
781
781
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Star.es.js
|
|
@@ -817,7 +817,7 @@ var l2 = /* @__PURE__ */ new Map([
|
|
|
817
817
|
]);
|
|
818
818
|
|
|
819
819
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Star.es.js
|
|
820
|
-
var t5 = r7.forwardRef((
|
|
820
|
+
var t5 = r7.forwardRef((o41, a27) => /* @__PURE__ */ r7.createElement(w, { ref: a27, ...o41, weights: l2 }));
|
|
821
821
|
t5.displayName = "StarIcon";
|
|
822
822
|
|
|
823
823
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/UserCircle.es.js
|
|
@@ -859,7 +859,7 @@ var a20 = /* @__PURE__ */ new Map([
|
|
|
859
859
|
]);
|
|
860
860
|
|
|
861
861
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/UserCircle.es.js
|
|
862
|
-
var r8 = e28.forwardRef((
|
|
862
|
+
var r8 = e28.forwardRef((o41, s4) => /* @__PURE__ */ e28.createElement(w, { ref: s4, ...o41, weights: a20 }));
|
|
863
863
|
r8.displayName = "UserCircleIcon";
|
|
864
864
|
|
|
865
865
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/WarningCircle.es.js
|
|
@@ -895,7 +895,7 @@ var a21 = /* @__PURE__ */ new Map([
|
|
|
895
895
|
]);
|
|
896
896
|
|
|
897
897
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/WarningCircle.es.js
|
|
898
|
-
var e30 = r9.forwardRef((
|
|
898
|
+
var e30 = r9.forwardRef((o41, a27) => /* @__PURE__ */ r9.createElement(w, { ref: a27, ...o41, weights: a21 }));
|
|
899
899
|
e30.displayName = "WarningCircleIcon";
|
|
900
900
|
|
|
901
901
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/X.es.js
|
|
@@ -937,7 +937,7 @@ var a22 = /* @__PURE__ */ new Map([
|
|
|
937
937
|
]);
|
|
938
938
|
|
|
939
939
|
// ../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/X.es.js
|
|
940
|
-
var e32 = o15.forwardRef((
|
|
940
|
+
var e32 = o15.forwardRef((r31, t9) => /* @__PURE__ */ o15.createElement(w, { ref: t9, ...r31, weights: a22 }));
|
|
941
941
|
e32.displayName = "XIcon";
|
|
942
942
|
|
|
943
943
|
// ../../apps/web/src/components/icons.tsx
|
|
@@ -1060,57 +1060,57 @@ import * as React3 from "react";
|
|
|
1060
1060
|
|
|
1061
1061
|
// ../../node_modules/.bun/@shadcn+react@0.3.0+03aa47d54245a271/node_modules/@shadcn/react/dist/chunk-HBS6WEDP.js
|
|
1062
1062
|
import * as i2 from "react";
|
|
1063
|
-
function S({ defaultTagName:
|
|
1064
|
-
let
|
|
1065
|
-
if (!
|
|
1066
|
-
if (typeof
|
|
1067
|
-
if (!i2.isValidElement(
|
|
1068
|
-
let s4 =
|
|
1069
|
-
return i2.cloneElement(
|
|
1070
|
-
}
|
|
1071
|
-
function d(...
|
|
1072
|
-
let
|
|
1073
|
-
for (let
|
|
1074
|
-
if (!
|
|
1075
|
-
let n =
|
|
1063
|
+
function S({ defaultTagName: a27, props: r31, render: t9, state: n = {}, stateAttributesMapping: e53 }) {
|
|
1064
|
+
let o41 = d(R(n, e53), r31);
|
|
1065
|
+
if (!t9) return i2.createElement(a27, o41);
|
|
1066
|
+
if (typeof t9 == "function") return t9(o41, n);
|
|
1067
|
+
if (!i2.isValidElement(t9)) return null;
|
|
1068
|
+
let s4 = t9.props, u = { ...d(o41, s4), ref: f8(o41.ref, s4.ref) };
|
|
1069
|
+
return i2.cloneElement(t9, u);
|
|
1070
|
+
}
|
|
1071
|
+
function d(...a27) {
|
|
1072
|
+
let r31 = {};
|
|
1073
|
+
for (let t9 of a27) {
|
|
1074
|
+
if (!t9) continue;
|
|
1075
|
+
let n = t9;
|
|
1076
1076
|
for (let e53 of Object.keys(n)) {
|
|
1077
|
-
let
|
|
1078
|
-
if (
|
|
1079
|
-
let s4 =
|
|
1080
|
-
e53 === "className" ?
|
|
1077
|
+
let o41 = n[e53];
|
|
1078
|
+
if (o41 === void 0) continue;
|
|
1079
|
+
let s4 = r31[e53];
|
|
1080
|
+
e53 === "className" ? r31[e53] = [s4, o41].filter(Boolean).join(" ") : e53 === "style" ? r31[e53] = { ...s4, ...o41 } : e53 === "ref" ? r31[e53] = f8(s4, o41) : l4(e53) && typeof s4 == "function" && typeof o41 == "function" ? r31[e53] = p2(o41, s4) : r31[e53] = o41;
|
|
1081
1081
|
}
|
|
1082
1082
|
}
|
|
1083
|
-
return
|
|
1084
|
-
}
|
|
1085
|
-
function R(
|
|
1086
|
-
let
|
|
1087
|
-
for (let n of Object.keys(
|
|
1088
|
-
let e53 =
|
|
1089
|
-
if (
|
|
1090
|
-
Object.assign(
|
|
1083
|
+
return r31;
|
|
1084
|
+
}
|
|
1085
|
+
function R(a27, r31) {
|
|
1086
|
+
let t9 = {};
|
|
1087
|
+
for (let n of Object.keys(a27)) {
|
|
1088
|
+
let e53 = a27[n], o41 = r31?.[n]?.(e53);
|
|
1089
|
+
if (o41) {
|
|
1090
|
+
Object.assign(t9, o41);
|
|
1091
1091
|
continue;
|
|
1092
1092
|
}
|
|
1093
1093
|
if (n === "slot") {
|
|
1094
|
-
|
|
1094
|
+
t9["data-slot"] = e53;
|
|
1095
1095
|
continue;
|
|
1096
1096
|
}
|
|
1097
1097
|
let s4 = `data-${String(n).replace(/[A-Z]/g, (c6) => `-${c6.toLowerCase()}`)}`;
|
|
1098
|
-
typeof e53 == "boolean" ?
|
|
1098
|
+
typeof e53 == "boolean" ? t9[s4] = e53 ? "" : void 0 : e53 != null && (t9[s4] = String(e53));
|
|
1099
1099
|
}
|
|
1100
|
-
return
|
|
1100
|
+
return t9;
|
|
1101
1101
|
}
|
|
1102
|
-
function p2(
|
|
1102
|
+
function p2(a27, r31) {
|
|
1103
1103
|
return function(n) {
|
|
1104
|
-
|
|
1104
|
+
a27(n), n.defaultPrevented || r31(n);
|
|
1105
1105
|
};
|
|
1106
1106
|
}
|
|
1107
|
-
function l4(
|
|
1108
|
-
return /^on[A-Z]/.test(
|
|
1107
|
+
function l4(a27) {
|
|
1108
|
+
return /^on[A-Z]/.test(a27);
|
|
1109
1109
|
}
|
|
1110
|
-
function f8(...
|
|
1111
|
-
let
|
|
1112
|
-
if (
|
|
1113
|
-
for (let n of
|
|
1110
|
+
function f8(...a27) {
|
|
1111
|
+
let r31 = a27.filter(Boolean);
|
|
1112
|
+
if (r31.length !== 0) return (t9) => {
|
|
1113
|
+
for (let n of r31) typeof n == "function" ? n(t9) : n && (n.current = t9);
|
|
1114
1114
|
};
|
|
1115
1115
|
}
|
|
1116
1116
|
|
|
@@ -1126,14 +1126,14 @@ var Be = /* @__PURE__ */ new Set(["ArrowDown", "ArrowUp", "End", "Home", "PageDo
|
|
|
1126
1126
|
var ge = { start: false, end: false };
|
|
1127
1127
|
var dt = [];
|
|
1128
1128
|
var Q = { currentAnchorId: null, visibleMessageIds: dt };
|
|
1129
|
-
function De({ content: e53, scrollEdgeThreshold:
|
|
1129
|
+
function De({ content: e53, scrollEdgeThreshold: t9, spacer: r31, viewport: n }) {
|
|
1130
1130
|
if (!n || !e53) return ge;
|
|
1131
|
-
let
|
|
1132
|
-
return { start: n.scrollTop >
|
|
1131
|
+
let o41 = Se({ content: e53, spacer: r31, viewport: n });
|
|
1132
|
+
return { start: n.scrollTop > t9, end: o41 - n.scrollTop - n.clientHeight > t9 };
|
|
1133
1133
|
}
|
|
1134
|
-
function Fe({ content: e53, scrollMargin:
|
|
1135
|
-
if (!e53 || !
|
|
1136
|
-
let S2 =
|
|
1134
|
+
function Fe({ content: e53, scrollMargin: t9, scrollPreviousItemPeek: r31, spacer: n, viewport: o41, visibleMessageIds: i3 }) {
|
|
1135
|
+
if (!e53 || !o41) return Q;
|
|
1136
|
+
let S2 = o41.getBoundingClientRect(), l5 = S2.top + t9 + r31, d2 = typeof IntersectionObserver > "u", E = [], b2 = null;
|
|
1137
1137
|
for (let C of ee(e53, n)) {
|
|
1138
1138
|
let p3 = C.dataset.messageId;
|
|
1139
1139
|
if (!p3) continue;
|
|
@@ -1142,70 +1142,70 @@ function Fe({ content: e53, scrollMargin: t8, scrollPreviousItemPeek: r28, space
|
|
|
1142
1142
|
}
|
|
1143
1143
|
return E.length === 0 && b2 === null ? Q : { currentAnchorId: b2, visibleMessageIds: E };
|
|
1144
1144
|
}
|
|
1145
|
-
function ee(e53,
|
|
1146
|
-
return Array.from(e53.children).filter((
|
|
1145
|
+
function ee(e53, t9) {
|
|
1146
|
+
return Array.from(e53.children).filter((r31) => r31 instanceof HTMLElement && r31 !== t9);
|
|
1147
1147
|
}
|
|
1148
|
-
function je(e53,
|
|
1149
|
-
for (let
|
|
1150
|
-
let n = e53[
|
|
1148
|
+
function je(e53, t9) {
|
|
1149
|
+
for (let r31 = t9; r31 < e53.length; r31++) {
|
|
1150
|
+
let n = e53[r31];
|
|
1151
1151
|
if (n?.dataset.scrollAnchor === "true") return n;
|
|
1152
1152
|
}
|
|
1153
1153
|
return null;
|
|
1154
1154
|
}
|
|
1155
|
-
function Ge(e53,
|
|
1156
|
-
for (let
|
|
1155
|
+
function Ge(e53, t9) {
|
|
1156
|
+
for (let r31 of e53) if (r31.dataset.scrollAnchor === "true" && !t9.has(r31)) return r31;
|
|
1157
1157
|
return null;
|
|
1158
1158
|
}
|
|
1159
|
-
function Ne(e53,
|
|
1160
|
-
let
|
|
1161
|
-
for (let n =
|
|
1159
|
+
function Ne(e53, t9) {
|
|
1160
|
+
let r31 = 0;
|
|
1161
|
+
for (let n = t9; n < e53.length; n++) if (e53[n]?.dataset.scrollAnchor === "true" && (r31 += 1, r31 > 1)) return true;
|
|
1162
1162
|
return false;
|
|
1163
1163
|
}
|
|
1164
1164
|
function Ue(e53) {
|
|
1165
|
-
for (let
|
|
1166
|
-
let
|
|
1167
|
-
if (
|
|
1165
|
+
for (let t9 = e53.length - 1; t9 >= 0; t9--) {
|
|
1166
|
+
let r31 = e53[t9];
|
|
1167
|
+
if (r31?.dataset.scrollAnchor === "true") return r31;
|
|
1168
1168
|
}
|
|
1169
1169
|
return null;
|
|
1170
1170
|
}
|
|
1171
|
-
function Ye({ content: e53, spacer:
|
|
1172
|
-
let n =
|
|
1173
|
-
for (let
|
|
1174
|
-
if (!
|
|
1175
|
-
let i3 =
|
|
1176
|
-
if (i3.bottom > n.top && i3.top < n.bottom) return
|
|
1171
|
+
function Ye({ content: e53, spacer: t9, viewport: r31 }) {
|
|
1172
|
+
let n = r31.getBoundingClientRect();
|
|
1173
|
+
for (let o41 of ee(e53, t9)) {
|
|
1174
|
+
if (!o41.dataset.messageId) continue;
|
|
1175
|
+
let i3 = o41.getBoundingClientRect();
|
|
1176
|
+
if (i3.bottom > n.top && i3.top < n.bottom) return o41;
|
|
1177
1177
|
}
|
|
1178
1178
|
return null;
|
|
1179
1179
|
}
|
|
1180
|
-
function ze({ align: e53, element:
|
|
1181
|
-
let i3 = pe(
|
|
1180
|
+
function ze({ align: e53, element: t9, scrollMargin: r31, spacer: n, viewport: o41 }) {
|
|
1181
|
+
let i3 = pe(t9, o41), S2 = t9.getBoundingClientRect().height, l5 = bt(n);
|
|
1182
1182
|
if (e53 === "center") {
|
|
1183
|
-
let d2 = Math.max(0,
|
|
1184
|
-
return i3 - l5.start - (d2 - S2) / 2 -
|
|
1183
|
+
let d2 = Math.max(0, o41.clientHeight - l5.start - l5.end);
|
|
1184
|
+
return i3 - l5.start - (d2 - S2) / 2 - r31;
|
|
1185
1185
|
}
|
|
1186
|
-
if (e53 === "end") return i3 -
|
|
1186
|
+
if (e53 === "end") return i3 - o41.clientHeight + S2 + l5.end + r31;
|
|
1187
1187
|
if (e53 === "nearest") {
|
|
1188
|
-
let d2 = i3 + S2, E =
|
|
1189
|
-
return i3 >= E && d2 <= b2 ?
|
|
1188
|
+
let d2 = i3 + S2, E = o41.scrollTop + l5.start, b2 = o41.scrollTop + o41.clientHeight - l5.end;
|
|
1189
|
+
return i3 >= E && d2 <= b2 ? o41.scrollTop : i3 < E ? i3 - l5.start - r31 : d2 - o41.clientHeight + l5.end + r31;
|
|
1190
1190
|
}
|
|
1191
|
-
return i3 - l5.start -
|
|
1191
|
+
return i3 - l5.start - r31;
|
|
1192
1192
|
}
|
|
1193
|
-
function pe(e53,
|
|
1194
|
-
let
|
|
1195
|
-
return
|
|
1193
|
+
function pe(e53, t9) {
|
|
1194
|
+
let r31 = e53.getBoundingClientRect(), n = t9.getBoundingClientRect();
|
|
1195
|
+
return r31.top - n.top + t9.scrollTop;
|
|
1196
1196
|
}
|
|
1197
|
-
function te(e53,
|
|
1198
|
-
return e53.getBoundingClientRect().top -
|
|
1197
|
+
function te(e53, t9) {
|
|
1198
|
+
return e53.getBoundingClientRect().top - t9.getBoundingClientRect().top;
|
|
1199
1199
|
}
|
|
1200
|
-
function qe({ content: e53, scrollTop:
|
|
1201
|
-
let
|
|
1202
|
-
return
|
|
1200
|
+
function qe({ content: e53, scrollTop: t9, spacer: r31, viewport: n }) {
|
|
1201
|
+
let o41 = Se({ content: e53, spacer: r31, viewport: n });
|
|
1202
|
+
return t9 + n.clientHeight - o41;
|
|
1203
1203
|
}
|
|
1204
|
-
function Se({ content: e53, spacer:
|
|
1205
|
-
let n = ee(e53,
|
|
1204
|
+
function Se({ content: e53, spacer: t9, viewport: r31 }) {
|
|
1205
|
+
let n = ee(e53, t9), o41 = We(e53), i3 = r31.getBoundingClientRect(), S2 = r31.scrollTop, l5 = o41.start + o41.end;
|
|
1206
1206
|
for (let d2 of n) {
|
|
1207
1207
|
let E = d2.getBoundingClientRect();
|
|
1208
|
-
l5 = Math.max(l5, E.bottom - i3.top + S2 +
|
|
1208
|
+
l5 = Math.max(l5, E.bottom - i3.top + S2 + o41.end);
|
|
1209
1209
|
}
|
|
1210
1210
|
return l5;
|
|
1211
1211
|
}
|
|
@@ -1213,29 +1213,29 @@ function Ke(e53) {
|
|
|
1213
1213
|
return Math.max(0, e53.scrollHeight - e53.clientHeight);
|
|
1214
1214
|
}
|
|
1215
1215
|
function We(e53) {
|
|
1216
|
-
let
|
|
1217
|
-
return { end: Re(
|
|
1216
|
+
let t9 = window.getComputedStyle(e53);
|
|
1217
|
+
return { end: Re(t9.paddingBlockEnd || t9.paddingBottom), start: Re(t9.paddingBlockStart || t9.paddingTop) };
|
|
1218
1218
|
}
|
|
1219
1219
|
function bt(e53) {
|
|
1220
|
-
let
|
|
1221
|
-
return
|
|
1220
|
+
let t9 = e53?.parentElement;
|
|
1221
|
+
return t9 ? We(t9) : { end: 0, start: 0 };
|
|
1222
1222
|
}
|
|
1223
1223
|
function $e(e53) {
|
|
1224
1224
|
if (!e53) return 0;
|
|
1225
|
-
let
|
|
1226
|
-
return Re(
|
|
1225
|
+
let t9 = window.getComputedStyle(e53), r31 = t9.rowGap === "normal" ? t9.gap : t9.rowGap;
|
|
1226
|
+
return Re(r31);
|
|
1227
1227
|
}
|
|
1228
1228
|
function Re(e53) {
|
|
1229
1229
|
if (!e53) return 0;
|
|
1230
|
-
let
|
|
1231
|
-
return Number.isFinite(
|
|
1230
|
+
let t9 = Number.parseFloat(e53);
|
|
1231
|
+
return Number.isFinite(t9) ? t9 : 0;
|
|
1232
1232
|
}
|
|
1233
|
-
function Je({ refs: e53, commitScrollState:
|
|
1234
|
-
let { streamingTurnRef:
|
|
1235
|
-
l5.current !== null && (window.clearTimeout(l5.current), l5.current = null), S2.current !== c6 && (S2.current = c6,
|
|
1236
|
-
l5.current = null, S2.current = false,
|
|
1233
|
+
function Je({ refs: e53, commitScrollState: t9, scheduleStateCommit: r31, scheduleVisibilitySync: n }) {
|
|
1234
|
+
let { streamingTurnRef: o41, 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: _ } = e53, G = g.useCallback((c6) => {
|
|
1235
|
+
l5.current !== null && (window.clearTimeout(l5.current), l5.current = null), S2.current !== c6 && (S2.current = c6, t9()), c6 && (l5.current = window.setTimeout(() => {
|
|
1236
|
+
l5.current = null, S2.current = false, t9();
|
|
1237
1237
|
}, ke));
|
|
1238
|
-
}, [
|
|
1238
|
+
}, [t9]), v = g.useCallback((c6) => {
|
|
1239
1239
|
let f9 = k.current;
|
|
1240
1240
|
if (!f9) return;
|
|
1241
1241
|
let h = Math.max(0, Math.ceil(c6));
|
|
@@ -1245,20 +1245,20 @@ function Je({ refs: e53, commitScrollState: t8, scheduleStateCommit: r28, schedu
|
|
|
1245
1245
|
if (!P) return;
|
|
1246
1246
|
let V = Math.max(0, c6);
|
|
1247
1247
|
if (Math.abs(P.scrollTop - V) <= J) {
|
|
1248
|
-
P.scrollTop = V,
|
|
1248
|
+
P.scrollTop = V, t9();
|
|
1249
1249
|
return;
|
|
1250
1250
|
}
|
|
1251
|
-
h && G(true), P.scrollTo({ top: V, behavior: f9 }),
|
|
1252
|
-
}, [
|
|
1251
|
+
h && G(true), P.scrollTo({ top: V, behavior: f9 }), r31();
|
|
1252
|
+
}, [t9, r31, G]), N = g.useCallback(({ behavior: c6 = "auto" } = {}) => _.current ? (v(0), o41.current = null, p3.current = "free-scrolling", H(0, { behavior: c6 }), n(), true) : false, [n, H, v]), ne = g.useCallback(({ behavior: c6 = "auto" } = {}) => {
|
|
1253
1253
|
let f9 = _.current;
|
|
1254
|
-
return f9 ? (v(0),
|
|
1254
|
+
return f9 ? (v(0), o41.current = null, p3.current = i3.current ? "following-bottom" : "free-scrolling", H(Ke(f9), { autoscrolling: true, behavior: c6 }), n(), true) : false;
|
|
1255
1255
|
}, [n, H, v]), A = g.useCallback((c6, { align: f9 = "start", behavior: h = "auto", scrollMargin: P = y.current } = {}, { keepPreviousPeek: V = false } = {}) => {
|
|
1256
1256
|
let z = d2.current, q = _.current;
|
|
1257
1257
|
if (!z || !q || !z.contains(c6)) return false;
|
|
1258
1258
|
let K = ze({ align: f9, element: c6, scrollMargin: V ? P + u.current : P, spacer: k.current, viewport: q }), se = qe({ content: z, scrollTop: K, spacer: k.current, viewport: q });
|
|
1259
|
-
return v(se), L.current = { element: c6, viewportTop: te(c6, q) }, p3.current = V ? "anchored-to-message" : "settling-jump",
|
|
1259
|
+
return v(se), L.current = { element: c6, viewportTop: te(c6, q) }, p3.current = V ? "anchored-to-message" : "settling-jump", o41.current = V ? c6 : null, H(K, { behavior: h }), n(), true;
|
|
1260
1260
|
}, [n, H, v]), B = g.useCallback(() => {
|
|
1261
|
-
let c6 =
|
|
1261
|
+
let c6 = o41.current;
|
|
1262
1262
|
return !c6 || !c6.isConnected || p3.current !== "anchored-to-message" ? false : A(c6, { align: "start" }, { keepPreviousPeek: true });
|
|
1263
1263
|
}, [A]), D = g.useCallback((c6, f9) => {
|
|
1264
1264
|
let h = C.current.get(c6);
|
|
@@ -1271,52 +1271,52 @@ function Je({ refs: e53, commitScrollState: t8, scheduleStateCommit: r28, schedu
|
|
|
1271
1271
|
return !f9 || !A(f9, c6.options) ? false : (m5.current = null, E.current = true, true);
|
|
1272
1272
|
}, [A]), reanchorToAnchoredMessage: B, scrollToElement: A, scrollToEnd: ne, scrollToMessage: D, scrollToStart: N };
|
|
1273
1273
|
}
|
|
1274
|
-
function Qe(e53,
|
|
1275
|
-
let
|
|
1276
|
-
return { getSnapshot: () =>
|
|
1277
|
-
|
|
1278
|
-
}, subscribe: (
|
|
1274
|
+
function Qe(e53, t9) {
|
|
1275
|
+
let r31 = e53, n = /* @__PURE__ */ new Set();
|
|
1276
|
+
return { getSnapshot: () => r31, hasListeners: () => n.size > 0, setSnapshot: (o41) => {
|
|
1277
|
+
t9(r31, o41) || (r31 = o41, n.forEach((i3) => i3()));
|
|
1278
|
+
}, subscribe: (o41, i3, S2) => {
|
|
1279
1279
|
let l5 = n.size === 0;
|
|
1280
|
-
return n.add(
|
|
1281
|
-
n.delete(
|
|
1280
|
+
return n.add(o41), l5 && i3?.(), () => {
|
|
1281
|
+
n.delete(o41), n.size === 0 && S2?.();
|
|
1282
1282
|
};
|
|
1283
1283
|
} };
|
|
1284
1284
|
}
|
|
1285
|
-
function Xe(e53,
|
|
1286
|
-
return Qe(e53,
|
|
1285
|
+
function Xe(e53, t9) {
|
|
1286
|
+
return Qe(e53, t9);
|
|
1287
1287
|
}
|
|
1288
1288
|
function Ze() {
|
|
1289
1289
|
return Qe(Q, Tt);
|
|
1290
1290
|
}
|
|
1291
|
-
function et(e53,
|
|
1292
|
-
return e53.start ===
|
|
1291
|
+
function et(e53, t9) {
|
|
1292
|
+
return e53.start === t9.start && e53.end === t9.end;
|
|
1293
1293
|
}
|
|
1294
|
-
function Tt(e53,
|
|
1295
|
-
return e53.currentAnchorId !==
|
|
1294
|
+
function Tt(e53, t9) {
|
|
1295
|
+
return e53.currentAnchorId !== t9.currentAnchorId || e53.visibleMessageIds.length !== t9.visibleMessageIds.length ? false : e53.visibleMessageIds.every((r31, n) => r31 === t9.visibleMessageIds[n]);
|
|
1296
1296
|
}
|
|
1297
|
-
function tt({ autoScroll: e53, scrollEdgeThreshold:
|
|
1298
|
-
let
|
|
1299
|
-
return A.current === null && (A.current = Xe(ge, et)), f9.current === null && (f9.current = Ze()),
|
|
1297
|
+
function tt({ autoScroll: e53, scrollEdgeThreshold: t9, scrollMargin: r31, scrollPreviousItemPeek: n }) {
|
|
1298
|
+
let o41 = g.useRef(e53), i3 = g.useRef(false), S2 = g.useRef(null), l5 = g.useRef(false), d2 = g.useRef(t9), E = g.useRef(0), b2 = g.useRef(null), C = g.useRef(0), p3 = g.useRef(e53 ? "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(r31), 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), c6 = g.useRef(null), f9 = g.useRef(null), h = g.useRef(/* @__PURE__ */ new Set()), P = g.useRef(/* @__PURE__ */ new WeakSet());
|
|
1299
|
+
return A.current === null && (A.current = Xe(ge, et)), f9.current === null && (f9.current = Ze()), o41.current = e53, d2.current = t9, _.current = r31, x.current = n, { autoScrollRef: o41, 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: c6, visibilityStore: f9.current, visibleMessageIdsRef: h, handledScrollAnchorsRef: P };
|
|
1300
1300
|
}
|
|
1301
|
-
function rt(e53,
|
|
1302
|
-
return g.useCallback((
|
|
1303
|
-
e53.current =
|
|
1304
|
-
}, [e53,
|
|
1301
|
+
function rt(e53, t9) {
|
|
1302
|
+
return g.useCallback((r31) => {
|
|
1303
|
+
e53.current = r31, r31 && t9();
|
|
1304
|
+
}, [e53, t9]);
|
|
1305
1305
|
}
|
|
1306
|
-
function nt({ autoScroll: e53 = false, defaultScrollPosition:
|
|
1307
|
-
let i3 = tt({ autoScroll: e53, scrollEdgeThreshold:
|
|
1308
|
-
q.current !==
|
|
1306
|
+
function nt({ autoScroll: e53 = false, defaultScrollPosition: t9 = "end", scrollEdgeThreshold: r31 = xe, scrollPreviousItemPeek: n = Ve, scrollMargin: o41 = _e }) {
|
|
1307
|
+
let i3 = tt({ autoScroll: e53, scrollEdgeThreshold: r31, scrollMargin: o41, 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: c6, visibilityFrameRef: f9, visibilityObserverRef: h, visibilityStore: P, visibleMessageIdsRef: V, handledScrollAnchorsRef: z } = i3, q = g.useRef(t9);
|
|
1308
|
+
q.current !== t9 && (q.current = t9, C.current = false);
|
|
1309
1309
|
let K = g.useCallback((s4) => {
|
|
1310
|
-
let
|
|
1311
|
-
for (let W of [
|
|
1310
|
+
let a27 = G.current, T = c6.current, O = [s4.start && "start", s4.end && "end"].filter(Boolean).join(" "), ue = d2.current;
|
|
1311
|
+
for (let W of [a27, T]) W && (O ? W.setAttribute("data-scrollable", O) : W.removeAttribute("data-scrollable"), W.toggleAttribute("data-autoscrolling", ue));
|
|
1312
1312
|
}, []), se = g.useCallback((s4) => {
|
|
1313
|
-
let
|
|
1314
|
-
L.current =
|
|
1313
|
+
let a27 = c6.current?.scrollTop ?? 0, T = a27 < L.current - J;
|
|
1314
|
+
L.current = a27, 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");
|
|
1315
1315
|
}, []), F = g.useCallback(() => {
|
|
1316
1316
|
let s4 = De({ content: b2.current, scrollEdgeThreshold: v.current, spacer: B.current, viewport: c6.current });
|
|
1317
1317
|
se(s4);
|
|
1318
|
-
let
|
|
1319
|
-
K(
|
|
1318
|
+
let a27 = u.current === "following-bottom" ? { ...s4, end: false } : s4;
|
|
1319
|
+
K(a27), U.setSnapshot(a27);
|
|
1320
1320
|
}, [se, U, K]), oe = g.useCallback(() => {
|
|
1321
1321
|
D.current === null && (D.current = window.requestAnimationFrame(() => {
|
|
1322
1322
|
D.current = null, F();
|
|
@@ -1326,54 +1326,54 @@ function nt({ autoScroll: e53 = false, defaultScrollPosition: t8 = "end", scroll
|
|
|
1326
1326
|
f9.current = null, P.hasListeners() && P.setSnapshot(Fe({ content: b2.current, scrollMargin: H.current, scrollPreviousItemPeek: N.current, spacer: B.current, viewport: c6.current, visibleMessageIds: V.current }));
|
|
1327
1327
|
}));
|
|
1328
1328
|
}, [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(() => {
|
|
1329
|
-
let s4 = k.current,
|
|
1330
|
-
if (!s4 || !
|
|
1331
|
-
let O = te(s4.element,
|
|
1332
|
-
return Math.abs(O) <= J ? false : (
|
|
1329
|
+
let s4 = k.current, a27 = c6.current;
|
|
1330
|
+
if (!s4 || !a27 || !s4.element.isConnected) return false;
|
|
1331
|
+
let O = te(s4.element, a27) - s4.viewportTop;
|
|
1332
|
+
return Math.abs(O) <= J ? false : (a27.scrollTop += O, s4.viewportTop = te(s4.element, a27), oe(), w2(), true);
|
|
1333
1333
|
}, [oe, w2]), Z = g.useCallback(() => {
|
|
1334
|
-
let s4 = b2.current,
|
|
1335
|
-
if (!s4 || !
|
|
1334
|
+
let s4 = b2.current, a27 = c6.current;
|
|
1335
|
+
if (!s4 || !a27) {
|
|
1336
1336
|
k.current = null;
|
|
1337
1337
|
return;
|
|
1338
1338
|
}
|
|
1339
|
-
let T = Ye({ content: s4, spacer: B.current, viewport:
|
|
1340
|
-
k.current = T ? { element: T, viewportTop: te(T,
|
|
1339
|
+
let T = Ye({ content: s4, spacer: B.current, viewport: a27 });
|
|
1340
|
+
k.current = T ? { element: T, viewportTop: te(T, a27) } : null;
|
|
1341
1341
|
}, []), be = g.useCallback(() => {
|
|
1342
1342
|
x.current === null && (x.current = window.requestAnimationFrame(() => {
|
|
1343
1343
|
x.current = null, ce() && Z();
|
|
1344
1344
|
}));
|
|
1345
1345
|
}, [Z, ce]), ie = g.useCallback(() => {
|
|
1346
|
-
if (!
|
|
1346
|
+
if (!t9 || C.current || m5.current === 0) return false;
|
|
1347
1347
|
let s4 = false;
|
|
1348
|
-
if (
|
|
1349
|
-
let
|
|
1350
|
-
if (!
|
|
1348
|
+
if (t9 === "last-anchor") {
|
|
1349
|
+
let a27 = b2.current, T = c6.current, O = a27 && T ? Ue(ee(a27, B.current)) : null;
|
|
1350
|
+
if (!a27 || !T || !O) s4 = I2({ behavior: "auto" });
|
|
1351
1351
|
else {
|
|
1352
1352
|
let ue = pe(O, T);
|
|
1353
|
-
s4 = Se({ content:
|
|
1353
|
+
s4 = Se({ content: a27, spacer: B.current, viewport: T }) - ue <= T.clientHeight ? I2({ behavior: "auto" }) : le(O, { align: "start" }, { keepPreviousPeek: true });
|
|
1354
1354
|
}
|
|
1355
|
-
} else s4 =
|
|
1355
|
+
} else s4 = t9 === "end" ? I2({ behavior: "auto" }) : ae({ behavior: "auto" });
|
|
1356
1356
|
return s4 ? (C.current = true, true) : false;
|
|
1357
|
-
}, [
|
|
1357
|
+
}, [t9, le, I2, ae]), Te = g.useCallback(() => {
|
|
1358
1358
|
let s4 = b2.current;
|
|
1359
1359
|
if (!s4) return;
|
|
1360
|
-
let
|
|
1361
|
-
m5.current =
|
|
1360
|
+
let a27 = ee(s4, B.current), T = m5.current, O = p3.current;
|
|
1361
|
+
m5.current = a27.length, p3.current = a27[0] ?? null, (() => {
|
|
1362
1362
|
if (ce()) return;
|
|
1363
1363
|
if (T === 0) {
|
|
1364
|
-
if (ie() ||
|
|
1364
|
+
if (ie() || a27.length > 0 && l5.current && I2({ behavior: "auto" })) return;
|
|
1365
1365
|
F(), w2();
|
|
1366
1366
|
return;
|
|
1367
1367
|
}
|
|
1368
|
-
let W = O ?
|
|
1368
|
+
let W = O ? a27.indexOf(O) : -1;
|
|
1369
1369
|
if (_.current && W > 0) {
|
|
1370
1370
|
de();
|
|
1371
1371
|
return;
|
|
1372
1372
|
}
|
|
1373
|
-
if (
|
|
1374
|
-
let $ = je(
|
|
1373
|
+
if (a27.length > T) {
|
|
1374
|
+
let $ = je(a27, T);
|
|
1375
1375
|
if ($) {
|
|
1376
|
-
if (l5.current && u.current === "following-bottom" && Ne(
|
|
1376
|
+
if (l5.current && u.current === "following-bottom" && Ne(a27, T)) {
|
|
1377
1377
|
I2({ behavior: "auto" });
|
|
1378
1378
|
return;
|
|
1379
1379
|
}
|
|
@@ -1381,8 +1381,8 @@ function nt({ autoScroll: e53 = false, defaultScrollPosition: t8 = "end", scroll
|
|
|
1381
1381
|
return;
|
|
1382
1382
|
}
|
|
1383
1383
|
}
|
|
1384
|
-
if (
|
|
1385
|
-
let $ = Ge(
|
|
1384
|
+
if (a27.length === T) {
|
|
1385
|
+
let $ = Ge(a27, z.current);
|
|
1386
1386
|
if ($) {
|
|
1387
1387
|
le($, { align: "start" }, { keepPreviousPeek: true }), z.current.add($);
|
|
1388
1388
|
return;
|
|
@@ -1408,21 +1408,21 @@ function nt({ autoScroll: e53 = false, defaultScrollPosition: t8 = "end", scroll
|
|
|
1408
1408
|
w2();
|
|
1409
1409
|
return;
|
|
1410
1410
|
}
|
|
1411
|
-
h.current || (h.current = new IntersectionObserver((
|
|
1412
|
-
for (let T of
|
|
1411
|
+
h.current || (h.current = new IntersectionObserver((a27) => {
|
|
1412
|
+
for (let T of a27) {
|
|
1413
1413
|
let O = T.target.dataset.messageId;
|
|
1414
1414
|
O && (T.isIntersecting ? V.current.add(O) : V.current.delete(O));
|
|
1415
1415
|
}
|
|
1416
1416
|
w2();
|
|
1417
|
-
}, { root: s4, rootMargin: `${-(H.current + N.current)}px 0px 0px 0px`, threshold: [0, 0.01, 0.5, 1] })), y.current.forEach((
|
|
1418
|
-
h.current?.observe(
|
|
1417
|
+
}, { root: s4, rootMargin: `${-(H.current + N.current)}px 0px 0px 0px`, threshold: [0, 0.01, 0.5, 1] })), y.current.forEach((a27) => {
|
|
1418
|
+
h.current?.observe(a27);
|
|
1419
1419
|
}), w2();
|
|
1420
1420
|
}
|
|
1421
1421
|
}, [w2, P]), he = g.useCallback(() => {
|
|
1422
1422
|
f9.current !== null && (window.cancelAnimationFrame(f9.current), f9.current = null), h.current?.disconnect(), h.current = null, V.current.clear(), P.setSnapshot(Q);
|
|
1423
|
-
}, [P]), pt = g.useCallback((s4,
|
|
1424
|
-
if (
|
|
1425
|
-
y.current.set(s4,
|
|
1423
|
+
}, [P]), pt = g.useCallback((s4, a27, T) => {
|
|
1424
|
+
if (a27) {
|
|
1425
|
+
y.current.set(s4, a27), h.current?.observe(a27), w2(), Y.current?.messageId === s4 && be();
|
|
1426
1426
|
return;
|
|
1427
1427
|
}
|
|
1428
1428
|
T && y.current.get(s4) === T && (y.current.delete(s4), V.current.delete(s4), h.current?.unobserve(T), w2());
|
|
@@ -1448,8 +1448,8 @@ function nt({ autoScroll: e53 = false, defaultScrollPosition: t8 = "end", scroll
|
|
|
1448
1448
|
}, [e53, F, I2]), { context: mt, registerMessage: pt };
|
|
1449
1449
|
}
|
|
1450
1450
|
function lt(e53) {
|
|
1451
|
-
let
|
|
1452
|
-
return
|
|
1451
|
+
let t9 = g.useRef(e53);
|
|
1452
|
+
return t9.current = e53, t9;
|
|
1453
1453
|
}
|
|
1454
1454
|
var st = g.createContext(null);
|
|
1455
1455
|
var ct = g.createContext(null);
|
|
@@ -1463,15 +1463,15 @@ function Et() {
|
|
|
1463
1463
|
if (!e53) throw new Error("MessageScrollerItem must be used within a MessageScroller.");
|
|
1464
1464
|
return e53;
|
|
1465
1465
|
}
|
|
1466
|
-
function at({ autoScroll: e53 = false, children:
|
|
1467
|
-
let { context: S2, registerMessage: l5 } = nt({ autoScroll: e53, defaultScrollPosition:
|
|
1468
|
-
return jsx2(st.Provider, { value: S2, children: jsx2(ct.Provider, { value: l5, children:
|
|
1466
|
+
function at({ autoScroll: e53 = false, children: t9, defaultScrollPosition: r31 = "end", scrollEdgeThreshold: n, scrollPreviousItemPeek: o41, scrollMargin: i3 }) {
|
|
1467
|
+
let { context: S2, registerMessage: l5 } = nt({ autoScroll: e53, defaultScrollPosition: r31, scrollEdgeThreshold: n, scrollPreviousItemPeek: o41, scrollMargin: i3 });
|
|
1468
|
+
return jsx2(st.Provider, { value: S2, children: jsx2(ct.Provider, { value: l5, children: t9 }) });
|
|
1469
1469
|
}
|
|
1470
|
-
function it({ children: e53, ...
|
|
1471
|
-
let { setRootElement:
|
|
1472
|
-
return jsx2("div", { ref:
|
|
1470
|
+
function it({ children: e53, ...t9 }) {
|
|
1471
|
+
let { setRootElement: r31 } = X2();
|
|
1472
|
+
return jsx2("div", { ref: r31, ...t9, children: e53 });
|
|
1473
1473
|
}
|
|
1474
|
-
function ut({ "aria-label": e53, children:
|
|
1474
|
+
function ut({ "aria-label": e53, children: t9, onKeyDown: r31, onScroll: n, onTouchMove: o41, onWheel: i3, preserveScrollOnPrepend: S2 = true, ref: l5, role: d2, tabIndex: E, ...b2 }) {
|
|
1475
1475
|
let { handleResize: C, preserveScrollOnPrependRef: p3, setViewportElement: m5, syncAfterScroll: L, userScrollIntent: y, viewportRef: u } = X2();
|
|
1476
1476
|
p3.current = S2;
|
|
1477
1477
|
let x = g.useCallback((v) => {
|
|
@@ -1484,10 +1484,10 @@ function ut({ "aria-label": e53, children: t8, onKeyDown: r28, onScroll: n, onTo
|
|
|
1484
1484
|
y(), i3?.(v);
|
|
1485
1485
|
}
|
|
1486
1486
|
function _(v) {
|
|
1487
|
-
y(),
|
|
1487
|
+
y(), o41?.(v);
|
|
1488
1488
|
}
|
|
1489
1489
|
function G(v) {
|
|
1490
|
-
Be.has(v.key) && y(),
|
|
1490
|
+
Be.has(v.key) && y(), r31?.(v);
|
|
1491
1491
|
}
|
|
1492
1492
|
return g.useEffect(() => {
|
|
1493
1493
|
let v = u.current;
|
|
@@ -1498,12 +1498,12 @@ function ut({ "aria-label": e53, children: t8, onKeyDown: r28, onScroll: n, onTo
|
|
|
1498
1498
|
return N.observe(v), () => {
|
|
1499
1499
|
window.cancelAnimationFrame(H), N.disconnect();
|
|
1500
1500
|
};
|
|
1501
|
-
}, [C, u]), jsx2("div", { ref: x, role: d2 ?? "region", "aria-label": e53 ?? "Messages", tabIndex: E ?? 0, onKeyDown: G, onScroll: Y, onTouchMove: _, onWheel: k, ...b2, children:
|
|
1501
|
+
}, [C, u]), jsx2("div", { ref: x, role: d2 ?? "region", "aria-label": e53 ?? "Messages", tabIndex: E ?? 0, onKeyDown: G, onScroll: Y, onTouchMove: _, onWheel: k, ...b2, children: t9 });
|
|
1502
1502
|
}
|
|
1503
|
-
function ft({ "aria-relevant": e53, children:
|
|
1503
|
+
function ft({ "aria-relevant": e53, children: t9, ref: r31, role: n, spacerClassName: o41, ...i3 }) {
|
|
1504
1504
|
let { handleContentChange: S2, handleResize: l5, setContentElement: d2, setSpacerElement: E } = X2(), b2 = g.useRef(null), C = g.useCallback((p3) => {
|
|
1505
|
-
b2.current = p3, d2(p3), f8(
|
|
1506
|
-
}, [
|
|
1505
|
+
b2.current = p3, d2(p3), f8(r31)?.(p3);
|
|
1506
|
+
}, [r31, d2]);
|
|
1507
1507
|
return g.useLayoutEffect(() => {
|
|
1508
1508
|
let p3 = b2.current;
|
|
1509
1509
|
if (!p3 || (S2(), typeof MutationObserver > "u")) return;
|
|
@@ -1520,23 +1520,23 @@ function ft({ "aria-relevant": e53, children: t8, ref: r28, role: n, spacerClass
|
|
|
1520
1520
|
return L.observe(p3), () => {
|
|
1521
1521
|
window.cancelAnimationFrame(m5), L.disconnect();
|
|
1522
1522
|
};
|
|
1523
|
-
}, [l5]), jsxs("div", { ref: C, role: n ?? "log", "aria-relevant": e53 ?? "additions", ...i3, children: [
|
|
1523
|
+
}, [l5]), jsxs("div", { ref: C, role: n ?? "log", "aria-relevant": e53 ?? "additions", ...i3, children: [t9, jsx2("div", { ref: E, "aria-hidden": "true", "data-message-scroller-spacer": "", hidden: true, className: o41 })] });
|
|
1524
1524
|
}
|
|
1525
|
-
function gt({ messageId: e53, ref:
|
|
1526
|
-
let
|
|
1525
|
+
function gt({ messageId: e53, ref: t9, scrollAnchor: r31 = false, ...n }) {
|
|
1526
|
+
let o41 = Et(), i3 = g.useRef(null), S2 = g.useCallback((l5) => {
|
|
1527
1527
|
let d2 = i3.current;
|
|
1528
|
-
i3.current = l5, e53 &&
|
|
1529
|
-
}, [e53,
|
|
1530
|
-
return jsx2("div", { ref: S2, "data-message-id": e53, "data-scroll-anchor":
|
|
1528
|
+
i3.current = l5, e53 && o41(e53, l5, d2), f8(t9)?.(l5);
|
|
1529
|
+
}, [e53, t9, o41]);
|
|
1530
|
+
return jsx2("div", { ref: S2, "data-message-id": e53, "data-scroll-anchor": r31 ? "true" : "false", ...n });
|
|
1531
1531
|
}
|
|
1532
|
-
function St({ behavior: e53 = "smooth", children:
|
|
1532
|
+
function St({ behavior: e53 = "smooth", children: t9, direction: r31 = "end", onClick: n, render: o41, tabIndex: i3, type: S2 = "button", ...l5 }) {
|
|
1533
1533
|
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(() => {
|
|
1534
1534
|
let u = b$1.getSnapshot();
|
|
1535
|
-
return
|
|
1536
|
-
}, [
|
|
1537
|
-
L && (C.current?.(u), u.defaultPrevented || (u.currentTarget.blur(),
|
|
1538
|
-
}, [e53,
|
|
1539
|
-
return S({ defaultTagName: "button", props: d({ type: S2, inert: !L, tabIndex: L ? i3 : -1, children:
|
|
1535
|
+
return r31 === "start" ? u.start : u.end;
|
|
1536
|
+
}, [r31, b$1]), L = g.useSyncExternalStore(p3, m5, m5), y = g.useCallback((u) => {
|
|
1537
|
+
L && (C.current?.(u), u.defaultPrevented || (u.currentTarget.blur(), r31 === "start" ? E({ behavior: e53 }) : d2({ behavior: e53 })));
|
|
1538
|
+
}, [e53, r31, L, C, d2, E]);
|
|
1539
|
+
return S({ defaultTagName: "button", props: d({ type: S2, inert: !L, tabIndex: L ? i3 : -1, children: t9 ?? jsxs("span", { children: ["Scroll to ", r31] }), onClick: y }, l5), render: o41, state: { active: L, direction: r31 }, stateAttributesMapping: { active: (u) => ({ "data-active": u ? "true" : "false" }) } });
|
|
1540
1540
|
}
|
|
1541
1541
|
var $t = { Provider: at, Root: it, Viewport: ut, Content: ft, Item: gt, Button: St };
|
|
1542
1542
|
|
|
@@ -1775,7 +1775,7 @@ var use = React2[" use ".trim().toString()];
|
|
|
1775
1775
|
// ../../apps/web/src/components/ui/button.tsx
|
|
1776
1776
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1777
1777
|
var buttonVariants = cva(
|
|
1778
|
-
"group/button inline-flex shrink-0 items-center justify-center rounded-full border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 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",
|
|
1778
|
+
"group/button inline-flex shrink-0 items-center justify-center rounded-full border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none touch-manipulation focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 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",
|
|
1779
1779
|
{
|
|
1780
1780
|
variants: {
|
|
1781
1781
|
variant: {
|
|
@@ -2126,8 +2126,11 @@ var Image = forwardRef24(function Image2({
|
|
|
2126
2126
|
});
|
|
2127
2127
|
var next_image_shim_default = Image;
|
|
2128
2128
|
|
|
2129
|
+
// ../../apps/web/src/components/attachments/attachment-image.tsx
|
|
2130
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
2131
|
+
|
|
2129
2132
|
// ../../apps/web/src/components/attachments/attachment-draft-chip.tsx
|
|
2130
|
-
import { jsx as
|
|
2133
|
+
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2131
2134
|
var KIND_ICONS = {
|
|
2132
2135
|
image: ImageSquare,
|
|
2133
2136
|
video: Play,
|
|
@@ -2153,7 +2156,7 @@ function AttachmentDraftChip({
|
|
|
2153
2156
|
draft.previewUrl ? (
|
|
2154
2157
|
// Object URLs cannot be optimised, and there is nothing to optimise:
|
|
2155
2158
|
// the file has not left the browser.
|
|
2156
|
-
/* @__PURE__ */
|
|
2159
|
+
/* @__PURE__ */ jsx7(
|
|
2157
2160
|
next_image_shim_default,
|
|
2158
2161
|
{
|
|
2159
2162
|
src: draft.previewUrl,
|
|
@@ -2164,7 +2167,7 @@ function AttachmentDraftChip({
|
|
|
2164
2167
|
className: "size-8 shrink-0 rounded-md object-cover"
|
|
2165
2168
|
}
|
|
2166
2169
|
)
|
|
2167
|
-
) : /* @__PURE__ */
|
|
2170
|
+
) : /* @__PURE__ */ jsx7("span", { className: "grid size-8 shrink-0 place-items-center rounded-md bg-muted", children: /* @__PURE__ */ jsx7(
|
|
2168
2171
|
Glyph,
|
|
2169
2172
|
{
|
|
2170
2173
|
className: cn(
|
|
@@ -2174,8 +2177,8 @@ function AttachmentDraftChip({
|
|
|
2174
2177
|
}
|
|
2175
2178
|
) }),
|
|
2176
2179
|
/* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
2177
|
-
/* @__PURE__ */
|
|
2178
|
-
/* @__PURE__ */
|
|
2180
|
+
/* @__PURE__ */ jsx7("p", { className: "truncate text-xs font-medium", children: draft.name }),
|
|
2181
|
+
/* @__PURE__ */ jsx7(
|
|
2179
2182
|
"p",
|
|
2180
2183
|
{
|
|
2181
2184
|
className: cn(
|
|
@@ -2186,7 +2189,7 @@ function AttachmentDraftChip({
|
|
|
2186
2189
|
}
|
|
2187
2190
|
)
|
|
2188
2191
|
] }),
|
|
2189
|
-
/* @__PURE__ */
|
|
2192
|
+
/* @__PURE__ */ jsx7(
|
|
2190
2193
|
Button,
|
|
2191
2194
|
{
|
|
2192
2195
|
type: "button",
|
|
@@ -2195,7 +2198,7 @@ function AttachmentDraftChip({
|
|
|
2195
2198
|
onClick: onRemove,
|
|
2196
2199
|
"aria-label": `Remove ${draft.name}`,
|
|
2197
2200
|
className: "shrink-0 rounded-full text-muted-foreground",
|
|
2198
|
-
children: /* @__PURE__ */
|
|
2201
|
+
children: /* @__PURE__ */ jsx7(X, {})
|
|
2199
2202
|
}
|
|
2200
2203
|
)
|
|
2201
2204
|
]
|
|
@@ -2206,6 +2209,16 @@ function AttachmentDraftChip({
|
|
|
2206
2209
|
// ../../apps/web/src/components/attachments/use-attachment-drafts.ts
|
|
2207
2210
|
import { useEffect as useEffect4, useRef as useRef4, useState as useState3 } from "react";
|
|
2208
2211
|
var MAX_BYTES = 25 * 1024 * 1024;
|
|
2212
|
+
var UNSAFE_TYPES = [
|
|
2213
|
+
"text/html",
|
|
2214
|
+
"application/xhtml+xml",
|
|
2215
|
+
"image/svg+xml",
|
|
2216
|
+
"text/xsl",
|
|
2217
|
+
"application/xslt+xml"
|
|
2218
|
+
];
|
|
2219
|
+
function isUnsafeType(type) {
|
|
2220
|
+
return UNSAFE_TYPES.includes(type.split(";")[0].trim().toLowerCase());
|
|
2221
|
+
}
|
|
2209
2222
|
var nextDraftId = 0;
|
|
2210
2223
|
function formatFileSize(bytes) {
|
|
2211
2224
|
if (bytes < 1024) return `${bytes} B`;
|
|
@@ -2218,6 +2231,11 @@ function formatFileSize(bytes) {
|
|
|
2218
2231
|
}
|
|
2219
2232
|
return `${value < 10 ? value.toFixed(1) : Math.round(value)} ${units[unit]}`;
|
|
2220
2233
|
}
|
|
2234
|
+
var KIND_NAMES = {
|
|
2235
|
+
image: "pictures",
|
|
2236
|
+
video: "videos",
|
|
2237
|
+
file: "files"
|
|
2238
|
+
};
|
|
2221
2239
|
function attachmentKindOf(type) {
|
|
2222
2240
|
if (type.startsWith("image/")) return "image";
|
|
2223
2241
|
if (type.startsWith("video/")) return "video";
|
|
@@ -2226,7 +2244,10 @@ function attachmentKindOf(type) {
|
|
|
2226
2244
|
function release(draft) {
|
|
2227
2245
|
if (draft.previewUrl) URL.revokeObjectURL(draft.previewUrl);
|
|
2228
2246
|
}
|
|
2229
|
-
function useAttachmentDrafts(
|
|
2247
|
+
function useAttachmentDrafts({
|
|
2248
|
+
accept,
|
|
2249
|
+
max
|
|
2250
|
+
} = {}) {
|
|
2230
2251
|
const [drafts, setDrafts] = useState3([]);
|
|
2231
2252
|
const draftsRef = useRef4(drafts);
|
|
2232
2253
|
useEffect4(() => {
|
|
@@ -2234,17 +2255,21 @@ function useAttachmentDrafts() {
|
|
|
2234
2255
|
}, [drafts]);
|
|
2235
2256
|
useEffect4(() => () => draftsRef.current.forEach(release), []);
|
|
2236
2257
|
function add(files) {
|
|
2237
|
-
const picked = Array.from(files).map((file) => {
|
|
2258
|
+
const picked = Array.from(files).map((file, index) => {
|
|
2238
2259
|
const isTooBig = file.size > MAX_BYTES;
|
|
2260
|
+
const isUnsafe = isUnsafeType(file.type);
|
|
2239
2261
|
const kind = attachmentKindOf(file.type);
|
|
2262
|
+
const isWrongKind = accept !== void 0 && kind !== accept;
|
|
2263
|
+
const isOverCap = max !== void 0 && drafts.length + index >= max;
|
|
2264
|
+
const error = isTooBig ? `Larger than the ${formatFileSize(MAX_BYTES)} limit` : isUnsafe ? "This kind of file cannot be sent" : isWrongKind ? `Only ${KIND_NAMES[accept]} can go here` : isOverCap ? `Only ${max} at a time` : null;
|
|
2240
2265
|
return {
|
|
2241
2266
|
id: `draft-${nextDraftId += 1}`,
|
|
2242
2267
|
file,
|
|
2243
2268
|
name: file.name,
|
|
2244
2269
|
size: formatFileSize(file.size),
|
|
2245
2270
|
kind,
|
|
2246
|
-
previewUrl: kind === "image" &&
|
|
2247
|
-
error
|
|
2271
|
+
previewUrl: kind === "image" && error === null ? URL.createObjectURL(file) : null,
|
|
2272
|
+
error
|
|
2248
2273
|
};
|
|
2249
2274
|
});
|
|
2250
2275
|
setDrafts([...drafts, ...picked]);
|
|
@@ -2266,7 +2291,9 @@ function useAttachmentDrafts() {
|
|
|
2266
2291
|
/** The originals, in the order they were picked. */
|
|
2267
2292
|
files: drafts.map((draft) => draft.file),
|
|
2268
2293
|
/** True while something in the list cannot be sent. */
|
|
2269
|
-
hasBlocker: drafts.some((draft) => draft.error !== null)
|
|
2294
|
+
hasBlocker: drafts.some((draft) => draft.error !== null),
|
|
2295
|
+
/** True once the cap is reached, for a picker that should go quiet. */
|
|
2296
|
+
isFull: max !== void 0 && drafts.length >= max
|
|
2270
2297
|
};
|
|
2271
2298
|
}
|
|
2272
2299
|
|
|
@@ -2319,7 +2346,7 @@ function useAttachmentTarget({
|
|
|
2319
2346
|
}
|
|
2320
2347
|
|
|
2321
2348
|
// ../../apps/web/src/components/support-widget/widget-button.tsx
|
|
2322
|
-
import { jsx as
|
|
2349
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
2323
2350
|
var widgetButtonVariants = cva(
|
|
2324
2351
|
"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-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 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",
|
|
2325
2352
|
{
|
|
@@ -2357,7 +2384,7 @@ function WidgetButton({
|
|
|
2357
2384
|
...props
|
|
2358
2385
|
}) {
|
|
2359
2386
|
const Comp = asChild ? dist_exports.Root : "button";
|
|
2360
|
-
return /* @__PURE__ */
|
|
2387
|
+
return /* @__PURE__ */ jsx8(
|
|
2361
2388
|
Comp,
|
|
2362
2389
|
{
|
|
2363
2390
|
"data-slot": "widget-button",
|
|
@@ -2371,7 +2398,7 @@ function WidgetButton({
|
|
|
2371
2398
|
|
|
2372
2399
|
// ../../apps/web/src/components/ui/text-field.ts
|
|
2373
2400
|
var TEXT_FIELD_SHELL = [
|
|
2374
|
-
"rounded-lg border border-input bg-transparent text-sm transition-[color,box-shadow] outline-none dark:bg-input/30",
|
|
2401
|
+
"rounded-lg border border-input bg-transparent text-sm max-sm:text-base transition-[color,box-shadow] outline-none dark:bg-input/30",
|
|
2375
2402
|
"placeholder:text-muted-foreground",
|
|
2376
2403
|
// Focus recolours the hairline rather than adding a ring on top of it, so
|
|
2377
2404
|
// the outline stays exactly 1px and nothing swells on click.
|
|
@@ -2381,14 +2408,14 @@ var TEXT_FIELD_SHELL = [
|
|
|
2381
2408
|
].join(" ");
|
|
2382
2409
|
|
|
2383
2410
|
// ../../apps/web/src/components/ui/textarea.tsx
|
|
2384
|
-
import { jsx as
|
|
2411
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
2385
2412
|
function Textarea({ className, ...props }) {
|
|
2386
|
-
return /* @__PURE__ */
|
|
2413
|
+
return /* @__PURE__ */ jsx9(
|
|
2387
2414
|
"textarea",
|
|
2388
2415
|
{
|
|
2389
2416
|
"data-slot": "textarea",
|
|
2390
2417
|
className: cn(
|
|
2391
|
-
"field-sizing-content w-full resize-none bg-transparent text-sm outline-none",
|
|
2418
|
+
"field-sizing-content w-full resize-none bg-transparent text-sm outline-none max-sm:text-base",
|
|
2392
2419
|
"placeholder:text-muted-foreground",
|
|
2393
2420
|
"disabled:pointer-events-none disabled:opacity-50",
|
|
2394
2421
|
className
|
|
@@ -2469,13 +2496,13 @@ var LOGO_MASK_URL = `url("data:image/svg+xml,${encodeURIComponent(
|
|
|
2469
2496
|
)}")`;
|
|
2470
2497
|
|
|
2471
2498
|
// ../../apps/web/src/components/brand.tsx
|
|
2472
|
-
import { jsx as
|
|
2499
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
2473
2500
|
var INVERT_IN_DARK = "dark:invert";
|
|
2474
2501
|
function Wordmark({
|
|
2475
2502
|
width = 132,
|
|
2476
2503
|
className = ""
|
|
2477
2504
|
}) {
|
|
2478
|
-
return /* @__PURE__ */
|
|
2505
|
+
return /* @__PURE__ */ jsx10(
|
|
2479
2506
|
"svg",
|
|
2480
2507
|
{
|
|
2481
2508
|
viewBox: WORDMARK.viewBox,
|
|
@@ -2484,7 +2511,7 @@ function Wordmark({
|
|
|
2484
2511
|
role: "img",
|
|
2485
2512
|
"aria-label": "Median",
|
|
2486
2513
|
className: `${INVERT_IN_DARK} ${className}`,
|
|
2487
|
-
children: WORDMARK.paths.map((d2) => /* @__PURE__ */
|
|
2514
|
+
children: WORDMARK.paths.map((d2) => /* @__PURE__ */ jsx10("path", { d: d2, fill: BRAND_INK }, d2))
|
|
2488
2515
|
}
|
|
2489
2516
|
);
|
|
2490
2517
|
}
|
|
@@ -2492,7 +2519,7 @@ function Logo({
|
|
|
2492
2519
|
size = 104,
|
|
2493
2520
|
className = ""
|
|
2494
2521
|
}) {
|
|
2495
|
-
return /* @__PURE__ */
|
|
2522
|
+
return /* @__PURE__ */ jsx10(
|
|
2496
2523
|
"svg",
|
|
2497
2524
|
{
|
|
2498
2525
|
viewBox: LOGO.viewBox,
|
|
@@ -2500,13 +2527,41 @@ function Logo({
|
|
|
2500
2527
|
height: size,
|
|
2501
2528
|
"aria-hidden": true,
|
|
2502
2529
|
className: `${INVERT_IN_DARK} ${className}`,
|
|
2503
|
-
children: LOGO.paths.map((d2) => /* @__PURE__ */
|
|
2530
|
+
children: LOGO.paths.map((d2) => /* @__PURE__ */ jsx10("path", { d: d2, fill: BRAND_INK }, d2))
|
|
2531
|
+
}
|
|
2532
|
+
);
|
|
2533
|
+
}
|
|
2534
|
+
function ShimmerLogo({
|
|
2535
|
+
label,
|
|
2536
|
+
className
|
|
2537
|
+
}) {
|
|
2538
|
+
return /* @__PURE__ */ jsx10(
|
|
2539
|
+
"span",
|
|
2540
|
+
{
|
|
2541
|
+
role: "status",
|
|
2542
|
+
"aria-label": label,
|
|
2543
|
+
style: {
|
|
2544
|
+
maskImage: LOGO_MASK_URL,
|
|
2545
|
+
maskSize: "contain",
|
|
2546
|
+
maskRepeat: "no-repeat",
|
|
2547
|
+
maskPosition: "center",
|
|
2548
|
+
WebkitMaskImage: LOGO_MASK_URL,
|
|
2549
|
+
WebkitMaskSize: "contain",
|
|
2550
|
+
WebkitMaskRepeat: "no-repeat",
|
|
2551
|
+
WebkitMaskPosition: "center",
|
|
2552
|
+
backgroundImage: "linear-gradient(115deg, var(--muted) 34%, var(--muted-foreground) 50%, var(--muted) 66%)",
|
|
2553
|
+
backgroundSize: "300% 100%"
|
|
2554
|
+
},
|
|
2555
|
+
className: cn(
|
|
2556
|
+
"size-12 animate-shimmer motion-reduce:animate-none motion-reduce:bg-muted",
|
|
2557
|
+
className
|
|
2558
|
+
)
|
|
2504
2559
|
}
|
|
2505
2560
|
);
|
|
2506
2561
|
}
|
|
2507
2562
|
|
|
2508
2563
|
// ../../apps/web/src/components/support-widget/widget-badge.tsx
|
|
2509
|
-
import { jsx as
|
|
2564
|
+
import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2510
2565
|
var MEDIAN_URL = "https://median.sh";
|
|
2511
2566
|
function PoweredByMedian({ className }) {
|
|
2512
2567
|
return /* @__PURE__ */ jsxs4(
|
|
@@ -2523,15 +2578,15 @@ function PoweredByMedian({ className }) {
|
|
|
2523
2578
|
),
|
|
2524
2579
|
children: [
|
|
2525
2580
|
"Powered by",
|
|
2526
|
-
/* @__PURE__ */
|
|
2527
|
-
/* @__PURE__ */
|
|
2581
|
+
/* @__PURE__ */ jsx11(Logo, { size: 12, className: "opacity-80" }),
|
|
2582
|
+
/* @__PURE__ */ jsx11(Wordmark, { width: 40, className: "opacity-80" })
|
|
2528
2583
|
]
|
|
2529
2584
|
}
|
|
2530
2585
|
);
|
|
2531
2586
|
}
|
|
2532
2587
|
|
|
2533
2588
|
// ../../apps/web/src/components/support-widget/widget-composer.tsx
|
|
2534
|
-
import { jsx as
|
|
2589
|
+
import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2535
2590
|
var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2536
2591
|
var SWAP = "transition-[opacity,translate] duration-300 ease-out motion-reduce:transition-none";
|
|
2537
2592
|
var RISE = "transition-transform duration-450 ease-spring motion-reduce:transition-none";
|
|
@@ -2610,7 +2665,7 @@ function WidgetComposer({
|
|
|
2610
2665
|
className: "flex shrink-0 flex-col gap-1.5 px-3 pt-1 pb-3",
|
|
2611
2666
|
...isAsking ? {} : target.targetProps,
|
|
2612
2667
|
children: [
|
|
2613
|
-
!isAsking && attachments.drafts.length > 0 && /* @__PURE__ */
|
|
2668
|
+
!isAsking && attachments.drafts.length > 0 && /* @__PURE__ */ jsx12("ul", { className: "flex flex-wrap gap-1.5 px-1", children: attachments.drafts.map((item) => /* @__PURE__ */ jsx12("li", { className: "min-w-0", children: /* @__PURE__ */ jsx12(
|
|
2614
2669
|
AttachmentDraftChip,
|
|
2615
2670
|
{
|
|
2616
2671
|
draft: item,
|
|
@@ -2618,13 +2673,13 @@ function WidgetComposer({
|
|
|
2618
2673
|
}
|
|
2619
2674
|
) }, item.id)) }),
|
|
2620
2675
|
/* @__PURE__ */ jsxs5("div", { className: "relative", children: [
|
|
2621
|
-
/* @__PURE__ */
|
|
2676
|
+
/* @__PURE__ */ jsx12(
|
|
2622
2677
|
"div",
|
|
2623
2678
|
{
|
|
2624
2679
|
"aria-hidden": !showTab,
|
|
2625
2680
|
inert: !showTab,
|
|
2626
2681
|
className: "pointer-events-none absolute inset-x-0 bottom-full z-0 -mb-0.5 flex items-end justify-center overflow-hidden pt-2",
|
|
2627
|
-
children: /* @__PURE__ */
|
|
2682
|
+
children: /* @__PURE__ */ jsx12(
|
|
2628
2683
|
"div",
|
|
2629
2684
|
{
|
|
2630
2685
|
className: cn(
|
|
@@ -2644,8 +2699,8 @@ function WidgetComposer({
|
|
|
2644
2699
|
isSaved && "-translate-y-full"
|
|
2645
2700
|
),
|
|
2646
2701
|
children: [
|
|
2647
|
-
/* @__PURE__ */
|
|
2648
|
-
/* @__PURE__ */
|
|
2702
|
+
/* @__PURE__ */ jsx12(EnvelopeSimple, { "aria-hidden": true, className: "size-4 shrink-0" }),
|
|
2703
|
+
/* @__PURE__ */ jsx12("span", { className: "truncate", children: "Enter your email" })
|
|
2649
2704
|
]
|
|
2650
2705
|
}
|
|
2651
2706
|
),
|
|
@@ -2659,8 +2714,8 @@ function WidgetComposer({
|
|
|
2659
2714
|
!isSaved && "translate-y-full"
|
|
2660
2715
|
),
|
|
2661
2716
|
children: [
|
|
2662
|
-
/* @__PURE__ */
|
|
2663
|
-
/* @__PURE__ */
|
|
2717
|
+
/* @__PURE__ */ jsx12(Check, { "aria-hidden": true, className: "size-4 shrink-0" }),
|
|
2718
|
+
/* @__PURE__ */ jsx12("span", { className: "truncate", children: "Saved" })
|
|
2664
2719
|
]
|
|
2665
2720
|
}
|
|
2666
2721
|
)
|
|
@@ -2691,7 +2746,7 @@ function WidgetComposer({
|
|
|
2691
2746
|
isAsking && "-translate-y-1 opacity-0 pointer-events-none"
|
|
2692
2747
|
),
|
|
2693
2748
|
children: [
|
|
2694
|
-
/* @__PURE__ */
|
|
2749
|
+
/* @__PURE__ */ jsx12(
|
|
2695
2750
|
"input",
|
|
2696
2751
|
{
|
|
2697
2752
|
ref: fileInputRef,
|
|
@@ -2702,7 +2757,7 @@ function WidgetComposer({
|
|
|
2702
2757
|
className: "sr-only"
|
|
2703
2758
|
}
|
|
2704
2759
|
),
|
|
2705
|
-
/* @__PURE__ */
|
|
2760
|
+
/* @__PURE__ */ jsx12(
|
|
2706
2761
|
WidgetButton,
|
|
2707
2762
|
{
|
|
2708
2763
|
type: "button",
|
|
@@ -2711,10 +2766,10 @@ function WidgetComposer({
|
|
|
2711
2766
|
onClick: () => fileInputRef.current?.click(),
|
|
2712
2767
|
"aria-label": "Add an attachment",
|
|
2713
2768
|
className: "rounded-full text-muted-foreground hover:rotate-90 motion-reduce:hover:rotate-0",
|
|
2714
|
-
children: /* @__PURE__ */
|
|
2769
|
+
children: /* @__PURE__ */ jsx12(Plus, {})
|
|
2715
2770
|
}
|
|
2716
2771
|
),
|
|
2717
|
-
/* @__PURE__ */
|
|
2772
|
+
/* @__PURE__ */ jsx12(
|
|
2718
2773
|
Textarea,
|
|
2719
2774
|
{
|
|
2720
2775
|
ref: draftRef,
|
|
@@ -2730,7 +2785,7 @@ function WidgetComposer({
|
|
|
2730
2785
|
className: "max-h-32 min-h-8 flex-1 px-1 py-1.5 max-sm:text-[16px]"
|
|
2731
2786
|
}
|
|
2732
2787
|
),
|
|
2733
|
-
/* @__PURE__ */
|
|
2788
|
+
/* @__PURE__ */ jsx12(
|
|
2734
2789
|
WidgetButton,
|
|
2735
2790
|
{
|
|
2736
2791
|
type: "button",
|
|
@@ -2742,7 +2797,7 @@ function WidgetComposer({
|
|
|
2742
2797
|
"rounded-full",
|
|
2743
2798
|
canSend ? "scale-100 opacity-100" : "scale-90 opacity-40 motion-reduce:scale-100"
|
|
2744
2799
|
),
|
|
2745
|
-
children: /* @__PURE__ */
|
|
2800
|
+
children: /* @__PURE__ */ jsx12(ArrowUp, {})
|
|
2746
2801
|
}
|
|
2747
2802
|
)
|
|
2748
2803
|
]
|
|
@@ -2759,7 +2814,7 @@ function WidgetComposer({
|
|
|
2759
2814
|
!isAsking && "pointer-events-none translate-y-1 opacity-0"
|
|
2760
2815
|
),
|
|
2761
2816
|
children: [
|
|
2762
|
-
/* @__PURE__ */
|
|
2817
|
+
/* @__PURE__ */ jsx12(
|
|
2763
2818
|
"input",
|
|
2764
2819
|
{
|
|
2765
2820
|
type: "email",
|
|
@@ -2778,7 +2833,7 @@ function WidgetComposer({
|
|
|
2778
2833
|
className: "h-8 min-w-0 flex-1 px-1 outline-none placeholder:text-muted-foreground max-sm:text-[16px]"
|
|
2779
2834
|
}
|
|
2780
2835
|
),
|
|
2781
|
-
/* @__PURE__ */
|
|
2836
|
+
/* @__PURE__ */ jsx12(
|
|
2782
2837
|
WidgetButton,
|
|
2783
2838
|
{
|
|
2784
2839
|
type: "button",
|
|
@@ -2790,7 +2845,7 @@ function WidgetComposer({
|
|
|
2790
2845
|
"rounded-full",
|
|
2791
2846
|
isValid ? "scale-100 opacity-100" : "scale-90 opacity-40 motion-reduce:scale-100"
|
|
2792
2847
|
),
|
|
2793
|
-
children: /* @__PURE__ */
|
|
2848
|
+
children: /* @__PURE__ */ jsx12(ArrowUp, {})
|
|
2794
2849
|
}
|
|
2795
2850
|
)
|
|
2796
2851
|
]
|
|
@@ -2800,7 +2855,7 @@ function WidgetComposer({
|
|
|
2800
2855
|
}
|
|
2801
2856
|
)
|
|
2802
2857
|
] }),
|
|
2803
|
-
showBadge && /* @__PURE__ */
|
|
2858
|
+
showBadge && /* @__PURE__ */ jsx12(PoweredByMedian, {})
|
|
2804
2859
|
]
|
|
2805
2860
|
}
|
|
2806
2861
|
)
|
|
@@ -2811,12 +2866,12 @@ function WidgetComposer({
|
|
|
2811
2866
|
import { useState as useState6 } from "react";
|
|
2812
2867
|
|
|
2813
2868
|
// ../../apps/web/src/components/initial-badge.tsx
|
|
2814
|
-
import { jsx as
|
|
2869
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
2815
2870
|
function InitialBadge({
|
|
2816
2871
|
value,
|
|
2817
2872
|
className
|
|
2818
2873
|
}) {
|
|
2819
|
-
return /* @__PURE__ */
|
|
2874
|
+
return /* @__PURE__ */ jsx13(
|
|
2820
2875
|
"span",
|
|
2821
2876
|
{
|
|
2822
2877
|
"aria-hidden": true,
|
|
@@ -2831,7 +2886,7 @@ function InitialBadge({
|
|
|
2831
2886
|
}
|
|
2832
2887
|
|
|
2833
2888
|
// ../../apps/web/src/components/avatar.tsx
|
|
2834
|
-
import { jsx as
|
|
2889
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
2835
2890
|
function Avatar({
|
|
2836
2891
|
src,
|
|
2837
2892
|
name,
|
|
@@ -2843,7 +2898,7 @@ function Avatar({
|
|
|
2843
2898
|
const hasFailed = failedSrc !== null && failedSrc === src;
|
|
2844
2899
|
const shape2 = "size-4.5 shrink-0 rounded-full";
|
|
2845
2900
|
if (!src || hasFailed) {
|
|
2846
|
-
return /* @__PURE__ */
|
|
2901
|
+
return /* @__PURE__ */ jsx14(
|
|
2847
2902
|
InitialBadge,
|
|
2848
2903
|
{
|
|
2849
2904
|
value: name,
|
|
@@ -2851,7 +2906,7 @@ function Avatar({
|
|
|
2851
2906
|
}
|
|
2852
2907
|
);
|
|
2853
2908
|
}
|
|
2854
|
-
return /* @__PURE__ */
|
|
2909
|
+
return /* @__PURE__ */ jsx14(
|
|
2855
2910
|
next_image_shim_default,
|
|
2856
2911
|
{
|
|
2857
2912
|
src,
|
|
@@ -2867,7 +2922,7 @@ function Avatar({
|
|
|
2867
2922
|
}
|
|
2868
2923
|
|
|
2869
2924
|
// ../../apps/web/src/components/support-widget/widget-avatar.tsx
|
|
2870
|
-
import { jsx as
|
|
2925
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
2871
2926
|
function WidgetAvatar({
|
|
2872
2927
|
agent,
|
|
2873
2928
|
label,
|
|
@@ -2875,7 +2930,7 @@ function WidgetAvatar({
|
|
|
2875
2930
|
}) {
|
|
2876
2931
|
const shape2 = "size-7 shrink-0 rounded-lg";
|
|
2877
2932
|
if (agent.kind === "ai" && !agent.avatarUrl) {
|
|
2878
|
-
return /* @__PURE__ */
|
|
2933
|
+
return /* @__PURE__ */ jsx15(
|
|
2879
2934
|
"span",
|
|
2880
2935
|
{
|
|
2881
2936
|
role: "img",
|
|
@@ -2885,17 +2940,17 @@ function WidgetAvatar({
|
|
|
2885
2940
|
shape2,
|
|
2886
2941
|
className
|
|
2887
2942
|
),
|
|
2888
|
-
children: /* @__PURE__ */
|
|
2943
|
+
children: /* @__PURE__ */ jsx15(Sparkle, { className: "size-[55%]" })
|
|
2889
2944
|
}
|
|
2890
2945
|
);
|
|
2891
2946
|
}
|
|
2892
|
-
return /* @__PURE__ */
|
|
2947
|
+
return /* @__PURE__ */ jsx15(
|
|
2893
2948
|
"span",
|
|
2894
2949
|
{
|
|
2895
2950
|
role: "img",
|
|
2896
2951
|
"aria-label": label ?? agent.name,
|
|
2897
2952
|
className: cn("inline-flex", shape2, className),
|
|
2898
|
-
children: /* @__PURE__ */
|
|
2953
|
+
children: /* @__PURE__ */ jsx15(
|
|
2899
2954
|
Avatar,
|
|
2900
2955
|
{
|
|
2901
2956
|
src: agent.avatarUrl,
|
|
@@ -2911,11 +2966,11 @@ function WidgetAvatarStack({
|
|
|
2911
2966
|
className
|
|
2912
2967
|
}) {
|
|
2913
2968
|
if (team.length === 0) return null;
|
|
2914
|
-
return /* @__PURE__ */
|
|
2969
|
+
return /* @__PURE__ */ jsx15("div", { className: cn("flex items-center gap-1", className), children: team.map((agent) => /* @__PURE__ */ jsx15(WidgetAvatar, { agent, className: "size-8" }, agent.id)) });
|
|
2915
2970
|
}
|
|
2916
2971
|
|
|
2917
2972
|
// ../../apps/web/src/components/support-widget/widget-empty.tsx
|
|
2918
|
-
import { jsx as
|
|
2973
|
+
import { jsx as jsx16, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2919
2974
|
var STARTERS = [
|
|
2920
2975
|
{
|
|
2921
2976
|
label: "Ask a question",
|
|
@@ -2942,7 +2997,7 @@ function WidgetEmpty({
|
|
|
2942
2997
|
}) {
|
|
2943
2998
|
const agent = team.find((member) => member.kind === "ai") ?? team[0];
|
|
2944
2999
|
return /* @__PURE__ */ jsxs6("div", { className: "flex min-h-0 flex-1 flex-col items-center justify-center gap-4 px-5 pb-2 text-center", children: [
|
|
2945
|
-
agent && /* @__PURE__ */
|
|
3000
|
+
agent && /* @__PURE__ */ jsx16(
|
|
2946
3001
|
WidgetAvatar,
|
|
2947
3002
|
{
|
|
2948
3003
|
agent,
|
|
@@ -2950,10 +3005,10 @@ function WidgetEmpty({
|
|
|
2950
3005
|
}
|
|
2951
3006
|
),
|
|
2952
3007
|
/* @__PURE__ */ jsxs6("div", { className: "flex max-w-64 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: [
|
|
2953
|
-
agent && /* @__PURE__ */
|
|
2954
|
-
/* @__PURE__ */
|
|
3008
|
+
agent && /* @__PURE__ */ jsx16("p", { className: "text-base font-semibold tracking-tight", children: agent.name }),
|
|
3009
|
+
/* @__PURE__ */ jsx16("p", { className: "text-sm text-balance text-muted-foreground", children: orgName ? `Ask me anything about ${orgName}.` : "Ask me anything." })
|
|
2955
3010
|
] }),
|
|
2956
|
-
onPick && /* @__PURE__ */
|
|
3011
|
+
onPick && /* @__PURE__ */ jsx16("div", { className: "flex w-full flex-col gap-1.5 pt-1", children: STARTERS.map((starter, index) => /* @__PURE__ */ jsxs6(
|
|
2957
3012
|
WidgetButton,
|
|
2958
3013
|
{
|
|
2959
3014
|
type: "button",
|
|
@@ -2967,9 +3022,9 @@ function WidgetEmpty({
|
|
|
2967
3022
|
"hover:border-foreground/15 hover:shadow-sm"
|
|
2968
3023
|
),
|
|
2969
3024
|
children: [
|
|
2970
|
-
/* @__PURE__ */
|
|
2971
|
-
/* @__PURE__ */
|
|
2972
|
-
/* @__PURE__ */
|
|
3025
|
+
/* @__PURE__ */ jsx16(starter.glyph, { className: "size-4 text-muted-foreground" }),
|
|
3026
|
+
/* @__PURE__ */ jsx16("span", { className: "min-w-0 flex-1 truncate", children: starter.label }),
|
|
3027
|
+
/* @__PURE__ */ jsx16(
|
|
2973
3028
|
CaretRight,
|
|
2974
3029
|
{
|
|
2975
3030
|
"aria-hidden": true,
|
|
@@ -2984,7 +3039,7 @@ function WidgetEmpty({
|
|
|
2984
3039
|
}
|
|
2985
3040
|
|
|
2986
3041
|
// ../../apps/web/src/components/support-widget/widget-header.tsx
|
|
2987
|
-
import { jsx as
|
|
3042
|
+
import { jsx as jsx17, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2988
3043
|
function WidgetHeader({
|
|
2989
3044
|
presence,
|
|
2990
3045
|
onClose,
|
|
@@ -3009,13 +3064,13 @@ function WidgetHeader({
|
|
|
3009
3064
|
),
|
|
3010
3065
|
children: [
|
|
3011
3066
|
/* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1 flex-col pt-0.5", children: [
|
|
3012
|
-
/* @__PURE__ */
|
|
3013
|
-
/* @__PURE__ */
|
|
3067
|
+
/* @__PURE__ */ jsx17("h2", { className: "truncate text-base font-semibold tracking-tight", children: presence.name }),
|
|
3068
|
+
/* @__PURE__ */ jsx17("p", { className: "truncate text-sm text-muted-foreground", children: presence.status })
|
|
3014
3069
|
] }),
|
|
3015
3070
|
/* @__PURE__ */ jsxs7("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
3016
|
-
/* @__PURE__ */
|
|
3071
|
+
/* @__PURE__ */ jsx17(WidgetAvatarStack, { team: presence.team }),
|
|
3017
3072
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-0.5", children: [
|
|
3018
|
-
onToggleExpanded && /* @__PURE__ */
|
|
3073
|
+
onToggleExpanded && /* @__PURE__ */ jsx17(
|
|
3019
3074
|
WidgetButton,
|
|
3020
3075
|
{
|
|
3021
3076
|
variant: "ghost",
|
|
@@ -3024,10 +3079,10 @@ function WidgetHeader({
|
|
|
3024
3079
|
"aria-pressed": isExpanded,
|
|
3025
3080
|
"aria-label": isExpanded ? "Shrink the panel" : "Expand the panel",
|
|
3026
3081
|
className: "text-muted-foreground",
|
|
3027
|
-
children: isExpanded ? /* @__PURE__ */
|
|
3082
|
+
children: isExpanded ? /* @__PURE__ */ jsx17(ArrowsIn, {}) : /* @__PURE__ */ jsx17(ArrowsOut, {})
|
|
3028
3083
|
}
|
|
3029
3084
|
),
|
|
3030
|
-
onClose && /* @__PURE__ */
|
|
3085
|
+
onClose && /* @__PURE__ */ jsx17(
|
|
3031
3086
|
WidgetButton,
|
|
3032
3087
|
{
|
|
3033
3088
|
variant: "ghost",
|
|
@@ -3035,7 +3090,7 @@ function WidgetHeader({
|
|
|
3035
3090
|
onClick: onClose,
|
|
3036
3091
|
"aria-label": "Close support",
|
|
3037
3092
|
className: "-mr-1 text-muted-foreground",
|
|
3038
|
-
children: /* @__PURE__ */
|
|
3093
|
+
children: /* @__PURE__ */ jsx17(X, {})
|
|
3039
3094
|
}
|
|
3040
3095
|
)
|
|
3041
3096
|
] })
|
|
@@ -3046,32 +3101,13 @@ function WidgetHeader({
|
|
|
3046
3101
|
}
|
|
3047
3102
|
|
|
3048
3103
|
// ../../apps/web/src/components/support-widget/widget-loading.tsx
|
|
3049
|
-
import { jsx as
|
|
3104
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
3050
3105
|
function WidgetLoading() {
|
|
3051
|
-
return /* @__PURE__ */
|
|
3052
|
-
"span",
|
|
3053
|
-
{
|
|
3054
|
-
role: "status",
|
|
3055
|
-
"aria-label": "Loading the conversation",
|
|
3056
|
-
style: {
|
|
3057
|
-
maskImage: LOGO_MASK_URL,
|
|
3058
|
-
maskSize: "contain",
|
|
3059
|
-
maskRepeat: "no-repeat",
|
|
3060
|
-
maskPosition: "center",
|
|
3061
|
-
WebkitMaskImage: LOGO_MASK_URL,
|
|
3062
|
-
WebkitMaskSize: "contain",
|
|
3063
|
-
WebkitMaskRepeat: "no-repeat",
|
|
3064
|
-
WebkitMaskPosition: "center",
|
|
3065
|
-
backgroundImage: "linear-gradient(115deg, var(--muted) 34%, var(--muted-foreground) 50%, var(--muted) 66%)",
|
|
3066
|
-
backgroundSize: "300% 100%"
|
|
3067
|
-
},
|
|
3068
|
-
className: "size-12 animate-shimmer motion-reduce:animate-none motion-reduce:bg-muted"
|
|
3069
|
-
}
|
|
3070
|
-
) });
|
|
3106
|
+
return /* @__PURE__ */ jsx18("div", { className: "grid min-h-0 flex-1 place-items-center p-6", children: /* @__PURE__ */ jsx18(ShimmerLogo, { label: "Loading the conversation" }) });
|
|
3071
3107
|
}
|
|
3072
3108
|
|
|
3073
3109
|
// ../../apps/web/src/components/support-widget/widget-locked.tsx
|
|
3074
|
-
import { jsx as
|
|
3110
|
+
import { jsx as jsx19, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3075
3111
|
function WidgetLocked({
|
|
3076
3112
|
orgName,
|
|
3077
3113
|
onSignIn,
|
|
@@ -3079,12 +3115,12 @@ function WidgetLocked({
|
|
|
3079
3115
|
}) {
|
|
3080
3116
|
return /* @__PURE__ */ jsxs8("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
3081
3117
|
/* @__PURE__ */ jsxs8("div", { className: "flex min-h-0 flex-1 flex-col items-center justify-center gap-4 px-6 text-center", children: [
|
|
3082
|
-
/* @__PURE__ */
|
|
3118
|
+
/* @__PURE__ */ jsx19("span", { className: "grid size-14 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__ */ jsx19(LockSimple, { className: "size-6 text-muted-foreground" }) }),
|
|
3083
3119
|
/* @__PURE__ */ jsxs8("div", { className: "flex max-w-64 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: [
|
|
3084
|
-
/* @__PURE__ */
|
|
3085
|
-
/* @__PURE__ */
|
|
3120
|
+
/* @__PURE__ */ jsx19("p", { className: "text-base font-semibold tracking-tight", children: "Sign in to chat" }),
|
|
3121
|
+
/* @__PURE__ */ jsx19("p", { className: "text-sm text-balance text-muted-foreground", children: orgName ? `Ask ${orgName} anything once you are signed in.` : "Ask us anything once you are signed in." })
|
|
3086
3122
|
] }),
|
|
3087
|
-
onSignIn && /* @__PURE__ */
|
|
3123
|
+
onSignIn && /* @__PURE__ */ jsx19(
|
|
3088
3124
|
WidgetButton,
|
|
3089
3125
|
{
|
|
3090
3126
|
onClick: onSignIn,
|
|
@@ -3093,12 +3129,12 @@ function WidgetLocked({
|
|
|
3093
3129
|
}
|
|
3094
3130
|
)
|
|
3095
3131
|
] }),
|
|
3096
|
-
showBadge && /* @__PURE__ */
|
|
3132
|
+
showBadge && /* @__PURE__ */ jsx19(PoweredByMedian, { className: "shrink-0 px-3 pb-3" })
|
|
3097
3133
|
] });
|
|
3098
3134
|
}
|
|
3099
3135
|
|
|
3100
3136
|
// ../../apps/web/src/components/ui/badge.tsx
|
|
3101
|
-
import { jsx as
|
|
3137
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
3102
3138
|
var badgeVariants = cva(
|
|
3103
3139
|
"inline-flex w-fit shrink-0 items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium whitespace-nowrap [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3",
|
|
3104
3140
|
{
|
|
@@ -3122,7 +3158,7 @@ function Badge({
|
|
|
3122
3158
|
...props
|
|
3123
3159
|
}) {
|
|
3124
3160
|
const Comp = asChild ? dist_exports.Root : "span";
|
|
3125
|
-
return /* @__PURE__ */
|
|
3161
|
+
return /* @__PURE__ */ jsx20(
|
|
3126
3162
|
Comp,
|
|
3127
3163
|
{
|
|
3128
3164
|
"data-slot": "badge",
|
|
@@ -3135,15 +3171,15 @@ function Badge({
|
|
|
3135
3171
|
|
|
3136
3172
|
// ../../apps/web/src/components/support-widget/widget-attachments.tsx
|
|
3137
3173
|
import { useState as useState7 } from "react";
|
|
3138
|
-
import { Fragment as Fragment24, jsx as
|
|
3174
|
+
import { Fragment as Fragment24, jsx as jsx21, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3139
3175
|
var SURFACE = "rounded-xl border border-foreground/10 bg-card/70";
|
|
3140
3176
|
function OpenAttachment({
|
|
3141
3177
|
attachment,
|
|
3142
3178
|
className,
|
|
3143
3179
|
children
|
|
3144
3180
|
}) {
|
|
3145
|
-
if (!attachment.url) return /* @__PURE__ */
|
|
3146
|
-
return /* @__PURE__ */
|
|
3181
|
+
if (!attachment.url) return /* @__PURE__ */ jsx21(Fragment24, { children });
|
|
3182
|
+
return /* @__PURE__ */ jsx21(
|
|
3147
3183
|
"a",
|
|
3148
3184
|
{
|
|
3149
3185
|
href: attachment.url,
|
|
@@ -3174,14 +3210,14 @@ function MediaTile({
|
|
|
3174
3210
|
className
|
|
3175
3211
|
),
|
|
3176
3212
|
children: [
|
|
3177
|
-
/* @__PURE__ */
|
|
3178
|
-
/* @__PURE__ */
|
|
3213
|
+
/* @__PURE__ */ jsx21(ImageSquare, { className: "size-5 text-muted-foreground" }),
|
|
3214
|
+
/* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: "Preview unavailable" })
|
|
3179
3215
|
]
|
|
3180
3216
|
}
|
|
3181
3217
|
);
|
|
3182
3218
|
}
|
|
3183
3219
|
return /* @__PURE__ */ jsxs9("figure", { className: cn(SURFACE, "relative overflow-hidden", className), children: [
|
|
3184
|
-
/* @__PURE__ */
|
|
3220
|
+
/* @__PURE__ */ jsx21(
|
|
3185
3221
|
"img",
|
|
3186
3222
|
{
|
|
3187
3223
|
src: attachment.previewUrl,
|
|
@@ -3193,22 +3229,22 @@ function MediaTile({
|
|
|
3193
3229
|
className: "size-full object-cover"
|
|
3194
3230
|
}
|
|
3195
3231
|
),
|
|
3196
|
-
attachment.kind === "video" && /* @__PURE__ */
|
|
3232
|
+
attachment.kind === "video" && /* @__PURE__ */ jsx21(
|
|
3197
3233
|
"span",
|
|
3198
3234
|
{
|
|
3199
3235
|
"aria-hidden": true,
|
|
3200
3236
|
className: "absolute inset-0 grid place-items-center bg-foreground/15",
|
|
3201
|
-
children: /* @__PURE__ */
|
|
3237
|
+
children: /* @__PURE__ */ jsx21("span", { className: "grid size-8 place-items-center rounded-full bg-background/85 shadow-sm", children: /* @__PURE__ */ jsx21(Play, { className: "size-3.5 translate-x-px" }) })
|
|
3202
3238
|
}
|
|
3203
3239
|
)
|
|
3204
3240
|
] });
|
|
3205
3241
|
}
|
|
3206
3242
|
function FileRow({ attachment }) {
|
|
3207
|
-
return /* @__PURE__ */
|
|
3208
|
-
/* @__PURE__ */
|
|
3243
|
+
return /* @__PURE__ */ jsx21(OpenAttachment, { attachment, children: /* @__PURE__ */ jsxs9("div", { className: cn(SURFACE, "flex items-center gap-2 px-2 py-1.5"), children: [
|
|
3244
|
+
/* @__PURE__ */ jsx21(File, { className: "size-4 shrink-0 text-muted-foreground" }),
|
|
3209
3245
|
/* @__PURE__ */ jsxs9("div", { className: "flex min-w-0 flex-1 flex-col text-left", children: [
|
|
3210
|
-
/* @__PURE__ */
|
|
3211
|
-
/* @__PURE__ */
|
|
3246
|
+
/* @__PURE__ */ jsx21("p", { className: "truncate text-xs font-medium", children: attachment.name }),
|
|
3247
|
+
/* @__PURE__ */ jsx21("p", { className: "truncate text-xs text-muted-foreground", children: attachment.size })
|
|
3212
3248
|
] })
|
|
3213
3249
|
] }) });
|
|
3214
3250
|
}
|
|
@@ -3218,22 +3254,22 @@ function WidgetAttachments({
|
|
|
3218
3254
|
const media = attachments.filter((one) => one.kind !== "file");
|
|
3219
3255
|
const files = attachments.filter((one) => one.kind === "file");
|
|
3220
3256
|
return /* @__PURE__ */ jsxs9("div", { className: "flex w-56 max-w-full flex-col gap-1.5", children: [
|
|
3221
|
-
media.length > 0 && /* @__PURE__ */
|
|
3257
|
+
media.length > 0 && /* @__PURE__ */ jsx21("div", { className: cn("grid gap-1.5", media.length > 1 && "grid-cols-2"), children: media.map((attachment) => /* @__PURE__ */ jsx21(
|
|
3222
3258
|
OpenAttachment,
|
|
3223
3259
|
{
|
|
3224
3260
|
attachment,
|
|
3225
3261
|
className: media.length > 1 ? "h-20" : "h-32",
|
|
3226
|
-
children: /* @__PURE__ */
|
|
3262
|
+
children: /* @__PURE__ */ jsx21(MediaTile, { attachment, className: "size-full" })
|
|
3227
3263
|
},
|
|
3228
3264
|
attachment.id
|
|
3229
3265
|
)) }),
|
|
3230
|
-
files.map((attachment) => /* @__PURE__ */
|
|
3266
|
+
files.map((attachment) => /* @__PURE__ */ jsx21(FileRow, { attachment }, attachment.id))
|
|
3231
3267
|
] });
|
|
3232
3268
|
}
|
|
3233
3269
|
|
|
3234
3270
|
// ../../apps/web/src/components/ui/morph-bubble.tsx
|
|
3235
3271
|
import { useLayoutEffect as useLayoutEffect3, useRef as useRef8 } from "react";
|
|
3236
|
-
import { jsx as
|
|
3272
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
3237
3273
|
var MORPH_MS = 260;
|
|
3238
3274
|
var MORPH_EASING = "cubic-bezier(0.22, 1, 0.36, 1)";
|
|
3239
3275
|
var CONTENT_FADE_MS = 140;
|
|
@@ -3302,17 +3338,17 @@ function MorphBubble({
|
|
|
3302
3338
|
reveal.cancel();
|
|
3303
3339
|
});
|
|
3304
3340
|
}, [morphKey]);
|
|
3305
|
-
return /* @__PURE__ */
|
|
3341
|
+
return /* @__PURE__ */ jsx22("div", { ref: box, className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsx22("div", { ref: content, className: contentClassName, children }) });
|
|
3306
3342
|
}
|
|
3307
3343
|
|
|
3308
3344
|
// ../../apps/web/src/components/support-widget/widget-bubble.tsx
|
|
3309
|
-
import { jsx as
|
|
3345
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
3310
3346
|
function WidgetBubble({
|
|
3311
3347
|
morphKey,
|
|
3312
3348
|
className,
|
|
3313
3349
|
children
|
|
3314
3350
|
}) {
|
|
3315
|
-
return /* @__PURE__ */
|
|
3351
|
+
return /* @__PURE__ */ jsx23(
|
|
3316
3352
|
MorphBubble,
|
|
3317
3353
|
{
|
|
3318
3354
|
morphKey,
|
|
@@ -3325,24 +3361,24 @@ function WidgetBubble({
|
|
|
3325
3361
|
|
|
3326
3362
|
// ../../apps/web/src/components/support-widget/widget-message-body.tsx
|
|
3327
3363
|
import { Suspense } from "react";
|
|
3328
|
-
import { jsx as
|
|
3364
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
3329
3365
|
function WidgetMessageBody({
|
|
3330
3366
|
body,
|
|
3331
3367
|
sender
|
|
3332
3368
|
}) {
|
|
3333
3369
|
const isReady = useMarkdownReady();
|
|
3334
|
-
const plain = /* @__PURE__ */
|
|
3370
|
+
const plain = /* @__PURE__ */ jsx24("p", { className: "break-words whitespace-pre-line", children: body });
|
|
3335
3371
|
if (sender === "visitor" || !isReady) return plain;
|
|
3336
|
-
return /* @__PURE__ */
|
|
3372
|
+
return /* @__PURE__ */ jsx24(Suspense, { fallback: plain, children: /* @__PURE__ */ jsx24(MessageMarkdown, { body }) });
|
|
3337
3373
|
}
|
|
3338
3374
|
|
|
3339
3375
|
// ../../apps/web/src/components/support-widget/widget-typing.tsx
|
|
3340
|
-
import { jsx as
|
|
3376
|
+
import { jsx as jsx25, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3341
3377
|
var DOTS = [0, 160, 320];
|
|
3342
3378
|
function WidgetTyping({ label }) {
|
|
3343
3379
|
return /* @__PURE__ */ jsxs10("span", { className: "flex items-center gap-1 py-1.5", children: [
|
|
3344
|
-
/* @__PURE__ */
|
|
3345
|
-
DOTS.map((delay) => /* @__PURE__ */
|
|
3380
|
+
/* @__PURE__ */ jsx25("span", { className: "sr-only", children: label }),
|
|
3381
|
+
DOTS.map((delay) => /* @__PURE__ */ jsx25(
|
|
3346
3382
|
"span",
|
|
3347
3383
|
{
|
|
3348
3384
|
"aria-hidden": true,
|
|
@@ -3355,7 +3391,7 @@ function WidgetTyping({ label }) {
|
|
|
3355
3391
|
}
|
|
3356
3392
|
|
|
3357
3393
|
// ../../apps/web/src/components/support-widget/widget-message.tsx
|
|
3358
|
-
import { Fragment as Fragment25, jsx as
|
|
3394
|
+
import { Fragment as Fragment25, jsx as jsx26, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3359
3395
|
var BUBBLE = "max-w-[80%] rounded-2xl px-3.5 py-2 text-sm";
|
|
3360
3396
|
var VISITOR_BUBBLE = "bg-[color-mix(in_oklch,var(--muted),var(--foreground)_12%)]";
|
|
3361
3397
|
var ARRIVES = "animate-in fade-in-0 slide-in-from-bottom-1 duration-200 ease-out motion-reduce:animate-none";
|
|
@@ -3363,21 +3399,21 @@ function WidgetDivider({ message }) {
|
|
|
3363
3399
|
const label = message.startsConversation ? "New conversation" : message.dayLabel;
|
|
3364
3400
|
if (!label) return null;
|
|
3365
3401
|
return /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-3 py-1", children: [
|
|
3366
|
-
/* @__PURE__ */
|
|
3367
|
-
/* @__PURE__ */
|
|
3368
|
-
/* @__PURE__ */
|
|
3402
|
+
/* @__PURE__ */ jsx26("span", { className: "h-px flex-1 bg-border" }),
|
|
3403
|
+
/* @__PURE__ */ jsx26("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
3404
|
+
/* @__PURE__ */ jsx26("span", { className: "h-px flex-1 bg-border" })
|
|
3369
3405
|
] });
|
|
3370
3406
|
}
|
|
3371
3407
|
function WidgetMessage({
|
|
3372
3408
|
message,
|
|
3373
3409
|
group = LONE_MESSAGE
|
|
3374
3410
|
}) {
|
|
3375
|
-
return message.sender === "visitor" ? /* @__PURE__ */
|
|
3411
|
+
return message.sender === "visitor" ? /* @__PURE__ */ jsx26(VisitorMessage, { message }) : /* @__PURE__ */ jsx26(AgentMessage, { message, group });
|
|
3376
3412
|
}
|
|
3377
3413
|
function BubbleContent({ message }) {
|
|
3378
3414
|
const hasAttachments = (message.attachments?.length ?? 0) > 0;
|
|
3379
3415
|
if (message.pending) {
|
|
3380
|
-
return /* @__PURE__ */
|
|
3416
|
+
return /* @__PURE__ */ jsx26(
|
|
3381
3417
|
WidgetTyping,
|
|
3382
3418
|
{
|
|
3383
3419
|
label: `${message.agent?.name ?? "Support"} is writing a reply`
|
|
@@ -3385,12 +3421,12 @@ function BubbleContent({ message }) {
|
|
|
3385
3421
|
);
|
|
3386
3422
|
}
|
|
3387
3423
|
return /* @__PURE__ */ jsxs11(Fragment25, { children: [
|
|
3388
|
-
hasAttachments && /* @__PURE__ */
|
|
3389
|
-
message.body && /* @__PURE__ */
|
|
3424
|
+
hasAttachments && /* @__PURE__ */ jsx26(WidgetAttachments, { attachments: message.attachments ?? [] }),
|
|
3425
|
+
message.body && /* @__PURE__ */ jsx26(WidgetMessageBody, { body: message.body, sender: message.sender })
|
|
3390
3426
|
] });
|
|
3391
3427
|
}
|
|
3392
3428
|
function VisitorMessage({ message }) {
|
|
3393
|
-
return /* @__PURE__ */
|
|
3429
|
+
return /* @__PURE__ */ jsx26("div", { className: cn("flex justify-end", ARRIVES), children: /* @__PURE__ */ jsx26(WidgetBubble, { morphKey: "settled", className: cn(BUBBLE, VISITOR_BUBBLE), children: /* @__PURE__ */ jsx26(BubbleContent, { message }) }) });
|
|
3394
3430
|
}
|
|
3395
3431
|
function AgentMessage({
|
|
3396
3432
|
message,
|
|
@@ -3406,18 +3442,18 @@ function AgentMessage({
|
|
|
3406
3442
|
/* @__PURE__ */ jsxs11("div", { className: cn("flex flex-col items-start gap-1", ARRIVES), children: [
|
|
3407
3443
|
group.isFirst && /* @__PURE__ */ jsxs11("div", { className: "flex max-w-full items-center gap-1.5 px-0.5", children: [
|
|
3408
3444
|
agent && /* @__PURE__ */ jsxs11(Fragment25, { children: [
|
|
3409
|
-
/* @__PURE__ */
|
|
3410
|
-
/* @__PURE__ */
|
|
3411
|
-
agent.kind === "ai" && /* @__PURE__ */
|
|
3445
|
+
/* @__PURE__ */ jsx26(WidgetAvatar, { agent, className: "size-5 rounded-md" }),
|
|
3446
|
+
/* @__PURE__ */ jsx26("span", { className: "truncate text-xs font-medium", children: agent.name }),
|
|
3447
|
+
agent.kind === "ai" && /* @__PURE__ */ jsx26(Badge, { variant: "muted", className: "shrink-0 rounded-md px-1", children: "AI" })
|
|
3412
3448
|
] }),
|
|
3413
|
-
!message.pending && /* @__PURE__ */
|
|
3449
|
+
!message.pending && /* @__PURE__ */ jsx26("span", { className: "shrink-0 text-xs text-muted-foreground tabular-nums", children: message.time })
|
|
3414
3450
|
] }),
|
|
3415
|
-
/* @__PURE__ */
|
|
3451
|
+
/* @__PURE__ */ jsx26(
|
|
3416
3452
|
WidgetBubble,
|
|
3417
3453
|
{
|
|
3418
3454
|
morphKey: message.pending ? "pending" : `${message.body.length}:${message.attachments?.length ?? 0}`,
|
|
3419
3455
|
className: cn(BUBBLE, "bg-muted"),
|
|
3420
|
-
children: /* @__PURE__ */
|
|
3456
|
+
children: /* @__PURE__ */ jsx26(BubbleContent, { message })
|
|
3421
3457
|
}
|
|
3422
3458
|
)
|
|
3423
3459
|
] })
|
|
@@ -3428,7 +3464,7 @@ function AgentMessage({
|
|
|
3428
3464
|
import { useEffect as useEffect7, useRef as useRef9, useState as useState8 } from "react";
|
|
3429
3465
|
|
|
3430
3466
|
// ../../apps/web/src/components/ui/collapse.tsx
|
|
3431
|
-
import { jsx as
|
|
3467
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
3432
3468
|
var COLLAPSE_MS = 200;
|
|
3433
3469
|
function Collapse({
|
|
3434
3470
|
isOpen,
|
|
@@ -3436,7 +3472,7 @@ function Collapse({
|
|
|
3436
3472
|
children,
|
|
3437
3473
|
className
|
|
3438
3474
|
}) {
|
|
3439
|
-
return /* @__PURE__ */
|
|
3475
|
+
return /* @__PURE__ */ jsx27(
|
|
3440
3476
|
"div",
|
|
3441
3477
|
{
|
|
3442
3478
|
id,
|
|
@@ -3446,13 +3482,13 @@ function Collapse({
|
|
|
3446
3482
|
isOpen ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0",
|
|
3447
3483
|
className
|
|
3448
3484
|
),
|
|
3449
|
-
children: /* @__PURE__ */
|
|
3485
|
+
children: /* @__PURE__ */ jsx27("div", { className: "overflow-hidden", children })
|
|
3450
3486
|
}
|
|
3451
3487
|
);
|
|
3452
3488
|
}
|
|
3453
3489
|
|
|
3454
3490
|
// ../../apps/web/src/components/support-widget/widget-rating.tsx
|
|
3455
|
-
import { jsx as
|
|
3491
|
+
import { jsx as jsx28, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3456
3492
|
var STARS = Array.from({ length: RATING_MAX_STARS }, (_, index) => index + 1);
|
|
3457
3493
|
var THANKS_MS = 1400;
|
|
3458
3494
|
var STAR_STAGGER_MS = 40;
|
|
@@ -3506,11 +3542,11 @@ function WidgetRating({ rating }) {
|
|
|
3506
3542
|
setIsDone(true);
|
|
3507
3543
|
later(THANKS_MS, leave);
|
|
3508
3544
|
}
|
|
3509
|
-
return /* @__PURE__ */
|
|
3510
|
-
/* @__PURE__ */
|
|
3545
|
+
return /* @__PURE__ */ jsx28(Collapse, { isOpen, className: "shrink-0", children: /* @__PURE__ */ jsxs12("div", { className: "mx-3 mb-2 rounded-xl border bg-muted/40 px-3 dark:bg-muted/20", children: [
|
|
3546
|
+
/* @__PURE__ */ jsx28(Collapse, { isOpen: !isDone, children: /* @__PURE__ */ jsxs12("div", { className: "py-2.5", children: [
|
|
3511
3547
|
/* @__PURE__ */ jsxs12("div", { className: "flex items-start justify-between gap-2", children: [
|
|
3512
|
-
/* @__PURE__ */
|
|
3513
|
-
/* @__PURE__ */
|
|
3548
|
+
/* @__PURE__ */ jsx28("p", { className: "text-sm font-medium", children: picked === null ? "How did we do?" : "Thanks. Tell us more?" }),
|
|
3549
|
+
/* @__PURE__ */ jsx28(
|
|
3514
3550
|
WidgetButton,
|
|
3515
3551
|
{
|
|
3516
3552
|
type: "button",
|
|
@@ -3523,14 +3559,14 @@ function WidgetRating({ rating }) {
|
|
|
3523
3559
|
}
|
|
3524
3560
|
)
|
|
3525
3561
|
] }),
|
|
3526
|
-
/* @__PURE__ */
|
|
3562
|
+
/* @__PURE__ */ jsx28(
|
|
3527
3563
|
"div",
|
|
3528
3564
|
{
|
|
3529
3565
|
role: "radiogroup",
|
|
3530
3566
|
"aria-label": "How did we do?",
|
|
3531
3567
|
className: "flex items-center justify-center gap-1 pt-1.5",
|
|
3532
3568
|
onMouseLeave: () => setHovered(null),
|
|
3533
|
-
children: STARS.map((value) => /* @__PURE__ */
|
|
3569
|
+
children: STARS.map((value) => /* @__PURE__ */ jsx28(
|
|
3534
3570
|
"button",
|
|
3535
3571
|
{
|
|
3536
3572
|
type: "button",
|
|
@@ -3548,7 +3584,7 @@ function WidgetRating({ rating }) {
|
|
|
3548
3584
|
"active:scale-95 disabled:pointer-events-none",
|
|
3549
3585
|
"motion-reduce:transition-none"
|
|
3550
3586
|
),
|
|
3551
|
-
children: /* @__PURE__ */
|
|
3587
|
+
children: /* @__PURE__ */ jsx28(
|
|
3552
3588
|
Star,
|
|
3553
3589
|
{
|
|
3554
3590
|
style: {
|
|
@@ -3565,8 +3601,8 @@ function WidgetRating({ rating }) {
|
|
|
3565
3601
|
))
|
|
3566
3602
|
}
|
|
3567
3603
|
),
|
|
3568
|
-
/* @__PURE__ */
|
|
3569
|
-
/* @__PURE__ */
|
|
3604
|
+
/* @__PURE__ */ jsx28(Collapse, { isOpen: picked !== null, children: /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-2 pt-2", children: [
|
|
3605
|
+
/* @__PURE__ */ jsx28(
|
|
3570
3606
|
Textarea,
|
|
3571
3607
|
{
|
|
3572
3608
|
value: feedback,
|
|
@@ -3582,7 +3618,7 @@ function WidgetRating({ rating }) {
|
|
|
3582
3618
|
)
|
|
3583
3619
|
}
|
|
3584
3620
|
),
|
|
3585
|
-
/* @__PURE__ */
|
|
3621
|
+
/* @__PURE__ */ jsx28(
|
|
3586
3622
|
WidgetButton,
|
|
3587
3623
|
{
|
|
3588
3624
|
type: "button",
|
|
@@ -3594,23 +3630,23 @@ function WidgetRating({ rating }) {
|
|
|
3594
3630
|
}
|
|
3595
3631
|
)
|
|
3596
3632
|
] }) }),
|
|
3597
|
-
/* @__PURE__ */
|
|
3633
|
+
/* @__PURE__ */ jsx28(Collapse, { isOpen: error !== null, children: /* @__PURE__ */ jsx28("p", { className: "pt-1.5 text-center text-xs text-destructive", children: error }) })
|
|
3598
3634
|
] }) }),
|
|
3599
|
-
/* @__PURE__ */
|
|
3635
|
+
/* @__PURE__ */ jsx28(Collapse, { isOpen: isDone, children: /* @__PURE__ */ jsx28("p", { className: "py-3 text-center text-sm font-medium", children: "Thanks for the feedback." }) })
|
|
3600
3636
|
] }) });
|
|
3601
3637
|
}
|
|
3602
3638
|
|
|
3603
3639
|
// ../../apps/web/src/components/support-widget/widget-status.tsx
|
|
3604
|
-
import { jsx as
|
|
3640
|
+
import { jsx as jsx29, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3605
3641
|
function WidgetAwaitingHuman() {
|
|
3606
3642
|
return /* @__PURE__ */ jsxs13("p", { className: "flex animate-in items-center justify-center gap-1.5 px-4 pb-1 text-xs text-muted-foreground duration-200 ease-out fade-in-0 slide-in-from-bottom-1 motion-reduce:animate-none", children: [
|
|
3607
|
-
/* @__PURE__ */
|
|
3643
|
+
/* @__PURE__ */ jsx29(UserCircle, { "aria-hidden": true, className: "size-3.5" }),
|
|
3608
3644
|
"Waiting for a teammate"
|
|
3609
3645
|
] });
|
|
3610
3646
|
}
|
|
3611
3647
|
|
|
3612
3648
|
// ../../apps/web/src/components/support-widget/support-widget.tsx
|
|
3613
|
-
import { jsx as
|
|
3649
|
+
import { jsx as jsx30, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3614
3650
|
function joinsPreviousTurn(message, previous) {
|
|
3615
3651
|
return !message.dayLabel && !message.startsConversation && message.sender === previous.sender && message.agent?.id === previous.agent?.id && withinRun(previous.sentAt, message.sentAt);
|
|
3616
3652
|
}
|
|
@@ -3649,7 +3685,7 @@ function SupportWidget({
|
|
|
3649
3685
|
className
|
|
3650
3686
|
),
|
|
3651
3687
|
children: [
|
|
3652
|
-
/* @__PURE__ */
|
|
3688
|
+
/* @__PURE__ */ jsx30(
|
|
3653
3689
|
WidgetHeader,
|
|
3654
3690
|
{
|
|
3655
3691
|
presence,
|
|
@@ -3660,10 +3696,10 @@ function SupportWidget({
|
|
|
3660
3696
|
isMoving
|
|
3661
3697
|
}
|
|
3662
3698
|
),
|
|
3663
|
-
isLoading ? /* @__PURE__ */
|
|
3699
|
+
isLoading ? /* @__PURE__ */ jsx30(WidgetLoading, {}) : isLocked ? (
|
|
3664
3700
|
/* After the loading rather than before it: the line names the host,
|
|
3665
3701
|
so it waits for the name the same as everything else does. */
|
|
3666
|
-
/* @__PURE__ */
|
|
3702
|
+
/* @__PURE__ */ jsx30(
|
|
3667
3703
|
WidgetLocked,
|
|
3668
3704
|
{
|
|
3669
3705
|
orgName: presence.name,
|
|
@@ -3671,7 +3707,7 @@ function SupportWidget({
|
|
|
3671
3707
|
showBadge
|
|
3672
3708
|
}
|
|
3673
3709
|
)
|
|
3674
|
-
) : /* @__PURE__ */
|
|
3710
|
+
) : /* @__PURE__ */ jsx30(
|
|
3675
3711
|
Conversation,
|
|
3676
3712
|
{
|
|
3677
3713
|
presence,
|
|
@@ -3708,7 +3744,7 @@ function Conversation({
|
|
|
3708
3744
|
}) {
|
|
3709
3745
|
const groups = groupMessages(messages, joinsPreviousTurn);
|
|
3710
3746
|
return /* @__PURE__ */ jsxs14("div", { className: "flex min-h-0 flex-1 flex-col animate-in fade-in-0 duration-500 ease-out motion-reduce:animate-none", children: [
|
|
3711
|
-
messages.length === 0 ? /* @__PURE__ */
|
|
3747
|
+
messages.length === 0 ? /* @__PURE__ */ jsx30(
|
|
3712
3748
|
WidgetEmpty,
|
|
3713
3749
|
{
|
|
3714
3750
|
team: presence.team,
|
|
@@ -3727,8 +3763,8 @@ function Conversation({
|
|
|
3727
3763
|
so a scroller left alone slides the newest message under the
|
|
3728
3764
|
composer and has to catch up afterwards. Following it is what the
|
|
3729
3765
|
scroller stops easing for, so this tracks frame by frame. */
|
|
3730
|
-
/* @__PURE__ */
|
|
3731
|
-
/* @__PURE__ */
|
|
3766
|
+
/* @__PURE__ */ jsx30(MessageScrollerProvider, { children: /* @__PURE__ */ jsxs14(MessageScroller, { className: "h-auto min-h-0 flex-1", children: [
|
|
3767
|
+
/* @__PURE__ */ jsx30(
|
|
3732
3768
|
MessageScrollerViewport,
|
|
3733
3769
|
{
|
|
3734
3770
|
role: "log",
|
|
@@ -3736,7 +3772,7 @@ function Conversation({
|
|
|
3736
3772
|
"aria-relevant": "additions",
|
|
3737
3773
|
"aria-label": "Conversation",
|
|
3738
3774
|
className: "px-3 py-2",
|
|
3739
|
-
children: /* @__PURE__ */
|
|
3775
|
+
children: /* @__PURE__ */ jsx30(
|
|
3740
3776
|
MessageScrollerContent,
|
|
3741
3777
|
{
|
|
3742
3778
|
ref: stackRef,
|
|
@@ -3750,8 +3786,8 @@ function Conversation({
|
|
|
3750
3786
|
groups[index].isFirst ? "pt-4" : "pt-1"
|
|
3751
3787
|
),
|
|
3752
3788
|
children: [
|
|
3753
|
-
/* @__PURE__ */
|
|
3754
|
-
/* @__PURE__ */
|
|
3789
|
+
/* @__PURE__ */ jsx30(WidgetDivider, { message }),
|
|
3790
|
+
/* @__PURE__ */ jsx30(WidgetMessage, { message, group: groups[index] })
|
|
3755
3791
|
]
|
|
3756
3792
|
},
|
|
3757
3793
|
message.id
|
|
@@ -3760,13 +3796,13 @@ function Conversation({
|
|
|
3760
3796
|
)
|
|
3761
3797
|
}
|
|
3762
3798
|
),
|
|
3763
|
-
/* @__PURE__ */
|
|
3799
|
+
/* @__PURE__ */ jsx30(MessageScrollerButton, {})
|
|
3764
3800
|
] }) })
|
|
3765
3801
|
),
|
|
3766
|
-
rating && /* @__PURE__ */
|
|
3767
|
-
awaitingHuman && /* @__PURE__ */
|
|
3768
|
-
notice && /* @__PURE__ */
|
|
3769
|
-
/* @__PURE__ */
|
|
3802
|
+
rating && /* @__PURE__ */ jsx30(WidgetRating, { rating }),
|
|
3803
|
+
awaitingHuman && /* @__PURE__ */ jsx30(WidgetAwaitingHuman, {}),
|
|
3804
|
+
notice && /* @__PURE__ */ jsx30("p", { className: "animate-in px-4 pb-1 text-center text-xs text-destructive fade-in duration-150", children: notice }),
|
|
3805
|
+
/* @__PURE__ */ jsx30(
|
|
3770
3806
|
WidgetComposer,
|
|
3771
3807
|
{
|
|
3772
3808
|
onSend,
|
|
@@ -4047,10 +4083,33 @@ function clamp2(value, low, high) {
|
|
|
4047
4083
|
return Math.min(Math.max(value, low), Math.max(low, high));
|
|
4048
4084
|
}
|
|
4049
4085
|
|
|
4086
|
+
// ../../apps/web/src/components/support-widget/use-teaser-placement.ts
|
|
4087
|
+
import { useLayoutEffect as useLayoutEffect5, useState as useState10 } from "react";
|
|
4088
|
+
var ROOM_ABOVE_PX = 128;
|
|
4089
|
+
function useTeaserPlacement({
|
|
4090
|
+
buttonRef,
|
|
4091
|
+
enabled: enabled2,
|
|
4092
|
+
isMoving
|
|
4093
|
+
}) {
|
|
4094
|
+
const [placement, setPlacement] = useState10("above");
|
|
4095
|
+
useLayoutEffect5(() => {
|
|
4096
|
+
if (!enabled2 || isMoving) return;
|
|
4097
|
+
const measure = () => {
|
|
4098
|
+
const button = buttonRef.current;
|
|
4099
|
+
if (button === null) return;
|
|
4100
|
+
setPlacement(button.offsetTop < ROOM_ABOVE_PX ? "below" : "above");
|
|
4101
|
+
};
|
|
4102
|
+
measure();
|
|
4103
|
+
window.addEventListener("resize", measure);
|
|
4104
|
+
return () => window.removeEventListener("resize", measure);
|
|
4105
|
+
}, [buttonRef, enabled2, isMoving]);
|
|
4106
|
+
return placement;
|
|
4107
|
+
}
|
|
4108
|
+
|
|
4050
4109
|
// ../../apps/web/src/components/support-widget/use-widget-sheet.ts
|
|
4051
4110
|
import {
|
|
4052
|
-
useLayoutEffect as
|
|
4053
|
-
useState as
|
|
4111
|
+
useLayoutEffect as useLayoutEffect6,
|
|
4112
|
+
useState as useState11,
|
|
4054
4113
|
useSyncExternalStore as useSyncExternalStore4
|
|
4055
4114
|
} from "react";
|
|
4056
4115
|
|
|
@@ -4105,13 +4164,13 @@ function useWidgetSheet({
|
|
|
4105
4164
|
isPhoneNow,
|
|
4106
4165
|
isPhoneOnServer
|
|
4107
4166
|
);
|
|
4108
|
-
const [isFramed, setIsFramed] =
|
|
4109
|
-
|
|
4167
|
+
const [isFramed, setIsFramed] = useState11(false);
|
|
4168
|
+
useLayoutEffect6(() => {
|
|
4110
4169
|
setIsFramed(boxRef.current?.offsetParent != null);
|
|
4111
4170
|
}, [boxRef, isPhone]);
|
|
4112
4171
|
const isSheet = isPhone && !isFramed;
|
|
4113
4172
|
const isUp = isSheet && isOpen;
|
|
4114
|
-
|
|
4173
|
+
useLayoutEffect6(() => {
|
|
4115
4174
|
if (!isUp) return;
|
|
4116
4175
|
const panel = panelRef.current;
|
|
4117
4176
|
const viewport = window.visualViewport;
|
|
@@ -4162,8 +4221,109 @@ function useWidgetSheet({
|
|
|
4162
4221
|
return isSheet;
|
|
4163
4222
|
}
|
|
4164
4223
|
|
|
4224
|
+
// ../../apps/web/src/components/support-widget/widget-teaser.tsx
|
|
4225
|
+
import { useState as useState12 } from "react";
|
|
4226
|
+
|
|
4227
|
+
// ../../apps/web/src/components/support-widget/plain-text.ts
|
|
4228
|
+
function plainTextOf(markdown) {
|
|
4229
|
+
return markdown.replace(/^\s*(?:```|~~~).*$/gm, "").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/[*`_~]/g, "").replace(/^\s*#{1,6}\s+/gm, "").replace(/^\s*[-+]\s+/gm, "").replace(/^\s*>\s?/gm, "").replace(/\s+/g, " ").trim();
|
|
4230
|
+
}
|
|
4231
|
+
|
|
4232
|
+
// ../../apps/web/src/components/support-widget/widget-teaser.tsx
|
|
4233
|
+
import { Fragment as Fragment26, jsx as jsx31, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4234
|
+
var WIDTH = "min(18rem, 100%)";
|
|
4235
|
+
var GAP = "0.5rem";
|
|
4236
|
+
function WidgetTeaser({
|
|
4237
|
+
message,
|
|
4238
|
+
isShown,
|
|
4239
|
+
side,
|
|
4240
|
+
placement,
|
|
4241
|
+
buttonY: buttonY2,
|
|
4242
|
+
buttonSize,
|
|
4243
|
+
onOpen,
|
|
4244
|
+
onDismiss
|
|
4245
|
+
}) {
|
|
4246
|
+
const [held, setHeld] = useState12(message);
|
|
4247
|
+
if (message !== null && message !== held) setHeld(message);
|
|
4248
|
+
const shown = message ?? held;
|
|
4249
|
+
if (shown === null) return null;
|
|
4250
|
+
const agent = shown.agent;
|
|
4251
|
+
const text = plainTextOf(shown.body);
|
|
4252
|
+
return /* @__PURE__ */ jsxs15(
|
|
4253
|
+
"div",
|
|
4254
|
+
{
|
|
4255
|
+
inert: !isShown,
|
|
4256
|
+
role: "status",
|
|
4257
|
+
"aria-live": "polite",
|
|
4258
|
+
style: {
|
|
4259
|
+
width: WIDTH,
|
|
4260
|
+
[side]: 0,
|
|
4261
|
+
...placement === "above" ? { bottom: `calc(100% - ${buttonY2} + ${GAP})` } : { top: `calc(${buttonY2} + ${buttonSize} + ${GAP})` }
|
|
4262
|
+
},
|
|
4263
|
+
className: cn(
|
|
4264
|
+
"absolute",
|
|
4265
|
+
// Grows out of the corner nearest the button, so it reads as coming
|
|
4266
|
+
// from it rather than landing beside it.
|
|
4267
|
+
placement === "above" ? side === "right" ? "origin-bottom-right" : "origin-bottom-left" : side === "right" ? "origin-top-right" : "origin-top-left",
|
|
4268
|
+
"transition-[opacity,translate,scale] motion-reduce:transition-none",
|
|
4269
|
+
isShown ? [
|
|
4270
|
+
"pointer-events-auto opacity-100 duration-300 ease-spring",
|
|
4271
|
+
// The arrival, once. The transition above takes over after.
|
|
4272
|
+
"animate-in fade-in-0 zoom-in-95 duration-300 ease-spring motion-reduce:animate-none",
|
|
4273
|
+
placement === "above" ? "slide-in-from-bottom-2" : "slide-in-from-top-2"
|
|
4274
|
+
] : "pointer-events-none scale-95 opacity-0 duration-150 ease-out-quint"
|
|
4275
|
+
),
|
|
4276
|
+
children: [
|
|
4277
|
+
/* @__PURE__ */ jsxs15(
|
|
4278
|
+
"button",
|
|
4279
|
+
{
|
|
4280
|
+
type: "button",
|
|
4281
|
+
onClick: onOpen,
|
|
4282
|
+
"aria-label": agent ? `Read the reply from ${agent.name}` : "Read the reply",
|
|
4283
|
+
className: cn(
|
|
4284
|
+
// Its own radius scale, like the panel, so the app's token cannot
|
|
4285
|
+
// reshape a card that sits on somebody else's site.
|
|
4286
|
+
"block w-full rounded-xl border bg-card p-3 pr-9 text-left text-card-foreground shadow-lg [--radius:0.625rem]",
|
|
4287
|
+
"transition-[background-color,box-shadow] outline-none",
|
|
4288
|
+
"hover:bg-muted/50 focus-visible:ring-3 focus-visible:ring-ring/50",
|
|
4289
|
+
"cursor-pointer select-none"
|
|
4290
|
+
),
|
|
4291
|
+
children: [
|
|
4292
|
+
/* @__PURE__ */ jsxs15("span", { className: "flex items-center gap-1.5", children: [
|
|
4293
|
+
agent && /* @__PURE__ */ jsxs15(Fragment26, { children: [
|
|
4294
|
+
/* @__PURE__ */ jsx31(WidgetAvatar, { agent, className: "size-5 rounded-md" }),
|
|
4295
|
+
/* @__PURE__ */ jsx31("span", { className: "truncate text-xs font-medium", children: agent.name }),
|
|
4296
|
+
agent.kind === "ai" && /* @__PURE__ */ jsx31(Badge, { variant: "muted", className: "shrink-0 rounded-md px-1", children: "AI" })
|
|
4297
|
+
] }),
|
|
4298
|
+
/* @__PURE__ */ jsx31("span", { className: "ml-auto shrink-0 text-xs text-muted-foreground tabular-nums", children: shown.time })
|
|
4299
|
+
] }),
|
|
4300
|
+
/* @__PURE__ */ jsx31("span", { className: "mt-1 line-clamp-2 block text-sm leading-snug", children: text.length > 0 ? text : "Sent a file" })
|
|
4301
|
+
]
|
|
4302
|
+
}
|
|
4303
|
+
),
|
|
4304
|
+
/* @__PURE__ */ jsx31(
|
|
4305
|
+
"button",
|
|
4306
|
+
{
|
|
4307
|
+
type: "button",
|
|
4308
|
+
onClick: onDismiss,
|
|
4309
|
+
"aria-label": "Dismiss",
|
|
4310
|
+
className: cn(
|
|
4311
|
+
"absolute top-2 right-2 grid size-6 place-items-center rounded-md",
|
|
4312
|
+
"text-muted-foreground transition-colors outline-none",
|
|
4313
|
+
"hover:bg-muted hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50",
|
|
4314
|
+
"cursor-pointer"
|
|
4315
|
+
),
|
|
4316
|
+
children: /* @__PURE__ */ jsx31(X, { className: "size-3.5" })
|
|
4317
|
+
}
|
|
4318
|
+
)
|
|
4319
|
+
]
|
|
4320
|
+
},
|
|
4321
|
+
shown.id
|
|
4322
|
+
);
|
|
4323
|
+
}
|
|
4324
|
+
|
|
4165
4325
|
// ../../apps/web/src/components/support-widget/widget-launcher.tsx
|
|
4166
|
-
import { jsx as
|
|
4326
|
+
import { jsx as jsx32, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4167
4327
|
var DEFAULT_WIDTH = "24rem";
|
|
4168
4328
|
var DEFAULT_HEIGHT = "34rem";
|
|
4169
4329
|
var DEFAULT_BUTTON_SIZE = "3.5rem";
|
|
@@ -4207,6 +4367,8 @@ function SupportLauncher({
|
|
|
4207
4367
|
awaitingHuman = false,
|
|
4208
4368
|
rating,
|
|
4209
4369
|
unreadCount = 0,
|
|
4370
|
+
teaser = null,
|
|
4371
|
+
onDismissTeaser,
|
|
4210
4372
|
notice,
|
|
4211
4373
|
showBadge = true,
|
|
4212
4374
|
width = DEFAULT_WIDTH,
|
|
@@ -4220,10 +4382,10 @@ function SupportLauncher({
|
|
|
4220
4382
|
onOpenChange,
|
|
4221
4383
|
className
|
|
4222
4384
|
}) {
|
|
4223
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
4385
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState13(defaultOpen);
|
|
4224
4386
|
const isOpen = open ?? uncontrolledOpen;
|
|
4225
4387
|
const hasBubble = launcher === "bubble";
|
|
4226
|
-
const [isExpanded, setExpanded] =
|
|
4388
|
+
const [isExpanded, setExpanded] = useState13(false);
|
|
4227
4389
|
const launcherRef = useRef11(null);
|
|
4228
4390
|
const panelRef = useRef11(null);
|
|
4229
4391
|
const boxRef = useRef11(null);
|
|
@@ -4235,6 +4397,12 @@ function SupportLauncher({
|
|
|
4235
4397
|
subject: isOpen ? "panel" : "button"
|
|
4236
4398
|
});
|
|
4237
4399
|
const isSheet = useWidgetSheet({ boxRef, panelRef, isOpen });
|
|
4400
|
+
const hasTeaser = teaser !== null && hasBubble;
|
|
4401
|
+
const teaserPlacement = useTeaserPlacement({
|
|
4402
|
+
buttonRef: launcherRef,
|
|
4403
|
+
enabled: hasTeaser,
|
|
4404
|
+
isMoving: drag.isMoving
|
|
4405
|
+
});
|
|
4238
4406
|
const opener = useRef11(null);
|
|
4239
4407
|
const wasOpen = useRef11(isOpen);
|
|
4240
4408
|
const setOpen = useCallback7(
|
|
@@ -4273,7 +4441,7 @@ function SupportLauncher({
|
|
|
4273
4441
|
// The box is panel sized whether it is open or not, so it never lets a
|
|
4274
4442
|
// click through to the host's page. Only what is actually on screen takes
|
|
4275
4443
|
// pointer events back.
|
|
4276
|
-
/* @__PURE__ */
|
|
4444
|
+
/* @__PURE__ */ jsxs16(
|
|
4277
4445
|
"div",
|
|
4278
4446
|
{
|
|
4279
4447
|
ref: boxRef,
|
|
@@ -4308,7 +4476,7 @@ function SupportLauncher({
|
|
|
4308
4476
|
className
|
|
4309
4477
|
),
|
|
4310
4478
|
children: [
|
|
4311
|
-
!isSheet && /* @__PURE__ */
|
|
4479
|
+
!isSheet && /* @__PURE__ */ jsx32("div", { "aria-hidden": true, className: "absolute inset-0 drop-shadow-xl", children: /* @__PURE__ */ jsx32(
|
|
4312
4480
|
"div",
|
|
4313
4481
|
{
|
|
4314
4482
|
style: shape(isOpen, buttonSize, drag.side, hasBubble),
|
|
@@ -4319,7 +4487,7 @@ function SupportLauncher({
|
|
|
4319
4487
|
)
|
|
4320
4488
|
}
|
|
4321
4489
|
) }),
|
|
4322
|
-
/* @__PURE__ */
|
|
4490
|
+
/* @__PURE__ */ jsx32(
|
|
4323
4491
|
"div",
|
|
4324
4492
|
{
|
|
4325
4493
|
ref: panelRef,
|
|
@@ -4338,7 +4506,7 @@ function SupportLauncher({
|
|
|
4338
4506
|
],
|
|
4339
4507
|
isOpen && "pointer-events-auto"
|
|
4340
4508
|
),
|
|
4341
|
-
children: /* @__PURE__ */
|
|
4509
|
+
children: /* @__PURE__ */ jsx32(
|
|
4342
4510
|
SupportWidget,
|
|
4343
4511
|
{
|
|
4344
4512
|
presence,
|
|
@@ -4365,7 +4533,7 @@ function SupportLauncher({
|
|
|
4365
4533
|
)
|
|
4366
4534
|
}
|
|
4367
4535
|
),
|
|
4368
|
-
hasBubble && /* @__PURE__ */
|
|
4536
|
+
hasBubble && /* @__PURE__ */ jsxs16(
|
|
4369
4537
|
"button",
|
|
4370
4538
|
{
|
|
4371
4539
|
ref: launcherRef,
|
|
@@ -4433,8 +4601,8 @@ function SupportLauncher({
|
|
|
4433
4601
|
!isOpen && (drag.isMoving ? "cursor-grabbing" : "cursor-pointer active:scale-95")
|
|
4434
4602
|
),
|
|
4435
4603
|
children: [
|
|
4436
|
-
/* @__PURE__ */
|
|
4437
|
-
unreadCount > 0 && /* @__PURE__ */
|
|
4604
|
+
/* @__PURE__ */ jsx32(ChatCircleDots, { className: "size-6" }),
|
|
4605
|
+
unreadCount > 0 && /* @__PURE__ */ jsx32(
|
|
4438
4606
|
"span",
|
|
4439
4607
|
{
|
|
4440
4608
|
"aria-hidden": true,
|
|
@@ -4449,6 +4617,19 @@ function SupportLauncher({
|
|
|
4449
4617
|
)
|
|
4450
4618
|
]
|
|
4451
4619
|
}
|
|
4620
|
+
),
|
|
4621
|
+
hasBubble && /* @__PURE__ */ jsx32(
|
|
4622
|
+
WidgetTeaser,
|
|
4623
|
+
{
|
|
4624
|
+
message: teaser,
|
|
4625
|
+
isShown: hasTeaser && !isOpen,
|
|
4626
|
+
side: drag.side,
|
|
4627
|
+
placement: teaserPlacement,
|
|
4628
|
+
buttonY: buttonY(buttonSize),
|
|
4629
|
+
buttonSize,
|
|
4630
|
+
onOpen: () => setOpen(true),
|
|
4631
|
+
onDismiss: () => onDismissTeaser?.()
|
|
4632
|
+
}
|
|
4452
4633
|
)
|
|
4453
4634
|
]
|
|
4454
4635
|
}
|
|
@@ -4457,9 +4638,9 @@ function SupportLauncher({
|
|
|
4457
4638
|
}
|
|
4458
4639
|
|
|
4459
4640
|
// ../../apps/web/src/components/support-widget/widget-spotlight.tsx
|
|
4460
|
-
import { useEffect as useEffect11, useRef as useRef12, useState as
|
|
4641
|
+
import { useEffect as useEffect11, useRef as useRef12, useState as useState14 } from "react";
|
|
4461
4642
|
import { createPortal } from "react-dom";
|
|
4462
|
-
import { jsx as
|
|
4643
|
+
import { jsx as jsx33, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
4463
4644
|
var FIND_TIMEOUT_MS = 4e3;
|
|
4464
4645
|
var HOLD_MS = 2600;
|
|
4465
4646
|
var FADE_MS = 300;
|
|
@@ -4468,8 +4649,8 @@ function prefersReducedMotion3() {
|
|
|
4468
4649
|
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
4469
4650
|
}
|
|
4470
4651
|
function WidgetSpotlight({ selector }) {
|
|
4471
|
-
const [isShown, setIsShown] =
|
|
4472
|
-
const [isLeaving, setIsLeaving] =
|
|
4652
|
+
const [isShown, setIsShown] = useState14(false);
|
|
4653
|
+
const [isLeaving, setIsLeaving] = useState14(false);
|
|
4473
4654
|
const ring = useRef12(null);
|
|
4474
4655
|
useEffect11(() => {
|
|
4475
4656
|
let target = null;
|
|
@@ -4530,7 +4711,7 @@ function WidgetSpotlight({ selector }) {
|
|
|
4530
4711
|
}, [selector]);
|
|
4531
4712
|
if (!isShown || typeof document === "undefined") return null;
|
|
4532
4713
|
return createPortal(
|
|
4533
|
-
/* @__PURE__ */
|
|
4714
|
+
/* @__PURE__ */ jsxs17(
|
|
4534
4715
|
"div",
|
|
4535
4716
|
{
|
|
4536
4717
|
ref: ring,
|
|
@@ -4539,7 +4720,7 @@ function WidgetSpotlight({ selector }) {
|
|
|
4539
4720
|
style: { zIndex: LAYER, top: 0, left: 0 },
|
|
4540
4721
|
className: "pointer-events-none fixed",
|
|
4541
4722
|
children: [
|
|
4542
|
-
/* @__PURE__ */
|
|
4723
|
+
/* @__PURE__ */ jsx33(
|
|
4543
4724
|
"span",
|
|
4544
4725
|
{
|
|
4545
4726
|
className: [
|
|
@@ -4550,7 +4731,7 @@ function WidgetSpotlight({ selector }) {
|
|
|
4550
4731
|
].join(" ")
|
|
4551
4732
|
}
|
|
4552
4733
|
),
|
|
4553
|
-
/* @__PURE__ */
|
|
4734
|
+
/* @__PURE__ */ jsx33(
|
|
4554
4735
|
"span",
|
|
4555
4736
|
{
|
|
4556
4737
|
className: [
|
|
@@ -4568,9 +4749,9 @@ function WidgetSpotlight({ selector }) {
|
|
|
4568
4749
|
}
|
|
4569
4750
|
|
|
4570
4751
|
// ../../apps/web/src/components/support-widget/widget-toast.tsx
|
|
4571
|
-
import { useEffect as useEffect12, useState as
|
|
4752
|
+
import { useEffect as useEffect12, useState as useState15 } from "react";
|
|
4572
4753
|
import { createPortal as createPortal2 } from "react-dom";
|
|
4573
|
-
import { jsx as
|
|
4754
|
+
import { jsx as jsx34, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
4574
4755
|
var STAY_MS = 5e3;
|
|
4575
4756
|
var MOVE_MS = 250;
|
|
4576
4757
|
var LAYER2 = 2147483001;
|
|
@@ -4578,7 +4759,7 @@ function WidgetToast({
|
|
|
4578
4759
|
agent,
|
|
4579
4760
|
children
|
|
4580
4761
|
}) {
|
|
4581
|
-
const [isShown, setIsShown] =
|
|
4762
|
+
const [isShown, setIsShown] = useState15(false);
|
|
4582
4763
|
useEffect12(() => {
|
|
4583
4764
|
const frame = requestAnimationFrame(() => setIsShown(true));
|
|
4584
4765
|
const timer = setTimeout(() => setIsShown(false), STAY_MS);
|
|
@@ -4589,7 +4770,7 @@ function WidgetToast({
|
|
|
4589
4770
|
}, []);
|
|
4590
4771
|
if (typeof document === "undefined") return null;
|
|
4591
4772
|
return createPortal2(
|
|
4592
|
-
/* @__PURE__ */
|
|
4773
|
+
/* @__PURE__ */ jsxs18(
|
|
4593
4774
|
"div",
|
|
4594
4775
|
{
|
|
4595
4776
|
"data-median-widget": "",
|
|
@@ -4607,8 +4788,8 @@ function WidgetToast({
|
|
|
4607
4788
|
isShown ? "translate-y-0 opacity-100" : "pointer-events-none translate-y-2 opacity-0"
|
|
4608
4789
|
),
|
|
4609
4790
|
children: [
|
|
4610
|
-
/* @__PURE__ */
|
|
4611
|
-
/* @__PURE__ */
|
|
4791
|
+
/* @__PURE__ */ jsx34(WidgetAvatar, { agent, className: "size-6 rounded-full" }),
|
|
4792
|
+
/* @__PURE__ */ jsx34("span", { className: "truncate", children })
|
|
4612
4793
|
]
|
|
4613
4794
|
}
|
|
4614
4795
|
),
|
|
@@ -5217,14 +5398,14 @@ import {
|
|
|
5217
5398
|
useCallback as useCallback11,
|
|
5218
5399
|
useEffect as useEffect17,
|
|
5219
5400
|
useMemo as useMemo2,
|
|
5220
|
-
useState as
|
|
5401
|
+
useState as useState17,
|
|
5221
5402
|
useSyncExternalStore as useSyncExternalStore7
|
|
5222
5403
|
} from "react";
|
|
5223
5404
|
|
|
5224
5405
|
// ../../apps/web/src/hooks/use-now.ts
|
|
5225
|
-
import { useEffect as useEffect16, useState as
|
|
5406
|
+
import { useEffect as useEffect16, useState as useState16 } from "react";
|
|
5226
5407
|
function useNow(intervalMs = 3e4) {
|
|
5227
|
-
const [now, setNow] =
|
|
5408
|
+
const [now, setNow] = useState16(() => Date.now());
|
|
5228
5409
|
useEffect16(() => {
|
|
5229
5410
|
const timer = setInterval(() => setNow(Date.now()), intervalMs);
|
|
5230
5411
|
return () => clearInterval(timer);
|
|
@@ -5341,31 +5522,44 @@ function writeSkippedRating(apiKey, conversationId) {
|
|
|
5341
5522
|
}
|
|
5342
5523
|
}
|
|
5343
5524
|
|
|
5344
|
-
// ../../apps/web/src/components/support-widget/sdk/
|
|
5345
|
-
var STORAGE_PREFIX3 = "median:read:";
|
|
5525
|
+
// ../../apps/web/src/components/support-widget/sdk/stamps.ts
|
|
5346
5526
|
var inMemory2 = /* @__PURE__ */ new Map();
|
|
5347
|
-
function
|
|
5527
|
+
function keyOf(name, apiKey) {
|
|
5528
|
+
return `median:${name}:${apiKey}`;
|
|
5529
|
+
}
|
|
5530
|
+
function readStamp(name, apiKey) {
|
|
5348
5531
|
if (typeof window === "undefined") return 0;
|
|
5532
|
+
const key = keyOf(name, apiKey);
|
|
5349
5533
|
try {
|
|
5350
|
-
const stored = window.localStorage.getItem(
|
|
5534
|
+
const stored = window.localStorage.getItem(key);
|
|
5351
5535
|
const at2 = stored === null ? Number.NaN : Number(stored);
|
|
5352
5536
|
return Number.isFinite(at2) ? at2 : 0;
|
|
5353
5537
|
} catch {
|
|
5354
|
-
return inMemory2.get(
|
|
5538
|
+
return inMemory2.get(key) ?? 0;
|
|
5355
5539
|
}
|
|
5356
5540
|
}
|
|
5357
|
-
function
|
|
5541
|
+
function writeStamp(name, apiKey, at2) {
|
|
5358
5542
|
if (typeof window === "undefined") return;
|
|
5359
|
-
|
|
5543
|
+
const key = keyOf(name, apiKey);
|
|
5544
|
+
inMemory2.set(key, at2);
|
|
5360
5545
|
try {
|
|
5361
|
-
window.localStorage.setItem(
|
|
5546
|
+
window.localStorage.setItem(key, String(at2));
|
|
5362
5547
|
} catch {
|
|
5363
5548
|
}
|
|
5364
5549
|
}
|
|
5365
5550
|
|
|
5551
|
+
// ../../apps/web/src/components/support-widget/sdk/read-state.ts
|
|
5552
|
+
var READ = "read";
|
|
5553
|
+
function readLastSeenAt(apiKey) {
|
|
5554
|
+
return readStamp(READ, apiKey);
|
|
5555
|
+
}
|
|
5556
|
+
function writeLastSeenAt(apiKey, at2) {
|
|
5557
|
+
writeStamp(READ, apiKey, at2);
|
|
5558
|
+
}
|
|
5559
|
+
|
|
5366
5560
|
// ../../apps/web/src/components/support-widget/sdk/visitor-email.ts
|
|
5367
5561
|
import { useCallback as useCallback10, useSyncExternalStore as useSyncExternalStore6 } from "react";
|
|
5368
|
-
var
|
|
5562
|
+
var STORAGE_PREFIX3 = "median:email:";
|
|
5369
5563
|
var inMemory3 = /* @__PURE__ */ new Map();
|
|
5370
5564
|
var listeners5 = /* @__PURE__ */ new Set();
|
|
5371
5565
|
function subscribeVisitorEmail(listener) {
|
|
@@ -5377,7 +5571,7 @@ function subscribeVisitorEmail(listener) {
|
|
|
5377
5571
|
function readVisitorEmail(apiKey) {
|
|
5378
5572
|
if (typeof window === "undefined") return null;
|
|
5379
5573
|
try {
|
|
5380
|
-
const stored = window.localStorage.getItem(`${
|
|
5574
|
+
const stored = window.localStorage.getItem(`${STORAGE_PREFIX3}${apiKey}`);
|
|
5381
5575
|
return stored && stored.length > 0 ? stored : null;
|
|
5382
5576
|
} catch {
|
|
5383
5577
|
return inMemory3.get(apiKey) ?? null;
|
|
@@ -5386,7 +5580,7 @@ function readVisitorEmail(apiKey) {
|
|
|
5386
5580
|
function writeVisitorEmail(apiKey, email) {
|
|
5387
5581
|
inMemory3.set(apiKey, email);
|
|
5388
5582
|
try {
|
|
5389
|
-
window.localStorage.setItem(`${
|
|
5583
|
+
window.localStorage.setItem(`${STORAGE_PREFIX3}${apiKey}`, email);
|
|
5390
5584
|
} catch {
|
|
5391
5585
|
}
|
|
5392
5586
|
for (const listener of listeners5) listener();
|
|
@@ -5398,7 +5592,7 @@ function resetVisitorEmails() {
|
|
|
5398
5592
|
const stale = [];
|
|
5399
5593
|
for (let i3 = 0; i3 < window.localStorage.length; i3 += 1) {
|
|
5400
5594
|
const key = window.localStorage.key(i3);
|
|
5401
|
-
if (key !== null && key.startsWith(
|
|
5595
|
+
if (key !== null && key.startsWith(STORAGE_PREFIX3)) stale.push(key);
|
|
5402
5596
|
}
|
|
5403
5597
|
for (const key of stale) window.localStorage.removeItem(key);
|
|
5404
5598
|
} catch {
|
|
@@ -5439,7 +5633,7 @@ var IDENTITY_COMPLAINTS = {
|
|
|
5439
5633
|
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.",
|
|
5440
5634
|
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."
|
|
5441
5635
|
};
|
|
5442
|
-
function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagnostics, appState, requireEmail = true) {
|
|
5636
|
+
function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagnostics, appState, requireEmail = true, messagePreview = true) {
|
|
5443
5637
|
const sessionId = useSyncExternalStore7(
|
|
5444
5638
|
subscribeSession,
|
|
5445
5639
|
useCallback11(() => getOrCreateSessionId(apiKey), [apiKey]),
|
|
@@ -5482,8 +5676,8 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
5482
5676
|
) ?? false;
|
|
5483
5677
|
const now = useNow(hasLiveDots ? 1e3 : 6e4);
|
|
5484
5678
|
const takeDiagnostics = useDiagnostics(diagnostics, appState);
|
|
5485
|
-
const [isSending, setIsSending] =
|
|
5486
|
-
const [sendError, setSendError] =
|
|
5679
|
+
const [isSending, setIsSending] = useState17(false);
|
|
5680
|
+
const [sendError, setSendError] = useState17(null);
|
|
5487
5681
|
const agent = useMemo2(
|
|
5488
5682
|
() => config === void 0 ? null : {
|
|
5489
5683
|
id: "median-agent",
|
|
@@ -5556,15 +5750,17 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
5556
5750
|
team: [...[...humans.values()].slice(-2), agent]
|
|
5557
5751
|
};
|
|
5558
5752
|
}, [config, agent, messages]);
|
|
5559
|
-
const [lastSeenAt, setLastSeenAt] =
|
|
5560
|
-
const
|
|
5753
|
+
const [lastSeenAt, setLastSeenAt] = useState17(() => readLastSeenAt(apiKey));
|
|
5754
|
+
const unread = useMemo2(
|
|
5561
5755
|
() => messages.filter(
|
|
5562
5756
|
(message) => message.sender === "agent" && !message.pending && (message.sentAt ?? 0) > lastSeenAt
|
|
5563
|
-
)
|
|
5757
|
+
),
|
|
5564
5758
|
[messages, lastSeenAt]
|
|
5565
5759
|
);
|
|
5566
|
-
const
|
|
5567
|
-
const [
|
|
5760
|
+
const unreadCount = unread.length;
|
|
5761
|
+
const latestUnread = messagePreview && (config?.messagePreview ?? true) ? unread[unread.length - 1] ?? null : null;
|
|
5762
|
+
const [picked, setPicked] = useState17(null);
|
|
5763
|
+
const [skipped, setSkipped] = useState17(
|
|
5568
5764
|
() => readSkippedRatings(apiKey)
|
|
5569
5765
|
);
|
|
5570
5766
|
const conversationId = thread?.conversationId ?? null;
|
|
@@ -5604,7 +5800,7 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
5604
5800
|
const custom = takeCustomData();
|
|
5605
5801
|
try {
|
|
5606
5802
|
const attachments = await uploadAttachments(
|
|
5607
|
-
() => generateUploadUrl({ apiKey }),
|
|
5803
|
+
() => generateUploadUrl({ apiKey, sessionId }),
|
|
5608
5804
|
files
|
|
5609
5805
|
);
|
|
5610
5806
|
const context = telemetry ? collectContext() : void 0;
|
|
@@ -5676,6 +5872,8 @@ function useMedianThread(apiKey, user, telemetry = true, isLocked = false, diagn
|
|
|
5676
5872
|
rating,
|
|
5677
5873
|
/** Replies that arrived while they were not looking. */
|
|
5678
5874
|
unreadCount,
|
|
5875
|
+
/** The newest of those, for the card on the closed button. */
|
|
5876
|
+
latestUnread,
|
|
5679
5877
|
markSeen,
|
|
5680
5878
|
/** Say the panel is on screen, so replies are not also emailed. */
|
|
5681
5879
|
reportPresence,
|
|
@@ -5890,7 +6088,7 @@ var MedianErrorBoundary = class extends Component {
|
|
|
5890
6088
|
};
|
|
5891
6089
|
|
|
5892
6090
|
// ../../apps/web/src/components/support-widget/sdk/use-identity.ts
|
|
5893
|
-
import { useEffect as useEffect18, useState as
|
|
6091
|
+
import { useEffect as useEffect18, useState as useState18 } from "react";
|
|
5894
6092
|
var NOTHING = {
|
|
5895
6093
|
apiKey: void 0,
|
|
5896
6094
|
user: void 0,
|
|
@@ -5927,7 +6125,7 @@ function useMissingCredentials(component, apiKey, endpoint) {
|
|
|
5927
6125
|
}, [component, apiKey, endpoint]);
|
|
5928
6126
|
}
|
|
5929
6127
|
function useMedianIdentity(endpoint) {
|
|
5930
|
-
const [answered, setAnswered] =
|
|
6128
|
+
const [answered, setAnswered] = useState18(null);
|
|
5931
6129
|
useEffect18(() => {
|
|
5932
6130
|
if (endpoint === void 0) return;
|
|
5933
6131
|
let listening = true;
|
|
@@ -6314,7 +6512,7 @@ function useMessageSound({
|
|
|
6314
6512
|
}
|
|
6315
6513
|
|
|
6316
6514
|
// ../../apps/web/src/components/support-widget/sdk/use-navigation.ts
|
|
6317
|
-
import { useLayoutEffect as
|
|
6515
|
+
import { useLayoutEffect as useLayoutEffect7, useRef as useRef15, useState as useState19 } from "react";
|
|
6318
6516
|
var isDevelopment2 = typeof process !== "undefined" && process.env.NODE_ENV === "development";
|
|
6319
6517
|
var STALE_AFTER_MS = 5 * 60 * 1e3;
|
|
6320
6518
|
function pathOnThisSite(destination) {
|
|
@@ -6353,8 +6551,8 @@ function useSupportNavigation({
|
|
|
6353
6551
|
}) {
|
|
6354
6552
|
const seen = useRef15(null);
|
|
6355
6553
|
const watching = useRef15(null);
|
|
6356
|
-
const [direction, setDirection] =
|
|
6357
|
-
|
|
6554
|
+
const [direction, setDirection] = useState19(null);
|
|
6555
|
+
useLayoutEffect7(() => {
|
|
6358
6556
|
if (isLoading) return;
|
|
6359
6557
|
const asked = directed(messages, ask);
|
|
6360
6558
|
if (seen.current === null || watching.current !== conversationId) {
|
|
@@ -6399,18 +6597,45 @@ function useSupportNavigation({
|
|
|
6399
6597
|
return direction;
|
|
6400
6598
|
}
|
|
6401
6599
|
|
|
6600
|
+
// ../../apps/web/src/components/support-widget/sdk/use-teaser.ts
|
|
6601
|
+
import { useCallback as useCallback12, useState as useState20 } from "react";
|
|
6602
|
+
|
|
6603
|
+
// ../../apps/web/src/components/support-widget/sdk/teaser-state.ts
|
|
6604
|
+
var TEASER = "teaser";
|
|
6605
|
+
function readTeaserDismissedAt(apiKey) {
|
|
6606
|
+
return readStamp(TEASER, apiKey);
|
|
6607
|
+
}
|
|
6608
|
+
function writeTeaserDismissedAt(apiKey, at2) {
|
|
6609
|
+
writeStamp(TEASER, apiKey, at2);
|
|
6610
|
+
}
|
|
6611
|
+
|
|
6612
|
+
// ../../apps/web/src/components/support-widget/sdk/use-teaser.ts
|
|
6613
|
+
function useTeaser(apiKey, latestUnread) {
|
|
6614
|
+
const [dismissedAt, setDismissedAt] = useState20(
|
|
6615
|
+
() => readTeaserDismissedAt(apiKey)
|
|
6616
|
+
);
|
|
6617
|
+
const teaser = latestUnread !== null && (latestUnread.sentAt ?? 0) > dismissedAt ? latestUnread : null;
|
|
6618
|
+
const dismiss = useCallback12(() => {
|
|
6619
|
+
if (teaser === null) return;
|
|
6620
|
+
const at2 = teaser.sentAt ?? Date.now();
|
|
6621
|
+
writeTeaserDismissedAt(apiKey, at2);
|
|
6622
|
+
setDismissedAt(at2);
|
|
6623
|
+
}, [apiKey, teaser]);
|
|
6624
|
+
return { teaser, dismiss };
|
|
6625
|
+
}
|
|
6626
|
+
|
|
6402
6627
|
// ../../apps/web/src/components/support-widget/sdk/median-support.tsx
|
|
6403
|
-
import { Fragment as
|
|
6628
|
+
import { Fragment as Fragment27, jsx as jsx35, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
6404
6629
|
var PRESENCE_BEAT_MS = 45e3;
|
|
6405
6630
|
function MedianSupport(props) {
|
|
6406
|
-
return /* @__PURE__ */
|
|
6631
|
+
return /* @__PURE__ */ jsx35(MedianSupportPreview, { ...props });
|
|
6407
6632
|
}
|
|
6408
6633
|
function MedianSupportPreview({
|
|
6409
6634
|
defaultOpen = false,
|
|
6410
6635
|
className,
|
|
6411
6636
|
...props
|
|
6412
6637
|
}) {
|
|
6413
|
-
return /* @__PURE__ */
|
|
6638
|
+
return /* @__PURE__ */ jsx35(MedianErrorBoundary, { children: /* @__PURE__ */ jsx35(
|
|
6414
6639
|
MedianIdentity,
|
|
6415
6640
|
{
|
|
6416
6641
|
...props,
|
|
@@ -6424,7 +6649,7 @@ function MedianIdentity({ apiKey, identity, user, ...rest }) {
|
|
|
6424
6649
|
useMissingCredentials("MedianSupport", apiKey, identity);
|
|
6425
6650
|
const key = apiKey ?? resolved.apiKey;
|
|
6426
6651
|
if (key === void 0) return null;
|
|
6427
|
-
return /* @__PURE__ */
|
|
6652
|
+
return /* @__PURE__ */ jsx35(
|
|
6428
6653
|
MedianConnection,
|
|
6429
6654
|
{
|
|
6430
6655
|
...rest,
|
|
@@ -6444,7 +6669,7 @@ function useApiKeyShapeWarning(apiKey) {
|
|
|
6444
6669
|
}, [apiKey]);
|
|
6445
6670
|
}
|
|
6446
6671
|
function MedianConnection(props) {
|
|
6447
|
-
const [client2] =
|
|
6672
|
+
const [client2] = useState21(() => {
|
|
6448
6673
|
if (!MEDIAN_DEPLOYMENT_URL) {
|
|
6449
6674
|
throw new Error(
|
|
6450
6675
|
"The Median widget was built without a deployment URL. Set NEXT_PUBLIC_CONVEX_URL."
|
|
@@ -6452,7 +6677,7 @@ function MedianConnection(props) {
|
|
|
6452
6677
|
}
|
|
6453
6678
|
return new ConvexReactClient(MEDIAN_DEPLOYMENT_URL);
|
|
6454
6679
|
});
|
|
6455
|
-
return /* @__PURE__ */
|
|
6680
|
+
return /* @__PURE__ */ jsx35(ConvexProvider, { client: client2, children: /* @__PURE__ */ jsx35(MedianLauncher, { ...props }) });
|
|
6456
6681
|
}
|
|
6457
6682
|
function MedianLauncher({
|
|
6458
6683
|
apiKey,
|
|
@@ -6463,6 +6688,7 @@ function MedianLauncher({
|
|
|
6463
6688
|
requireSignIn = false,
|
|
6464
6689
|
onSignIn,
|
|
6465
6690
|
requireEmail = true,
|
|
6691
|
+
messagePreview = true,
|
|
6466
6692
|
launcher,
|
|
6467
6693
|
defaultOpen,
|
|
6468
6694
|
open,
|
|
@@ -6492,6 +6718,7 @@ function MedianLauncher({
|
|
|
6492
6718
|
awaitingHuman,
|
|
6493
6719
|
rating,
|
|
6494
6720
|
unreadCount,
|
|
6721
|
+
latestUnread,
|
|
6495
6722
|
markSeen,
|
|
6496
6723
|
reportPresence,
|
|
6497
6724
|
sendError,
|
|
@@ -6504,8 +6731,10 @@ function MedianLauncher({
|
|
|
6504
6731
|
isLocked,
|
|
6505
6732
|
diagnostics,
|
|
6506
6733
|
appState,
|
|
6507
|
-
requireEmail
|
|
6734
|
+
requireEmail,
|
|
6735
|
+
messagePreview
|
|
6508
6736
|
);
|
|
6737
|
+
const { teaser, dismiss: dismissTeaser } = useTeaser(apiKey, latestUnread);
|
|
6509
6738
|
const isSettling = isLoading || isResolvingIdentity;
|
|
6510
6739
|
useEffect20(() => {
|
|
6511
6740
|
if (isOpen) markSeen();
|
|
@@ -6553,19 +6782,19 @@ function MedianLauncher({
|
|
|
6553
6782
|
team: []
|
|
6554
6783
|
};
|
|
6555
6784
|
const mover = resolvedPresence.team.find((member) => member.kind === "ai");
|
|
6556
|
-
return /* @__PURE__ */
|
|
6557
|
-
direction?.selector != null && /* @__PURE__ */
|
|
6785
|
+
return /* @__PURE__ */ jsxs19(Fragment27, { children: [
|
|
6786
|
+
direction?.selector != null && /* @__PURE__ */ jsx35(
|
|
6558
6787
|
WidgetSpotlight,
|
|
6559
6788
|
{
|
|
6560
6789
|
selector: direction.selector
|
|
6561
6790
|
},
|
|
6562
6791
|
`ring:${direction.key}`
|
|
6563
6792
|
),
|
|
6564
|
-
direction?.didNavigate === true && mover !== void 0 && /* @__PURE__ */
|
|
6793
|
+
direction?.didNavigate === true && mover !== void 0 && /* @__PURE__ */ jsxs19(WidgetToast, { agent: mover, children: [
|
|
6565
6794
|
mover.name,
|
|
6566
6795
|
" navigated you here"
|
|
6567
6796
|
] }, `moved:${direction.key}`),
|
|
6568
|
-
/* @__PURE__ */
|
|
6797
|
+
/* @__PURE__ */ jsx35(
|
|
6569
6798
|
SupportLauncher,
|
|
6570
6799
|
{
|
|
6571
6800
|
presence: resolvedPresence,
|
|
@@ -6581,6 +6810,8 @@ function MedianLauncher({
|
|
|
6581
6810
|
awaitingHuman,
|
|
6582
6811
|
rating,
|
|
6583
6812
|
unreadCount,
|
|
6813
|
+
teaser,
|
|
6814
|
+
onDismissTeaser: dismissTeaser,
|
|
6584
6815
|
notice: sendError,
|
|
6585
6816
|
launcher,
|
|
6586
6817
|
open: isOpen,
|
|
@@ -6593,7 +6824,7 @@ function MedianLauncher({
|
|
|
6593
6824
|
|
|
6594
6825
|
// ../../apps/web/src/components/support-widget/sdk/mount.tsx
|
|
6595
6826
|
import { createRoot } from "react-dom/client";
|
|
6596
|
-
import { jsx as
|
|
6827
|
+
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
6597
6828
|
var isDevelopment3 = typeof process !== "undefined" && process.env.NODE_ENV === "development";
|
|
6598
6829
|
function mountMedianSupport(options) {
|
|
6599
6830
|
if (typeof document === "undefined") {
|
|
@@ -6611,7 +6842,7 @@ function mountMedianSupport(options) {
|
|
|
6611
6842
|
let current2 = options;
|
|
6612
6843
|
let mounted = true;
|
|
6613
6844
|
const render = () => {
|
|
6614
|
-
root.render(/* @__PURE__ */
|
|
6845
|
+
root.render(/* @__PURE__ */ jsx36(MedianSupport, { ...current2 }));
|
|
6615
6846
|
};
|
|
6616
6847
|
render();
|
|
6617
6848
|
return {
|
|
@@ -6638,13 +6869,20 @@ function mountMedianSupport(options) {
|
|
|
6638
6869
|
|
|
6639
6870
|
// ../../apps/web/src/components/support-widget/sdk/median-feedback.tsx
|
|
6640
6871
|
import { ConvexProvider as ConvexProvider2, ConvexReactClient as ConvexReactClient2 } from "convex/react";
|
|
6641
|
-
import { useCallback as
|
|
6872
|
+
import { useCallback as useCallback14, useEffect as useEffect23, useRef as useRef18, useState as useState25 } from "react";
|
|
6642
6873
|
|
|
6643
6874
|
// ../backend/convex/shared/feedback.ts
|
|
6644
6875
|
var NOTE_MAX_LENGTH = 2e3;
|
|
6645
6876
|
|
|
6877
|
+
// ../backend/convex/shared/reportImages.ts
|
|
6878
|
+
var MAX_REPORT_IMAGES = 6;
|
|
6879
|
+
|
|
6646
6880
|
// ../../apps/web/src/components/support-widget/feedback/feedback-panel.tsx
|
|
6647
|
-
import {
|
|
6881
|
+
import {
|
|
6882
|
+
useEffect as useEffect22,
|
|
6883
|
+
useRef as useRef17,
|
|
6884
|
+
useState as useState23
|
|
6885
|
+
} from "react";
|
|
6648
6886
|
|
|
6649
6887
|
// ../../apps/web/src/components/support-widget/feedback/feedback-popover.tsx
|
|
6650
6888
|
import { useEffect as useEffect21, useRef as useRef16 } from "react";
|
|
@@ -6661,8 +6899,8 @@ function useHydrated() {
|
|
|
6661
6899
|
}
|
|
6662
6900
|
|
|
6663
6901
|
// ../../apps/web/src/components/support-widget/feedback/use-anchor.ts
|
|
6664
|
-
import { useLayoutEffect as
|
|
6665
|
-
var
|
|
6902
|
+
import { useLayoutEffect as useLayoutEffect8, useState as useState22 } from "react";
|
|
6903
|
+
var GAP2 = 8;
|
|
6666
6904
|
var MARGIN2 = 16;
|
|
6667
6905
|
function findAnchor(selector) {
|
|
6668
6906
|
if (selector === void 0 || typeof document === "undefined") return null;
|
|
@@ -6681,8 +6919,8 @@ function useAnchor({
|
|
|
6681
6919
|
panelRef,
|
|
6682
6920
|
isOpen
|
|
6683
6921
|
}) {
|
|
6684
|
-
const [side, setSide] =
|
|
6685
|
-
|
|
6922
|
+
const [side, setSide] = useState22("bottom");
|
|
6923
|
+
useLayoutEffect8(() => {
|
|
6686
6924
|
if (!isOpen) return;
|
|
6687
6925
|
let frame = 0;
|
|
6688
6926
|
function place() {
|
|
@@ -6702,11 +6940,11 @@ function useAnchor({
|
|
|
6702
6940
|
return;
|
|
6703
6941
|
}
|
|
6704
6942
|
const rect = trigger.getBoundingClientRect();
|
|
6705
|
-
const below = room.height - rect.bottom -
|
|
6706
|
-
const above = rect.top -
|
|
6943
|
+
const below = room.height - rect.bottom - GAP2 - MARGIN2;
|
|
6944
|
+
const above = rect.top - GAP2 - MARGIN2;
|
|
6707
6945
|
const onTop = height > below && above > below;
|
|
6708
6946
|
setSide(onTop ? "top" : "bottom");
|
|
6709
|
-
const top = onTop ? rect.top -
|
|
6947
|
+
const top = onTop ? rect.top - GAP2 - height : rect.bottom + GAP2;
|
|
6710
6948
|
const fromStart = rect.left;
|
|
6711
6949
|
const fromEnd = rect.right - width;
|
|
6712
6950
|
const left = fromStart + width + MARGIN2 <= room.width ? fromStart : fromEnd;
|
|
@@ -6736,7 +6974,7 @@ function clamp3(value, low, high) {
|
|
|
6736
6974
|
}
|
|
6737
6975
|
|
|
6738
6976
|
// ../../apps/web/src/components/support-widget/feedback/feedback-popover.tsx
|
|
6739
|
-
import { jsx as
|
|
6977
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
6740
6978
|
var LAYER3 = 2147483e3;
|
|
6741
6979
|
var AUTOFOCUS_ATTRIBUTE = "data-median-autofocus";
|
|
6742
6980
|
var MOTION = "transition-[opacity,scale,translate] motion-reduce:transition-none";
|
|
@@ -6793,7 +7031,7 @@ function FeedbackPopover({
|
|
|
6793
7031
|
}, [isOpen, triggerRef]);
|
|
6794
7032
|
if (!isHydrated) return null;
|
|
6795
7033
|
return createPortal3(
|
|
6796
|
-
/* @__PURE__ */
|
|
7034
|
+
/* @__PURE__ */ jsx37(
|
|
6797
7035
|
"div",
|
|
6798
7036
|
{
|
|
6799
7037
|
ref: panelRef,
|
|
@@ -6831,7 +7069,7 @@ function FeedbackPopover({
|
|
|
6831
7069
|
}
|
|
6832
7070
|
|
|
6833
7071
|
// ../../apps/web/src/components/support-widget/feedback/feedback-panel.tsx
|
|
6834
|
-
import { jsx as
|
|
7072
|
+
import { Fragment as Fragment28, jsx as jsx38, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
6835
7073
|
var THANKS_MS2 = 1600;
|
|
6836
7074
|
function FeedbackPanel({
|
|
6837
7075
|
onSubmit,
|
|
@@ -6844,10 +7082,16 @@ function FeedbackPanel({
|
|
|
6844
7082
|
placeholder = "What should change?",
|
|
6845
7083
|
className
|
|
6846
7084
|
}) {
|
|
6847
|
-
const [draft, setDraft] =
|
|
6848
|
-
const [isSending, setSending] =
|
|
6849
|
-
const [isSent, setSent] =
|
|
6850
|
-
const
|
|
7085
|
+
const [draft, setDraft] = useState23("");
|
|
7086
|
+
const [isSending, setSending] = useState23(false);
|
|
7087
|
+
const [isSent, setSent] = useState23(false);
|
|
7088
|
+
const fileInputRef = useRef17(null);
|
|
7089
|
+
const images = useAttachmentDrafts({
|
|
7090
|
+
accept: "image",
|
|
7091
|
+
max: MAX_REPORT_IMAGES
|
|
7092
|
+
});
|
|
7093
|
+
const target = useAttachmentTarget({ onFiles: images.add });
|
|
7094
|
+
const canSend = draft.trim().length > 0 && !images.hasBlocker && !isSending && !isSent;
|
|
6851
7095
|
useEffect22(() => {
|
|
6852
7096
|
if (!isSent) return;
|
|
6853
7097
|
const timer = setTimeout(() => onSent?.(), THANKS_MS2);
|
|
@@ -6857,24 +7101,30 @@ function FeedbackPanel({
|
|
|
6857
7101
|
if (!canSend) return;
|
|
6858
7102
|
setSending(true);
|
|
6859
7103
|
try {
|
|
6860
|
-
await onSubmit?.(draft.trim());
|
|
7104
|
+
await onSubmit?.(draft.trim(), images.files);
|
|
6861
7105
|
} catch {
|
|
6862
7106
|
return;
|
|
6863
7107
|
} finally {
|
|
6864
7108
|
setSending(false);
|
|
6865
7109
|
}
|
|
7110
|
+
images.clear();
|
|
6866
7111
|
setSent(true);
|
|
6867
7112
|
}
|
|
7113
|
+
function handlePick(event) {
|
|
7114
|
+
if (event.target.files?.length) images.add(event.target.files);
|
|
7115
|
+
event.target.value = "";
|
|
7116
|
+
}
|
|
6868
7117
|
function handleKeyDown(event) {
|
|
6869
7118
|
if (event.key !== "Enter") return;
|
|
6870
7119
|
if (!event.metaKey && !event.ctrlKey) return;
|
|
6871
7120
|
event.preventDefault();
|
|
6872
7121
|
void send();
|
|
6873
7122
|
}
|
|
6874
|
-
return /* @__PURE__ */
|
|
7123
|
+
return /* @__PURE__ */ jsxs20(
|
|
6875
7124
|
"section",
|
|
6876
7125
|
{
|
|
6877
7126
|
"aria-label": title,
|
|
7127
|
+
...target.targetProps,
|
|
6878
7128
|
className: cn(
|
|
6879
7129
|
// The widget's own radius scale, so the app's token can climb as the
|
|
6880
7130
|
// chrome gets rounder without this changing shape under its hosts.
|
|
@@ -6882,12 +7132,12 @@ function FeedbackPanel({
|
|
|
6882
7132
|
className
|
|
6883
7133
|
),
|
|
6884
7134
|
children: [
|
|
6885
|
-
/* @__PURE__ */
|
|
6886
|
-
/* @__PURE__ */
|
|
6887
|
-
/* @__PURE__ */
|
|
6888
|
-
/* @__PURE__ */
|
|
7135
|
+
/* @__PURE__ */ jsxs20("header", { className: "flex items-start gap-2", children: [
|
|
7136
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
7137
|
+
/* @__PURE__ */ jsx38("h2", { className: "truncate text-sm font-semibold tracking-tight", children: title }),
|
|
7138
|
+
/* @__PURE__ */ jsx38("p", { className: "text-xs text-muted-foreground", children: description })
|
|
6889
7139
|
] }),
|
|
6890
|
-
onClose && /* @__PURE__ */
|
|
7140
|
+
onClose && /* @__PURE__ */ jsx38(
|
|
6891
7141
|
WidgetButton,
|
|
6892
7142
|
{
|
|
6893
7143
|
type: "button",
|
|
@@ -6896,13 +7146,13 @@ function FeedbackPanel({
|
|
|
6896
7146
|
onClick: onClose,
|
|
6897
7147
|
"aria-label": "Close feedback",
|
|
6898
7148
|
className: "-mt-0.5 -mr-1 shrink-0 text-muted-foreground",
|
|
6899
|
-
children: /* @__PURE__ */
|
|
7149
|
+
children: /* @__PURE__ */ jsx38(X, {})
|
|
6900
7150
|
}
|
|
6901
7151
|
)
|
|
6902
7152
|
] }),
|
|
6903
|
-
/* @__PURE__ */
|
|
6904
|
-
/* @__PURE__ */
|
|
6905
|
-
/* @__PURE__ */
|
|
7153
|
+
/* @__PURE__ */ jsxs20("div", { className: "grid", children: [
|
|
7154
|
+
/* @__PURE__ */ jsx38(Collapse, { isOpen: !isSent, children: /* @__PURE__ */ jsxs20("div", { className: "flex flex-col gap-1.5", children: [
|
|
7155
|
+
/* @__PURE__ */ jsx38(
|
|
6906
7156
|
Textarea,
|
|
6907
7157
|
{
|
|
6908
7158
|
rows: 3,
|
|
@@ -6910,7 +7160,7 @@ function FeedbackPanel({
|
|
|
6910
7160
|
maxLength: NOTE_MAX_LENGTH,
|
|
6911
7161
|
onChange: (event) => setDraft(event.target.value),
|
|
6912
7162
|
onKeyDown: handleKeyDown,
|
|
6913
|
-
placeholder,
|
|
7163
|
+
placeholder: target.isDropTarget ? "Drop to attach" : placeholder,
|
|
6914
7164
|
"aria-label": title,
|
|
6915
7165
|
...{ [AUTOFOCUS_ATTRIBUTE]: "" },
|
|
6916
7166
|
className: cn(
|
|
@@ -6922,44 +7172,79 @@ function FeedbackPanel({
|
|
|
6922
7172
|
)
|
|
6923
7173
|
}
|
|
6924
7174
|
),
|
|
6925
|
-
|
|
7175
|
+
images.drafts.length > 0 && /* @__PURE__ */ jsx38("div", { className: "flex flex-wrap gap-1.5", children: images.drafts.map((draft2) => /* @__PURE__ */ jsx38(
|
|
7176
|
+
AttachmentDraftChip,
|
|
7177
|
+
{
|
|
7178
|
+
draft: draft2,
|
|
7179
|
+
onRemove: () => images.remove(draft2.id)
|
|
7180
|
+
},
|
|
7181
|
+
draft2.id
|
|
7182
|
+
)) }),
|
|
7183
|
+
notice && /* @__PURE__ */ jsx38("p", { className: "animate-in px-0.5 text-xs text-destructive fade-in duration-150", children: notice })
|
|
6926
7184
|
] }) }),
|
|
6927
|
-
/* @__PURE__ */
|
|
6928
|
-
/* @__PURE__ */
|
|
7185
|
+
/* @__PURE__ */ jsx38(Collapse, { isOpen: isSent, children: /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-center gap-2 py-4 text-sm font-medium", children: [
|
|
7186
|
+
/* @__PURE__ */ jsx38("span", { className: "grid size-5 shrink-0 place-items-center rounded-full bg-primary text-primary-foreground", children: /* @__PURE__ */ jsx38(Check, { className: "size-3" }) }),
|
|
6929
7187
|
"Thanks, we got it."
|
|
6930
7188
|
] }) })
|
|
6931
7189
|
] }),
|
|
6932
|
-
/* @__PURE__ */
|
|
6933
|
-
showBadge && /* @__PURE__ */
|
|
6934
|
-
!isSent && /* @__PURE__ */
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
7190
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex min-h-8 items-center gap-2", children: [
|
|
7191
|
+
showBadge && /* @__PURE__ */ jsx38(PoweredByMedian, { className: "justify-start" }),
|
|
7192
|
+
!isSent && /* @__PURE__ */ jsxs20(Fragment28, { children: [
|
|
7193
|
+
/* @__PURE__ */ jsx38(
|
|
7194
|
+
"input",
|
|
7195
|
+
{
|
|
7196
|
+
ref: fileInputRef,
|
|
7197
|
+
type: "file",
|
|
7198
|
+
accept: "image/*",
|
|
7199
|
+
multiple: true,
|
|
7200
|
+
tabIndex: -1,
|
|
7201
|
+
onChange: handlePick,
|
|
7202
|
+
className: "sr-only"
|
|
7203
|
+
}
|
|
7204
|
+
),
|
|
7205
|
+
/* @__PURE__ */ jsx38(
|
|
7206
|
+
WidgetButton,
|
|
7207
|
+
{
|
|
7208
|
+
type: "button",
|
|
7209
|
+
variant: "ghost",
|
|
7210
|
+
size: "icon",
|
|
7211
|
+
disabled: images.isFull,
|
|
7212
|
+
onClick: () => fileInputRef.current?.click(),
|
|
7213
|
+
"aria-label": "Add a picture",
|
|
7214
|
+
className: "ml-auto shrink-0 rounded-full text-muted-foreground",
|
|
7215
|
+
children: /* @__PURE__ */ jsx38(ImageSquare, {})
|
|
7216
|
+
}
|
|
7217
|
+
),
|
|
7218
|
+
/* @__PURE__ */ jsxs20(
|
|
7219
|
+
WidgetButton,
|
|
7220
|
+
{
|
|
7221
|
+
type: "button",
|
|
7222
|
+
disabled: !canSend,
|
|
7223
|
+
"aria-busy": isSending,
|
|
7224
|
+
onClick: () => void send(),
|
|
7225
|
+
className: "relative shrink-0 rounded-full px-3",
|
|
7226
|
+
children: [
|
|
7227
|
+
/* @__PURE__ */ jsx38(
|
|
7228
|
+
"span",
|
|
7229
|
+
{
|
|
7230
|
+
className: cn(
|
|
7231
|
+
"transition-opacity duration-150 motion-reduce:transition-none",
|
|
7232
|
+
isSending && "opacity-0"
|
|
7233
|
+
),
|
|
7234
|
+
children: "Submit feedback"
|
|
7235
|
+
}
|
|
7236
|
+
),
|
|
7237
|
+
isSending && /* @__PURE__ */ jsx38(
|
|
7238
|
+
ArrowsClockwise,
|
|
7239
|
+
{
|
|
7240
|
+
"aria-hidden": true,
|
|
7241
|
+
className: "absolute inset-0 m-auto animate-spin motion-reduce:animate-none"
|
|
7242
|
+
}
|
|
7243
|
+
)
|
|
7244
|
+
]
|
|
7245
|
+
}
|
|
7246
|
+
)
|
|
7247
|
+
] })
|
|
6963
7248
|
] })
|
|
6964
7249
|
]
|
|
6965
7250
|
}
|
|
@@ -7011,7 +7296,7 @@ function useRegisterMedianFeedback() {
|
|
|
7011
7296
|
|
|
7012
7297
|
// ../../apps/web/src/components/support-widget/sdk/use-feedback-note.ts
|
|
7013
7298
|
import { useMutation as useMutation2 } from "convex/react";
|
|
7014
|
-
import { useCallback as
|
|
7299
|
+
import { useCallback as useCallback13, useState as useState24, useSyncExternalStore as useSyncExternalStore12 } from "react";
|
|
7015
7300
|
var REFUSALS = {
|
|
7016
7301
|
off: "This site is not taking feedback right now.",
|
|
7017
7302
|
empty: "Write something first."
|
|
@@ -7025,14 +7310,15 @@ function useFeedbackNote({
|
|
|
7025
7310
|
}) {
|
|
7026
7311
|
const sessionId = useSyncExternalStore12(
|
|
7027
7312
|
subscribeSession,
|
|
7028
|
-
|
|
7313
|
+
useCallback13(() => getOrCreateSessionId(apiKey), [apiKey]),
|
|
7029
7314
|
() => null
|
|
7030
7315
|
);
|
|
7031
7316
|
const submitNote = useMutation2(api.feedback.submit);
|
|
7317
|
+
const getUploadUrl = useMutation2(api.widget.generateUploadUrl);
|
|
7032
7318
|
const takeDiagnostics = useDiagnostics(diagnostics, appState);
|
|
7033
|
-
const [notice, setNotice] =
|
|
7034
|
-
const submit =
|
|
7035
|
-
async (body) => {
|
|
7319
|
+
const [notice, setNotice] = useState24(null);
|
|
7320
|
+
const submit = useCallback13(
|
|
7321
|
+
async (body, images = []) => {
|
|
7036
7322
|
setNotice(null);
|
|
7037
7323
|
if (sessionId === null) {
|
|
7038
7324
|
setNotice("This browser is still waking up. Try again in a moment.");
|
|
@@ -7045,6 +7331,10 @@ function useFeedbackNote({
|
|
|
7045
7331
|
const page = telemetry ? collectPage() : void 0;
|
|
7046
7332
|
const collected = takeDiagnostics();
|
|
7047
7333
|
const { facts, claim } = splitIdentity(user ?? null);
|
|
7334
|
+
const attached = await uploadAttachments(
|
|
7335
|
+
() => getUploadUrl({ apiKey, sessionId }),
|
|
7336
|
+
images
|
|
7337
|
+
);
|
|
7048
7338
|
const outcome = await submitNote({
|
|
7049
7339
|
apiKey,
|
|
7050
7340
|
sessionId,
|
|
@@ -7054,7 +7344,8 @@ function useFeedbackNote({
|
|
|
7054
7344
|
...context ? { context } : {},
|
|
7055
7345
|
...page ? { page } : {},
|
|
7056
7346
|
...collected ? { diagnostics: collected } : {},
|
|
7057
|
-
...custom ? { customData: custom } : {}
|
|
7347
|
+
...custom ? { customData: custom } : {},
|
|
7348
|
+
...attached.length > 0 ? { images: attached } : {}
|
|
7058
7349
|
});
|
|
7059
7350
|
if (outcome !== "taken") {
|
|
7060
7351
|
explained = true;
|
|
@@ -7070,16 +7361,24 @@ function useFeedbackNote({
|
|
|
7070
7361
|
throw caught;
|
|
7071
7362
|
}
|
|
7072
7363
|
},
|
|
7073
|
-
[
|
|
7364
|
+
[
|
|
7365
|
+
apiKey,
|
|
7366
|
+
sessionId,
|
|
7367
|
+
user,
|
|
7368
|
+
telemetry,
|
|
7369
|
+
takeDiagnostics,
|
|
7370
|
+
submitNote,
|
|
7371
|
+
getUploadUrl
|
|
7372
|
+
]
|
|
7074
7373
|
);
|
|
7075
7374
|
return { submit, notice, clearNotice: () => setNotice(null) };
|
|
7076
7375
|
}
|
|
7077
7376
|
|
|
7078
7377
|
// ../../apps/web/src/components/support-widget/sdk/median-feedback.tsx
|
|
7079
|
-
import { Fragment as
|
|
7378
|
+
import { Fragment as Fragment29, jsx as jsx39, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
7080
7379
|
var DEFAULT_WIDTH2 = "20rem";
|
|
7081
7380
|
function MedianFeedback(props) {
|
|
7082
|
-
return /* @__PURE__ */
|
|
7381
|
+
return /* @__PURE__ */ jsx39(MedianErrorBoundary, { children: /* @__PURE__ */ jsx39(FeedbackIdentity, { ...props }) });
|
|
7083
7382
|
}
|
|
7084
7383
|
function FeedbackIdentity({
|
|
7085
7384
|
apiKey,
|
|
@@ -7092,7 +7391,7 @@ function FeedbackIdentity({
|
|
|
7092
7391
|
const key = apiKey ?? resolved.apiKey;
|
|
7093
7392
|
const person = user ?? resolved.user;
|
|
7094
7393
|
if (key === void 0) return null;
|
|
7095
|
-
return /* @__PURE__ */
|
|
7394
|
+
return /* @__PURE__ */ jsx39(
|
|
7096
7395
|
FeedbackConnection,
|
|
7097
7396
|
{
|
|
7098
7397
|
...rest,
|
|
@@ -7111,7 +7410,7 @@ function useApiKeyShapeWarning2(apiKey) {
|
|
|
7111
7410
|
}, [apiKey]);
|
|
7112
7411
|
}
|
|
7113
7412
|
function FeedbackConnection(props) {
|
|
7114
|
-
const [client2] =
|
|
7413
|
+
const [client2] = useState25(() => {
|
|
7115
7414
|
if (!MEDIAN_DEPLOYMENT_URL) {
|
|
7116
7415
|
throw new Error(
|
|
7117
7416
|
"The Median feedback panel was built without a deployment URL. Set NEXT_PUBLIC_CONVEX_URL."
|
|
@@ -7119,7 +7418,7 @@ function FeedbackConnection(props) {
|
|
|
7119
7418
|
}
|
|
7120
7419
|
return new ConvexReactClient2(MEDIAN_DEPLOYMENT_URL);
|
|
7121
7420
|
});
|
|
7122
|
-
return /* @__PURE__ */
|
|
7421
|
+
return /* @__PURE__ */ jsx39(ConvexProvider2, { client: client2, children: /* @__PURE__ */ jsx39(Feedback, { ...props }) });
|
|
7123
7422
|
}
|
|
7124
7423
|
function Feedback({
|
|
7125
7424
|
apiKey,
|
|
@@ -7139,7 +7438,7 @@ function Feedback({
|
|
|
7139
7438
|
useRegisterMedianFeedback();
|
|
7140
7439
|
useApiKeyShapeWarning2(apiKey);
|
|
7141
7440
|
useRememberInstall(apiKey, user);
|
|
7142
|
-
const triggerRef =
|
|
7441
|
+
const triggerRef = useRef18(null);
|
|
7143
7442
|
const [isOpen, setOpen] = useMedianFeedbackOpenState({
|
|
7144
7443
|
...open !== void 0 ? { open } : {},
|
|
7145
7444
|
...onOpenChange ? { onOpenChange } : {}
|
|
@@ -7151,20 +7450,20 @@ function Feedback({
|
|
|
7151
7450
|
...diagnostics !== void 0 ? { diagnostics } : {},
|
|
7152
7451
|
...appState ? { appState } : {}
|
|
7153
7452
|
});
|
|
7154
|
-
const close =
|
|
7155
|
-
const [attempt, setAttempt] =
|
|
7156
|
-
const hasSent =
|
|
7453
|
+
const close = useCallback14(() => setOpen(false), [setOpen]);
|
|
7454
|
+
const [attempt, setAttempt] = useState25(0);
|
|
7455
|
+
const hasSent = useRef18(false);
|
|
7157
7456
|
useEffect23(() => {
|
|
7158
7457
|
if (!isOpen || !hasSent.current) return;
|
|
7159
7458
|
hasSent.current = false;
|
|
7160
7459
|
setAttempt((count) => count + 1);
|
|
7161
7460
|
}, [isOpen]);
|
|
7162
|
-
return /* @__PURE__ */
|
|
7461
|
+
return /* @__PURE__ */ jsxs21(Fragment29, { children: [
|
|
7163
7462
|
children !== void 0 && // An inline span rather than a clone of whatever was passed: the
|
|
7164
7463
|
// host's trigger keeps its own props, its own ref and its own
|
|
7165
7464
|
// styles, and the click is caught on the way past. `display:
|
|
7166
7465
|
// contents` would lose the rectangle the panel is measured against.
|
|
7167
|
-
/* @__PURE__ */
|
|
7466
|
+
/* @__PURE__ */ jsx39(
|
|
7168
7467
|
"span",
|
|
7169
7468
|
{
|
|
7170
7469
|
ref: triggerRef,
|
|
@@ -7173,7 +7472,7 @@ function Feedback({
|
|
|
7173
7472
|
children
|
|
7174
7473
|
}
|
|
7175
7474
|
),
|
|
7176
|
-
/* @__PURE__ */
|
|
7475
|
+
/* @__PURE__ */ jsx39(
|
|
7177
7476
|
FeedbackPopover,
|
|
7178
7477
|
{
|
|
7179
7478
|
isOpen,
|
|
@@ -7181,7 +7480,7 @@ function Feedback({
|
|
|
7181
7480
|
triggerRef,
|
|
7182
7481
|
...anchor !== void 0 ? { anchor } : {},
|
|
7183
7482
|
width,
|
|
7184
|
-
children: /* @__PURE__ */
|
|
7483
|
+
children: /* @__PURE__ */ jsx39(
|
|
7185
7484
|
FeedbackPanel,
|
|
7186
7485
|
{
|
|
7187
7486
|
onSubmit: note.submit,
|
|
@@ -7204,7 +7503,7 @@ function Feedback({
|
|
|
7204
7503
|
|
|
7205
7504
|
// ../../apps/web/src/components/support-widget/sdk/mount-feedback.tsx
|
|
7206
7505
|
import { createRoot as createRoot2 } from "react-dom/client";
|
|
7207
|
-
import { jsx as
|
|
7506
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
7208
7507
|
function mountMedianFeedback(options) {
|
|
7209
7508
|
if (typeof document === "undefined") {
|
|
7210
7509
|
console.error(
|
|
@@ -7221,7 +7520,7 @@ function mountMedianFeedback(options) {
|
|
|
7221
7520
|
let current2 = options;
|
|
7222
7521
|
let mounted = true;
|
|
7223
7522
|
const render = () => {
|
|
7224
|
-
root.render(/* @__PURE__ */
|
|
7523
|
+
root.render(/* @__PURE__ */ jsx40(MedianFeedback, { ...current2 }));
|
|
7225
7524
|
};
|
|
7226
7525
|
render();
|
|
7227
7526
|
return {
|