@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.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 useState18 } from "react";
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-5ZZ6COCL.js");
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 useState11 } from "react";
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: r28,
88
- color: a26 = "currentColor",
89
- size: t8 = "1em",
90
- weight: o36 = "regular",
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: t8,
102
- height: t8,
103
- fill: a26,
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
- !!r28 && /* @__PURE__ */ e.createElement("title", null, r28),
108
+ !!r31 && /* @__PURE__ */ e.createElement("title", null, r31),
109
109
  n,
110
- c6.get(o36)
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, t8) => /* @__PURE__ */ o.createElement(w, { ref: t8, ...e53, weights: a }));
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, t8) => /* @__PURE__ */ r2.createElement(w, { ref: t8, ...e53, weights: a2 }));
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((t8, e53) => /* @__PURE__ */ r5.createElement(w, { ref: e53, ...t8, weights: e6 }));
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((r28, t8) => /* @__PURE__ */ o6.createElement(w, { ref: t8, ...r28, weights: e7 }));
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((r28, o36) => /* @__PURE__ */ t2.createElement(w, { ref: o36, ...r28, weights: t }));
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, r28) => /* @__PURE__ */ t3.createElement(w, { ref: r28, ...e53, weights: e11 }));
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((r28, t8) => /* @__PURE__ */ e13.createElement(w, { ref: t8, ...r28, weights: a8 }));
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((r28, t8) => /* @__PURE__ */ e17.createElement(w, { ref: t8, ...r28, weights: a10 }));
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((r28, o36) => /* @__PURE__ */ e19.createElement(w, { ref: o36, ...r28, weights: e18 }));
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, r28) => /* @__PURE__ */ t4.createElement(w, { ref: r28, ...e53, weights: e20 }));
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, r28) => /* @__PURE__ */ o12.createElement(w, { ref: r28, ...m5, weights: e21 }));
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, r28) => /* @__PURE__ */ o13.createElement(w, { ref: r28, ...e53, weights: a15 }));
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((r28, s4) => /* @__PURE__ */ o14.createElement(w, { ref: s4, ...r28, weights: a17 }));
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((o36, a26) => /* @__PURE__ */ e26.createElement(w, { ref: a26, ...o36, weights: l }));
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((o36, a26) => /* @__PURE__ */ r7.createElement(w, { ref: a26, ...o36, weights: l2 }));
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((o36, s4) => /* @__PURE__ */ e28.createElement(w, { ref: s4, ...o36, weights: a20 }));
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((o36, a26) => /* @__PURE__ */ r9.createElement(w, { ref: a26, ...o36, weights: a21 }));
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((r28, t8) => /* @__PURE__ */ o15.createElement(w, { ref: t8, ...r28, weights: a22 }));
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: a26, props: r28, render: t8, state: n = {}, stateAttributesMapping: e53 }) {
1064
- let o36 = d(R(n, e53), r28);
1065
- if (!t8) return i2.createElement(a26, o36);
1066
- if (typeof t8 == "function") return t8(o36, n);
1067
- if (!i2.isValidElement(t8)) return null;
1068
- let s4 = t8.props, u = { ...d(o36, s4), ref: f8(o36.ref, s4.ref) };
1069
- return i2.cloneElement(t8, u);
1070
- }
1071
- function d(...a26) {
1072
- let r28 = {};
1073
- for (let t8 of a26) {
1074
- if (!t8) continue;
1075
- let n = t8;
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 o36 = n[e53];
1078
- if (o36 === void 0) continue;
1079
- let s4 = r28[e53];
1080
- e53 === "className" ? r28[e53] = [s4, o36].filter(Boolean).join(" ") : e53 === "style" ? r28[e53] = { ...s4, ...o36 } : e53 === "ref" ? r28[e53] = f8(s4, o36) : l4(e53) && typeof s4 == "function" && typeof o36 == "function" ? r28[e53] = p2(o36, s4) : r28[e53] = o36;
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 r28;
1084
- }
1085
- function R(a26, r28) {
1086
- let t8 = {};
1087
- for (let n of Object.keys(a26)) {
1088
- let e53 = a26[n], o36 = r28?.[n]?.(e53);
1089
- if (o36) {
1090
- Object.assign(t8, o36);
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
- t8["data-slot"] = e53;
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" ? t8[s4] = e53 ? "" : void 0 : e53 != null && (t8[s4] = String(e53));
1098
+ typeof e53 == "boolean" ? t9[s4] = e53 ? "" : void 0 : e53 != null && (t9[s4] = String(e53));
1099
1099
  }
1100
- return t8;
1100
+ return t9;
1101
1101
  }
1102
- function p2(a26, r28) {
1102
+ function p2(a27, r31) {
1103
1103
  return function(n) {
1104
- a26(n), n.defaultPrevented || r28(n);
1104
+ a27(n), n.defaultPrevented || r31(n);
1105
1105
  };
1106
1106
  }
1107
- function l4(a26) {
1108
- return /^on[A-Z]/.test(a26);
1107
+ function l4(a27) {
1108
+ return /^on[A-Z]/.test(a27);
1109
1109
  }
1110
- function f8(...a26) {
1111
- let r28 = a26.filter(Boolean);
1112
- if (r28.length !== 0) return (t8) => {
1113
- for (let n of r28) typeof n == "function" ? n(t8) : n && (n.current = t8);
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: t8, spacer: r28, viewport: n }) {
1129
+ function De({ content: e53, scrollEdgeThreshold: t9, spacer: r31, viewport: n }) {
1130
1130
  if (!n || !e53) return ge;
1131
- let o36 = Se({ content: e53, spacer: r28, viewport: n });
1132
- return { start: n.scrollTop > t8, end: o36 - n.scrollTop - n.clientHeight > t8 };
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: t8, scrollPreviousItemPeek: r28, spacer: n, viewport: o36, visibleMessageIds: i3 }) {
1135
- if (!e53 || !o36) return Q;
1136
- let S2 = o36.getBoundingClientRect(), l5 = S2.top + t8 + r28, d2 = typeof IntersectionObserver > "u", E = [], b2 = null;
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, t8) {
1146
- return Array.from(e53.children).filter((r28) => r28 instanceof HTMLElement && r28 !== t8);
1145
+ function ee(e53, t9) {
1146
+ return Array.from(e53.children).filter((r31) => r31 instanceof HTMLElement && r31 !== t9);
1147
1147
  }
1148
- function je(e53, t8) {
1149
- for (let r28 = t8; r28 < e53.length; r28++) {
1150
- let n = e53[r28];
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, t8) {
1156
- for (let r28 of e53) if (r28.dataset.scrollAnchor === "true" && !t8.has(r28)) return r28;
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, t8) {
1160
- let r28 = 0;
1161
- for (let n = t8; n < e53.length; n++) if (e53[n]?.dataset.scrollAnchor === "true" && (r28 += 1, r28 > 1)) return true;
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 t8 = e53.length - 1; t8 >= 0; t8--) {
1166
- let r28 = e53[t8];
1167
- if (r28?.dataset.scrollAnchor === "true") return r28;
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: t8, viewport: r28 }) {
1172
- let n = r28.getBoundingClientRect();
1173
- for (let o36 of ee(e53, t8)) {
1174
- if (!o36.dataset.messageId) continue;
1175
- let i3 = o36.getBoundingClientRect();
1176
- if (i3.bottom > n.top && i3.top < n.bottom) return o36;
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: t8, scrollMargin: r28, spacer: n, viewport: o36 }) {
1181
- let i3 = pe(t8, o36), S2 = t8.getBoundingClientRect().height, l5 = bt(n);
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, o36.clientHeight - l5.start - l5.end);
1184
- return i3 - l5.start - (d2 - S2) / 2 - r28;
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 - o36.clientHeight + S2 + l5.end + r28;
1186
+ if (e53 === "end") return i3 - o41.clientHeight + S2 + l5.end + r31;
1187
1187
  if (e53 === "nearest") {
1188
- let d2 = i3 + S2, E = o36.scrollTop + l5.start, b2 = o36.scrollTop + o36.clientHeight - l5.end;
1189
- return i3 >= E && d2 <= b2 ? o36.scrollTop : i3 < E ? i3 - l5.start - r28 : d2 - o36.clientHeight + l5.end + r28;
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 - r28;
1191
+ return i3 - l5.start - r31;
1192
1192
  }
1193
- function pe(e53, t8) {
1194
- let r28 = e53.getBoundingClientRect(), n = t8.getBoundingClientRect();
1195
- return r28.top - n.top + t8.scrollTop;
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, t8) {
1198
- return e53.getBoundingClientRect().top - t8.getBoundingClientRect().top;
1197
+ function te(e53, t9) {
1198
+ return e53.getBoundingClientRect().top - t9.getBoundingClientRect().top;
1199
1199
  }
1200
- function qe({ content: e53, scrollTop: t8, spacer: r28, viewport: n }) {
1201
- let o36 = Se({ content: e53, spacer: r28, viewport: n });
1202
- return t8 + n.clientHeight - o36;
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: t8, viewport: r28 }) {
1205
- let n = ee(e53, t8), o36 = We(e53), i3 = r28.getBoundingClientRect(), S2 = r28.scrollTop, l5 = o36.start + o36.end;
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 + o36.end);
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 t8 = window.getComputedStyle(e53);
1217
- return { end: Re(t8.paddingBlockEnd || t8.paddingBottom), start: Re(t8.paddingBlockStart || t8.paddingTop) };
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 t8 = e53?.parentElement;
1221
- return t8 ? We(t8) : { end: 0, start: 0 };
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 t8 = window.getComputedStyle(e53), r28 = t8.rowGap === "normal" ? t8.gap : t8.rowGap;
1226
- return Re(r28);
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 t8 = Number.parseFloat(e53);
1231
- return Number.isFinite(t8) ? t8 : 0;
1230
+ let t9 = Number.parseFloat(e53);
1231
+ return Number.isFinite(t9) ? t9 : 0;
1232
1232
  }
1233
- function Je({ refs: e53, commitScrollState: t8, scheduleStateCommit: r28, scheduleVisibilitySync: n }) {
1234
- let { streamingTurnRef: o36, 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, t8()), c6 && (l5.current = window.setTimeout(() => {
1236
- l5.current = null, S2.current = false, t8();
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
- }, [t8]), v = g.useCallback((c6) => {
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, t8();
1248
+ P.scrollTop = V, t9();
1249
1249
  return;
1250
1250
  }
1251
- h && G(true), P.scrollTo({ top: V, behavior: f9 }), r28();
1252
- }, [t8, r28, G]), N = g.useCallback(({ behavior: c6 = "auto" } = {}) => _.current ? (v(0), o36.current = null, p3.current = "free-scrolling", H(0, { behavior: c6 }), n(), true) : false, [n, H, v]), ne = g.useCallback(({ behavior: c6 = "auto" } = {}) => {
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), o36.current = null, p3.current = i3.current ? "following-bottom" : "free-scrolling", H(Ke(f9), { autoscrolling: true, behavior: c6 }), n(), true) : false;
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", o36.current = V ? c6 : null, H(K, { behavior: h }), n(), true;
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 = o36.current;
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, t8) {
1275
- let r28 = e53, n = /* @__PURE__ */ new Set();
1276
- return { getSnapshot: () => r28, hasListeners: () => n.size > 0, setSnapshot: (o36) => {
1277
- t8(r28, o36) || (r28 = o36, n.forEach((i3) => i3()));
1278
- }, subscribe: (o36, i3, S2) => {
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(o36), l5 && i3?.(), () => {
1281
- n.delete(o36), n.size === 0 && S2?.();
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, t8) {
1286
- return Qe(e53, t8);
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, t8) {
1292
- return e53.start === t8.start && e53.end === t8.end;
1291
+ function et(e53, t9) {
1292
+ return e53.start === t9.start && e53.end === t9.end;
1293
1293
  }
1294
- function Tt(e53, t8) {
1295
- return e53.currentAnchorId !== t8.currentAnchorId || e53.visibleMessageIds.length !== t8.visibleMessageIds.length ? false : e53.visibleMessageIds.every((r28, n) => r28 === t8.visibleMessageIds[n]);
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: t8, scrollMargin: r28, scrollPreviousItemPeek: n }) {
1298
- let o36 = g.useRef(e53), i3 = g.useRef(false), S2 = g.useRef(null), l5 = g.useRef(false), d2 = g.useRef(t8), 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(r28), 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()), o36.current = e53, d2.current = t8, _.current = r28, x.current = n, { autoScrollRef: o36, 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 };
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, t8) {
1302
- return g.useCallback((r28) => {
1303
- e53.current = r28, r28 && t8();
1304
- }, [e53, t8]);
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: t8 = "end", scrollEdgeThreshold: r28 = xe, scrollPreviousItemPeek: n = Ve, scrollMargin: o36 = _e }) {
1307
- let i3 = tt({ autoScroll: e53, scrollEdgeThreshold: r28, scrollMargin: o36, 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(t8);
1308
- q.current !== t8 && (q.current = t8, C.current = false);
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 a26 = G.current, T = c6.current, O = [s4.start && "start", s4.end && "end"].filter(Boolean).join(" "), ue = d2.current;
1311
- for (let W of [a26, T]) W && (O ? W.setAttribute("data-scrollable", O) : W.removeAttribute("data-scrollable"), W.toggleAttribute("data-autoscrolling", ue));
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 a26 = c6.current?.scrollTop ?? 0, T = a26 < L.current - J;
1314
- L.current = a26, 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");
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 a26 = u.current === "following-bottom" ? { ...s4, end: false } : s4;
1319
- K(a26), U.setSnapshot(a26);
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, a26 = c6.current;
1330
- if (!s4 || !a26 || !s4.element.isConnected) return false;
1331
- let O = te(s4.element, a26) - s4.viewportTop;
1332
- return Math.abs(O) <= J ? false : (a26.scrollTop += O, s4.viewportTop = te(s4.element, a26), oe(), w2(), true);
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, a26 = c6.current;
1335
- if (!s4 || !a26) {
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: a26 });
1340
- k.current = T ? { element: T, viewportTop: te(T, a26) } : null;
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 (!t8 || C.current || m5.current === 0) return false;
1346
+ if (!t9 || C.current || m5.current === 0) return false;
1347
1347
  let s4 = false;
1348
- if (t8 === "last-anchor") {
1349
- let a26 = b2.current, T = c6.current, O = a26 && T ? Ue(ee(a26, B.current)) : null;
1350
- if (!a26 || !T || !O) s4 = I2({ behavior: "auto" });
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: a26, spacer: B.current, viewport: T }) - ue <= T.clientHeight ? I2({ behavior: "auto" }) : le(O, { align: "start" }, { keepPreviousPeek: true });
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 = t8 === "end" ? I2({ behavior: "auto" }) : ae({ behavior: "auto" });
1355
+ } else s4 = t9 === "end" ? I2({ behavior: "auto" }) : ae({ behavior: "auto" });
1356
1356
  return s4 ? (C.current = true, true) : false;
1357
- }, [t8, le, I2, ae]), Te = g.useCallback(() => {
1357
+ }, [t9, le, I2, ae]), Te = g.useCallback(() => {
1358
1358
  let s4 = b2.current;
1359
1359
  if (!s4) return;
1360
- let a26 = ee(s4, B.current), T = m5.current, O = p3.current;
1361
- m5.current = a26.length, p3.current = a26[0] ?? null, (() => {
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() || a26.length > 0 && l5.current && I2({ behavior: "auto" })) return;
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 ? a26.indexOf(O) : -1;
1368
+ let W = O ? a27.indexOf(O) : -1;
1369
1369
  if (_.current && W > 0) {
1370
1370
  de();
1371
1371
  return;
1372
1372
  }
1373
- if (a26.length > T) {
1374
- let $ = je(a26, T);
1373
+ if (a27.length > T) {
1374
+ let $ = je(a27, T);
1375
1375
  if ($) {
1376
- if (l5.current && u.current === "following-bottom" && Ne(a26, T)) {
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 (a26.length === T) {
1385
- let $ = Ge(a26, z.current);
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((a26) => {
1412
- for (let T of a26) {
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((a26) => {
1418
- h.current?.observe(a26);
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, a26, T) => {
1424
- if (a26) {
1425
- y.current.set(s4, a26), h.current?.observe(a26), w2(), Y.current?.messageId === s4 && be();
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 t8 = g.useRef(e53);
1452
- return t8.current = e53, t8;
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: t8, defaultScrollPosition: r28 = "end", scrollEdgeThreshold: n, scrollPreviousItemPeek: o36, scrollMargin: i3 }) {
1467
- let { context: S2, registerMessage: l5 } = nt({ autoScroll: e53, defaultScrollPosition: r28, scrollEdgeThreshold: n, scrollPreviousItemPeek: o36, scrollMargin: i3 });
1468
- return jsx2(st.Provider, { value: S2, children: jsx2(ct.Provider, { value: l5, children: t8 }) });
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, ...t8 }) {
1471
- let { setRootElement: r28 } = X2();
1472
- return jsx2("div", { ref: r28, ...t8, children: e53 });
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: t8, onKeyDown: r28, onScroll: n, onTouchMove: o36, onWheel: i3, preserveScrollOnPrepend: S2 = true, ref: l5, role: d2, tabIndex: E, ...b2 }) {
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(), o36?.(v);
1487
+ y(), o41?.(v);
1488
1488
  }
1489
1489
  function G(v) {
1490
- Be.has(v.key) && y(), r28?.(v);
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: t8 });
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: t8, ref: r28, role: n, spacerClassName: o36, ...i3 }) {
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(r28)?.(p3);
1506
- }, [r28, d2]);
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: [t8, jsx2("div", { ref: E, "aria-hidden": "true", "data-message-scroller-spacer": "", hidden: true, className: o36 })] });
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: t8, scrollAnchor: r28 = false, ...n }) {
1526
- let o36 = Et(), i3 = g.useRef(null), S2 = g.useCallback((l5) => {
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 && o36(e53, l5, d2), f8(t8)?.(l5);
1529
- }, [e53, t8, o36]);
1530
- return jsx2("div", { ref: S2, "data-message-id": e53, "data-scroll-anchor": r28 ? "true" : "false", ...n });
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: t8, direction: r28 = "end", onClick: n, render: o36, tabIndex: i3, type: S2 = "button", ...l5 }) {
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 r28 === "start" ? u.start : u.end;
1536
- }, [r28, b$1]), L = g.useSyncExternalStore(p3, m5, m5), y = g.useCallback((u) => {
1537
- L && (C.current?.(u), u.defaultPrevented || (u.currentTarget.blur(), r28 === "start" ? E({ behavior: e53 }) : d2({ behavior: e53 })));
1538
- }, [e53, r28, L, C, d2, E]);
1539
- return S({ defaultTagName: "button", props: d({ type: S2, inert: !L, tabIndex: L ? i3 : -1, children: t8 ?? jsxs("span", { children: ["Scroll to ", r28] }), onClick: y }, l5), render: o36, state: { active: L, direction: r28 }, stateAttributesMapping: { active: (u) => ({ "data-active": u ? "true" : "false" }) } });
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 jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
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__ */ jsx6(
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__ */ jsx6("span", { className: "grid size-8 shrink-0 place-items-center rounded-md bg-muted", children: /* @__PURE__ */ jsx6(
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__ */ jsx6("p", { className: "truncate text-xs font-medium", children: draft.name }),
2178
- /* @__PURE__ */ jsx6(
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__ */ jsx6(
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__ */ jsx6(X, {})
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" && !isTooBig ? URL.createObjectURL(file) : null,
2247
- error: isTooBig ? `Larger than the ${formatFileSize(MAX_BYTES)} limit` : null
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 jsx7 } from "react/jsx-runtime";
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__ */ jsx7(
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 jsx8 } from "react/jsx-runtime";
2411
+ import { jsx as jsx9 } from "react/jsx-runtime";
2385
2412
  function Textarea({ className, ...props }) {
2386
- return /* @__PURE__ */ jsx8(
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 jsx9 } from "react/jsx-runtime";
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__ */ jsx9(
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__ */ jsx9("path", { d: d2, fill: BRAND_INK }, d2))
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__ */ jsx9(
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__ */ jsx9("path", { d: d2, fill: BRAND_INK }, d2))
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 jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
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__ */ jsx10(Logo, { size: 12, className: "opacity-80" }),
2527
- /* @__PURE__ */ jsx10(Wordmark, { width: 40, className: "opacity-80" })
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 jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
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__ */ jsx11("ul", { className: "flex flex-wrap gap-1.5 px-1", children: attachments.drafts.map((item) => /* @__PURE__ */ jsx11("li", { className: "min-w-0", children: /* @__PURE__ */ jsx11(
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__ */ jsx11(
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__ */ jsx11(
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__ */ jsx11(EnvelopeSimple, { "aria-hidden": true, className: "size-4 shrink-0" }),
2648
- /* @__PURE__ */ jsx11("span", { className: "truncate", children: "Enter your email" })
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__ */ jsx11(Check, { "aria-hidden": true, className: "size-4 shrink-0" }),
2663
- /* @__PURE__ */ jsx11("span", { className: "truncate", children: "Saved" })
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__ */ jsx11(
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__ */ jsx11(
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__ */ jsx11(Plus, {})
2769
+ children: /* @__PURE__ */ jsx12(Plus, {})
2715
2770
  }
2716
2771
  ),
2717
- /* @__PURE__ */ jsx11(
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__ */ jsx11(
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__ */ jsx11(ArrowUp, {})
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__ */ jsx11(
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__ */ jsx11(
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__ */ jsx11(ArrowUp, {})
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__ */ jsx11(PoweredByMedian, {})
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 jsx12 } from "react/jsx-runtime";
2869
+ import { jsx as jsx13 } from "react/jsx-runtime";
2815
2870
  function InitialBadge({
2816
2871
  value,
2817
2872
  className
2818
2873
  }) {
2819
- return /* @__PURE__ */ jsx12(
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 jsx13 } from "react/jsx-runtime";
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__ */ jsx13(
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__ */ jsx13(
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 jsx14 } from "react/jsx-runtime";
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__ */ jsx14(
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__ */ jsx14(Sparkle, { className: "size-[55%]" })
2943
+ children: /* @__PURE__ */ jsx15(Sparkle, { className: "size-[55%]" })
2889
2944
  }
2890
2945
  );
2891
2946
  }
2892
- return /* @__PURE__ */ jsx14(
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__ */ jsx14(
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__ */ jsx14("div", { className: cn("flex items-center gap-1", className), children: team.map((agent) => /* @__PURE__ */ jsx14(WidgetAvatar, { agent, className: "size-8" }, agent.id)) });
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 jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
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__ */ jsx15(
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__ */ jsx15("p", { className: "text-base font-semibold tracking-tight", children: agent.name }),
2954
- /* @__PURE__ */ jsx15("p", { className: "text-sm text-balance text-muted-foreground", children: orgName ? `Ask me anything about ${orgName}.` : "Ask me anything." })
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__ */ jsx15("div", { className: "flex w-full flex-col gap-1.5 pt-1", children: STARTERS.map((starter, index) => /* @__PURE__ */ jsxs6(
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__ */ jsx15(starter.glyph, { className: "size-4 text-muted-foreground" }),
2971
- /* @__PURE__ */ jsx15("span", { className: "min-w-0 flex-1 truncate", children: starter.label }),
2972
- /* @__PURE__ */ jsx15(
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 jsx16, jsxs as jsxs7 } from "react/jsx-runtime";
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__ */ jsx16("h2", { className: "truncate text-base font-semibold tracking-tight", children: presence.name }),
3013
- /* @__PURE__ */ jsx16("p", { className: "truncate text-sm text-muted-foreground", children: presence.status })
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__ */ jsx16(WidgetAvatarStack, { team: presence.team }),
3071
+ /* @__PURE__ */ jsx17(WidgetAvatarStack, { team: presence.team }),
3017
3072
  /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-0.5", children: [
3018
- onToggleExpanded && /* @__PURE__ */ jsx16(
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__ */ jsx16(ArrowsIn, {}) : /* @__PURE__ */ jsx16(ArrowsOut, {})
3082
+ children: isExpanded ? /* @__PURE__ */ jsx17(ArrowsIn, {}) : /* @__PURE__ */ jsx17(ArrowsOut, {})
3028
3083
  }
3029
3084
  ),
3030
- onClose && /* @__PURE__ */ jsx16(
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__ */ jsx16(X, {})
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 jsx17 } from "react/jsx-runtime";
3104
+ import { jsx as jsx18 } from "react/jsx-runtime";
3050
3105
  function WidgetLoading() {
3051
- return /* @__PURE__ */ jsx17("div", { className: "grid min-h-0 flex-1 place-items-center p-6", children: /* @__PURE__ */ jsx17(
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 jsx18, jsxs as jsxs8 } from "react/jsx-runtime";
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__ */ jsx18("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__ */ jsx18(LockSimple, { className: "size-6 text-muted-foreground" }) }),
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__ */ jsx18("p", { className: "text-base font-semibold tracking-tight", children: "Sign in to chat" }),
3085
- /* @__PURE__ */ jsx18("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." })
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__ */ jsx18(
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__ */ jsx18(PoweredByMedian, { className: "shrink-0 px-3 pb-3" })
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 jsx19 } from "react/jsx-runtime";
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__ */ jsx19(
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 jsx20, jsxs as jsxs9 } from "react/jsx-runtime";
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__ */ jsx20(Fragment24, { children });
3146
- return /* @__PURE__ */ jsx20(
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__ */ jsx20(ImageSquare, { className: "size-5 text-muted-foreground" }),
3178
- /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: "Preview unavailable" })
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__ */ jsx20(
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__ */ jsx20(
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__ */ jsx20("span", { className: "grid size-8 place-items-center rounded-full bg-background/85 shadow-sm", children: /* @__PURE__ */ jsx20(Play, { className: "size-3.5 translate-x-px" }) })
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__ */ jsx20(OpenAttachment, { attachment, children: /* @__PURE__ */ jsxs9("div", { className: cn(SURFACE, "flex items-center gap-2 px-2 py-1.5"), children: [
3208
- /* @__PURE__ */ jsx20(File, { className: "size-4 shrink-0 text-muted-foreground" }),
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__ */ jsx20("p", { className: "truncate text-xs font-medium", children: attachment.name }),
3211
- /* @__PURE__ */ jsx20("p", { className: "truncate text-xs text-muted-foreground", children: attachment.size })
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__ */ jsx20("div", { className: cn("grid gap-1.5", media.length > 1 && "grid-cols-2"), children: media.map((attachment) => /* @__PURE__ */ jsx20(
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__ */ jsx20(MediaTile, { attachment, className: "size-full" })
3262
+ children: /* @__PURE__ */ jsx21(MediaTile, { attachment, className: "size-full" })
3227
3263
  },
3228
3264
  attachment.id
3229
3265
  )) }),
3230
- files.map((attachment) => /* @__PURE__ */ jsx20(FileRow, { attachment }, attachment.id))
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 jsx21 } from "react/jsx-runtime";
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__ */ jsx21("div", { ref: box, className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsx21("div", { ref: content, className: contentClassName, children }) });
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 jsx22 } from "react/jsx-runtime";
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__ */ jsx22(
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 jsx23 } from "react/jsx-runtime";
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__ */ jsx23("p", { className: "break-words whitespace-pre-line", children: body });
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__ */ jsx23(Suspense, { fallback: plain, children: /* @__PURE__ */ jsx23(MessageMarkdown, { body }) });
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 jsx24, jsxs as jsxs10 } from "react/jsx-runtime";
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__ */ jsx24("span", { className: "sr-only", children: label }),
3345
- DOTS.map((delay) => /* @__PURE__ */ jsx24(
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 jsx25, jsxs as jsxs11 } from "react/jsx-runtime";
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__ */ jsx25("span", { className: "h-px flex-1 bg-border" }),
3367
- /* @__PURE__ */ jsx25("span", { className: "text-xs text-muted-foreground", children: label }),
3368
- /* @__PURE__ */ jsx25("span", { className: "h-px flex-1 bg-border" })
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__ */ jsx25(VisitorMessage, { message }) : /* @__PURE__ */ jsx25(AgentMessage, { message, group });
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__ */ jsx25(
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__ */ jsx25(WidgetAttachments, { attachments: message.attachments ?? [] }),
3389
- message.body && /* @__PURE__ */ jsx25(WidgetMessageBody, { body: message.body, sender: message.sender })
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__ */ jsx25("div", { className: cn("flex justify-end", ARRIVES), children: /* @__PURE__ */ jsx25(WidgetBubble, { morphKey: "settled", className: cn(BUBBLE, VISITOR_BUBBLE), children: /* @__PURE__ */ jsx25(BubbleContent, { message }) }) });
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__ */ jsx25(WidgetAvatar, { agent, className: "size-5 rounded-md" }),
3410
- /* @__PURE__ */ jsx25("span", { className: "truncate text-xs font-medium", children: agent.name }),
3411
- agent.kind === "ai" && /* @__PURE__ */ jsx25(Badge, { variant: "muted", className: "shrink-0 rounded-md px-1", children: "AI" })
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__ */ jsx25("span", { className: "shrink-0 text-xs text-muted-foreground tabular-nums", children: message.time })
3449
+ !message.pending && /* @__PURE__ */ jsx26("span", { className: "shrink-0 text-xs text-muted-foreground tabular-nums", children: message.time })
3414
3450
  ] }),
3415
- /* @__PURE__ */ jsx25(
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__ */ jsx25(BubbleContent, { message })
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 jsx26 } from "react/jsx-runtime";
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__ */ jsx26(
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__ */ jsx26("div", { className: "overflow-hidden", children })
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 jsx27, jsxs as jsxs12 } from "react/jsx-runtime";
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__ */ jsx27(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: [
3510
- /* @__PURE__ */ jsx27(Collapse, { isOpen: !isDone, children: /* @__PURE__ */ jsxs12("div", { className: "py-2.5", children: [
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__ */ jsx27("p", { className: "text-sm font-medium", children: picked === null ? "How did we do?" : "Thanks. Tell us more?" }),
3513
- /* @__PURE__ */ jsx27(
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__ */ jsx27(
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__ */ jsx27(
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__ */ jsx27(
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__ */ jsx27(Collapse, { isOpen: picked !== null, children: /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-2 pt-2", children: [
3569
- /* @__PURE__ */ jsx27(
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__ */ jsx27(
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__ */ jsx27(Collapse, { isOpen: error !== null, children: /* @__PURE__ */ jsx27("p", { className: "pt-1.5 text-center text-xs text-destructive", children: error }) })
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__ */ jsx27(Collapse, { isOpen: isDone, children: /* @__PURE__ */ jsx27("p", { className: "py-3 text-center text-sm font-medium", children: "Thanks for the feedback." }) })
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 jsx28, jsxs as jsxs13 } from "react/jsx-runtime";
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__ */ jsx28(UserCircle, { "aria-hidden": true, className: "size-3.5" }),
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 jsx29, jsxs as jsxs14 } from "react/jsx-runtime";
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__ */ jsx29(
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__ */ jsx29(WidgetLoading, {}) : isLocked ? (
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__ */ jsx29(
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__ */ jsx29(
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__ */ jsx29(
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__ */ jsx29(MessageScrollerProvider, { children: /* @__PURE__ */ jsxs14(MessageScroller, { className: "h-auto min-h-0 flex-1", children: [
3731
- /* @__PURE__ */ jsx29(
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__ */ jsx29(
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__ */ jsx29(WidgetDivider, { message }),
3754
- /* @__PURE__ */ jsx29(WidgetMessage, { message, group: groups[index] })
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__ */ jsx29(MessageScrollerButton, {})
3799
+ /* @__PURE__ */ jsx30(MessageScrollerButton, {})
3764
3800
  ] }) })
3765
3801
  ),
3766
- rating && /* @__PURE__ */ jsx29(WidgetRating, { rating }),
3767
- awaitingHuman && /* @__PURE__ */ jsx29(WidgetAwaitingHuman, {}),
3768
- notice && /* @__PURE__ */ jsx29("p", { className: "animate-in px-4 pb-1 text-center text-xs text-destructive fade-in duration-150", children: notice }),
3769
- /* @__PURE__ */ jsx29(
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 useLayoutEffect5,
4053
- useState as useState10,
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] = useState10(false);
4109
- useLayoutEffect5(() => {
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
- useLayoutEffect5(() => {
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 jsx30, jsxs as jsxs15 } from "react/jsx-runtime";
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] = useState11(defaultOpen);
4385
+ const [uncontrolledOpen, setUncontrolledOpen] = useState13(defaultOpen);
4224
4386
  const isOpen = open ?? uncontrolledOpen;
4225
4387
  const hasBubble = launcher === "bubble";
4226
- const [isExpanded, setExpanded] = useState11(false);
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__ */ jsxs15(
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__ */ jsx30("div", { "aria-hidden": true, className: "absolute inset-0 drop-shadow-xl", children: /* @__PURE__ */ jsx30(
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__ */ jsx30(
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__ */ jsx30(
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__ */ jsxs15(
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__ */ jsx30(ChatCircleDots, { className: "size-6" }),
4437
- unreadCount > 0 && /* @__PURE__ */ jsx30(
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 useState12 } from "react";
4641
+ import { useEffect as useEffect11, useRef as useRef12, useState as useState14 } from "react";
4461
4642
  import { createPortal } from "react-dom";
4462
- import { jsx as jsx31, jsxs as jsxs16 } from "react/jsx-runtime";
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] = useState12(false);
4472
- const [isLeaving, setIsLeaving] = useState12(false);
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__ */ jsxs16(
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__ */ jsx31(
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__ */ jsx31(
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 useState13 } from "react";
4752
+ import { useEffect as useEffect12, useState as useState15 } from "react";
4572
4753
  import { createPortal as createPortal2 } from "react-dom";
4573
- import { jsx as jsx32, jsxs as jsxs17 } from "react/jsx-runtime";
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] = useState13(false);
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__ */ jsxs17(
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__ */ jsx32(WidgetAvatar, { agent, className: "size-6 rounded-full" }),
4611
- /* @__PURE__ */ jsx32("span", { className: "truncate", children })
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 useState15,
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 useState14 } from "react";
5406
+ import { useEffect as useEffect16, useState as useState16 } from "react";
5226
5407
  function useNow(intervalMs = 3e4) {
5227
- const [now, setNow] = useState14(() => Date.now());
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/read-state.ts
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 readLastSeenAt(apiKey) {
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(`${STORAGE_PREFIX3}${apiKey}`);
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(apiKey) ?? 0;
5538
+ return inMemory2.get(key) ?? 0;
5355
5539
  }
5356
5540
  }
5357
- function writeLastSeenAt(apiKey, at2) {
5541
+ function writeStamp(name, apiKey, at2) {
5358
5542
  if (typeof window === "undefined") return;
5359
- inMemory2.set(apiKey, at2);
5543
+ const key = keyOf(name, apiKey);
5544
+ inMemory2.set(key, at2);
5360
5545
  try {
5361
- window.localStorage.setItem(`${STORAGE_PREFIX3}${apiKey}`, String(at2));
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 STORAGE_PREFIX4 = "median:email:";
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(`${STORAGE_PREFIX4}${apiKey}`);
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(`${STORAGE_PREFIX4}${apiKey}`, email);
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(STORAGE_PREFIX4)) stale.push(key);
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] = useState15(false);
5486
- const [sendError, setSendError] = useState15(null);
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] = useState15(() => readLastSeenAt(apiKey));
5560
- const unreadCount = useMemo2(
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
- ).length,
5757
+ ),
5564
5758
  [messages, lastSeenAt]
5565
5759
  );
5566
- const [picked, setPicked] = useState15(null);
5567
- const [skipped, setSkipped] = useState15(
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 useState16 } from "react";
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] = useState16(null);
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 useLayoutEffect6, useRef as useRef15, useState as useState17 } from "react";
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] = useState17(null);
6357
- useLayoutEffect6(() => {
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 Fragment26, jsx as jsx33, jsxs as jsxs18 } from "react/jsx-runtime";
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__ */ jsx33(MedianSupportPreview, { ...props });
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__ */ jsx33(MedianErrorBoundary, { children: /* @__PURE__ */ jsx33(
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__ */ jsx33(
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] = useState18(() => {
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__ */ jsx33(ConvexProvider, { client: client2, children: /* @__PURE__ */ jsx33(MedianLauncher, { ...props }) });
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__ */ jsxs18(Fragment26, { children: [
6557
- direction?.selector != null && /* @__PURE__ */ jsx33(
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__ */ jsxs18(WidgetToast, { agent: mover, children: [
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__ */ jsx33(
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 jsx34 } from "react/jsx-runtime";
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__ */ jsx34(MedianSupport, { ...current2 }));
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 useCallback13, useEffect as useEffect23, useRef as useRef17, useState as useState22 } from "react";
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 { useEffect as useEffect22, useState as useState20 } from "react";
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 useLayoutEffect7, useState as useState19 } from "react";
6665
- var GAP = 8;
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] = useState19("bottom");
6685
- useLayoutEffect7(() => {
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 - GAP - MARGIN2;
6706
- const above = rect.top - GAP - MARGIN2;
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 - GAP - height : rect.bottom + GAP;
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 jsx35 } from "react/jsx-runtime";
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__ */ jsx35(
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 jsx36, jsxs as jsxs19 } from "react/jsx-runtime";
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] = useState20("");
6848
- const [isSending, setSending] = useState20(false);
6849
- const [isSent, setSent] = useState20(false);
6850
- const canSend = draft.trim().length > 0 && !isSending && !isSent;
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__ */ jsxs19(
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__ */ jsxs19("header", { className: "flex items-start gap-2", children: [
6886
- /* @__PURE__ */ jsxs19("div", { className: "flex min-w-0 flex-1 flex-col", children: [
6887
- /* @__PURE__ */ jsx36("h2", { className: "truncate text-sm font-semibold tracking-tight", children: title }),
6888
- /* @__PURE__ */ jsx36("p", { className: "text-xs text-muted-foreground", children: description })
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__ */ jsx36(
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__ */ jsx36(X, {})
7149
+ children: /* @__PURE__ */ jsx38(X, {})
6900
7150
  }
6901
7151
  )
6902
7152
  ] }),
6903
- /* @__PURE__ */ jsxs19("div", { className: "grid", children: [
6904
- /* @__PURE__ */ jsx36(Collapse, { isOpen: !isSent, children: /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-1.5", children: [
6905
- /* @__PURE__ */ jsx36(
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
- notice && /* @__PURE__ */ jsx36("p", { className: "animate-in px-0.5 text-xs text-destructive fade-in duration-150", children: notice })
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__ */ jsx36(Collapse, { isOpen: isSent, children: /* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-center gap-2 py-4 text-sm font-medium", children: [
6928
- /* @__PURE__ */ jsx36("span", { className: "grid size-5 shrink-0 place-items-center rounded-full bg-primary text-primary-foreground", children: /* @__PURE__ */ jsx36(Check, { className: "size-3" }) }),
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__ */ jsxs19("div", { className: "flex min-h-8 items-center gap-2", children: [
6933
- showBadge && /* @__PURE__ */ jsx36(PoweredByMedian, { className: "justify-start" }),
6934
- !isSent && /* @__PURE__ */ jsxs19(
6935
- WidgetButton,
6936
- {
6937
- type: "button",
6938
- disabled: !canSend,
6939
- "aria-busy": isSending,
6940
- onClick: () => void send(),
6941
- className: "relative ml-auto shrink-0 rounded-full px-3",
6942
- children: [
6943
- /* @__PURE__ */ jsx36(
6944
- "span",
6945
- {
6946
- className: cn(
6947
- "transition-opacity duration-150 motion-reduce:transition-none",
6948
- isSending && "opacity-0"
6949
- ),
6950
- children: "Submit feedback"
6951
- }
6952
- ),
6953
- isSending && /* @__PURE__ */ jsx36(
6954
- ArrowsClockwise,
6955
- {
6956
- "aria-hidden": true,
6957
- className: "absolute inset-0 m-auto animate-spin motion-reduce:animate-none"
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 useCallback12, useState as useState21, useSyncExternalStore as useSyncExternalStore12 } from "react";
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
- useCallback12(() => getOrCreateSessionId(apiKey), [apiKey]),
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] = useState21(null);
7034
- const submit = useCallback12(
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
- [apiKey, sessionId, user, telemetry, takeDiagnostics, submitNote]
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 Fragment27, jsx as jsx37, jsxs as jsxs20 } from "react/jsx-runtime";
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__ */ jsx37(MedianErrorBoundary, { children: /* @__PURE__ */ jsx37(FeedbackIdentity, { ...props }) });
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__ */ jsx37(
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] = useState22(() => {
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__ */ jsx37(ConvexProvider2, { client: client2, children: /* @__PURE__ */ jsx37(Feedback, { ...props }) });
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 = useRef17(null);
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 = useCallback13(() => setOpen(false), [setOpen]);
7155
- const [attempt, setAttempt] = useState22(0);
7156
- const hasSent = useRef17(false);
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__ */ jsxs20(Fragment27, { children: [
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__ */ jsx37(
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__ */ jsx37(
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__ */ jsx37(
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 jsx38 } from "react/jsx-runtime";
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__ */ jsx38(MedianFeedback, { ...current2 }));
7523
+ root.render(/* @__PURE__ */ jsx40(MedianFeedback, { ...current2 }));
7225
7524
  };
7226
7525
  render();
7227
7526
  return {