@linktr.ee/messaging-react 4.3.2 → 4.4.0-rc-1787598778

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/{AttachmentCard-Pc93Wcd0.js → AttachmentCard-BqwWgqvi.js} +83 -78
  2. package/dist/AttachmentCard-BqwWgqvi.js.map +1 -0
  3. package/dist/AttachmentCard-DUrgGRsq.cjs +2 -0
  4. package/dist/AttachmentCard-DUrgGRsq.cjs.map +1 -0
  5. package/dist/{Card-ByU9P9GA.cjs → Card-BIbqWagz.cjs} +2 -2
  6. package/dist/{Card-ByU9P9GA.cjs.map → Card-BIbqWagz.cjs.map} +1 -1
  7. package/dist/{Card-D__kW2E_.js → Card-f51K6V7Y.js} +20 -20
  8. package/dist/{Card-D__kW2E_.js.map → Card-f51K6V7Y.js.map} +1 -1
  9. package/dist/index.cjs +2 -2
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.ts +15 -0
  12. package/dist/index.js +1017 -969
  13. package/dist/index.js.map +1 -1
  14. package/package.json +3 -3
  15. package/src/components/AttachmentCard/MediaPlayer.tsx +2 -0
  16. package/src/components/CustomMessage/StreamAttachmentMessage.test.tsx +26 -0
  17. package/src/components/CustomMessage/StreamAttachmentMessage.tsx +31 -3
  18. package/src/components/LinkAttachment/components/_shared/CardThumbnail.tsx +2 -0
  19. package/src/components/MessageAttachment/Audio/index.tsx +2 -0
  20. package/src/components/MessageAttachment/Image/index.tsx +11 -56
  21. package/src/components/MessageAttachment/MessageAttachment.test.tsx +249 -0
  22. package/src/components/MessageAttachment/Video/VideoAttachment.stories.tsx +163 -0
  23. package/src/components/MessageAttachment/Video/index.tsx +195 -36
  24. package/src/components/MessageAttachment/_shared/MediaStackGrid.tsx +27 -3
  25. package/src/components/MessageAttachment/_shared/VideoViewer.test.tsx +68 -1
  26. package/src/components/MessageAttachment/_shared/VideoViewer.tsx +86 -25
  27. package/src/components/MessageAttachment/_shared/useSingleMediaRatio.ts +75 -0
  28. package/src/components/MessageAttachment/types.ts +9 -0
  29. package/src/utils/nativeMediaPlayers.test.ts +55 -0
  30. package/src/utils/nativeMediaPlayers.ts +41 -0
  31. package/dist/AttachmentCard-DI2chsB_.cjs +0 -2
  32. package/dist/AttachmentCard-DI2chsB_.cjs.map +0 -1
  33. package/dist/AttachmentCard-Pc93Wcd0.js.map +0 -1
@@ -23,8 +23,12 @@ function E(e) {
23
23
  return r.searchParams.get("io") === "true" && r.searchParams.get("size") === C ? t : (r.searchParams.set("io", "true"), r.searchParams.set("size", C), r.toString());
24
24
  }
25
25
  //#endregion
26
- //#region src/components/AttachmentCard/utils/mimeType.ts
27
- var D = [
26
+ //#region src/utils/nativeMediaPlayers.ts
27
+ var D = "data-mes-native-player", O = { [D]: "" }, k = (e) => {
28
+ typeof document > "u" || document.querySelectorAll(`[${D}]`).forEach((t) => {
29
+ t !== e && t.pause();
30
+ });
31
+ }, A = [
28
32
  [/pdf/, "pdf"],
29
33
  [/wordprocessingml|msword|\.doc/, "doc"],
30
34
  [/spreadsheetml|ms-excel|\.xls/, "xls"],
@@ -34,21 +38,21 @@ var D = [
34
38
  [/plain|rtf/, "text"],
35
39
  [/markdown/, "markdown"]
36
40
  ];
37
- function O(e) {
41
+ function j(e) {
38
42
  return e.startsWith("video/") ? "video" : e.startsWith("audio/") ? "audio" : e.startsWith("image/") ? "image" : "document";
39
43
  }
40
- function k(e) {
41
- let t = D.find(([t]) => t.test(e));
44
+ function M(e) {
45
+ let t = A.find(([t]) => t.test(e));
42
46
  return t ? t[1] : "generic";
43
47
  }
44
48
  //#endregion
45
49
  //#region src/components/AttachmentCard/utils/icons.ts
46
- var A = {
50
+ var N = {
47
51
  video: x,
48
52
  audio: b,
49
53
  image: _,
50
54
  document: u
51
- }, j = {
55
+ }, P = {
52
56
  pdf: f,
53
57
  doc: l,
54
58
  xls: h,
@@ -59,38 +63,38 @@ var A = {
59
63
  markdown: d,
60
64
  generic: u
61
65
  };
62
- function M(e) {
63
- let t = O(e);
64
- return t === "document" ? j[k(e)] : A[t];
66
+ function F(e) {
67
+ let t = j(e);
68
+ return t === "document" ? P[M(e)] : N[t];
65
69
  }
66
- function N(t, n) {
67
- return e.createElement(M(t), n);
70
+ function I(t, n) {
71
+ return e.createElement(F(t), n);
68
72
  }
69
73
  //#endregion
70
74
  //#region src/utils/isDevBuild.ts
71
- function P() {
75
+ function L() {
72
76
  return !1;
73
77
  }
74
78
  //#endregion
75
79
  //#region src/components/AttachmentCard/MediaPlayer.tsx
76
- var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.clientX ?? 0 : e.clientX, I = ({ source: e, mimeType: c, poster: l, autoPlay: u = !1, playing: d, loop: f = !1, controls: p = !0, showProgress: m = !1, muted: h = !1, onContainerClick: g }) => {
77
- let _ = O(c), b = r(null), x = r(null), S = r(null), C = r(d), [w, T] = i(u), [E, D] = i(0), [k, A] = i(!1), [j, M] = i(!1), [I, L] = i(!1), [R, z] = i(!1), [B, V] = i(!0), [H, U] = i(null), W = t(() => {
78
- L(!1), T(!0);
79
- }, []), G = t((e) => {
80
+ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.clientX ?? 0 : e.clientX, z = ({ source: e, mimeType: c, poster: l, autoPlay: u = !1, playing: d, loop: f = !1, controls: p = !0, showProgress: m = !1, muted: h = !1, onContainerClick: g }) => {
81
+ let _ = j(c), b = r(null), x = r(null), S = r(null), C = r(d), [w, T] = i(u), [E, D] = i(0), [k, A] = i(!1), [M, N] = i(!1), [P, F] = i(!1), [z, B] = i(!1), [V, H] = i(!0), [U, W] = i(null), G = t(() => {
82
+ F(!1), T(!0);
83
+ }, []), K = t((e) => {
80
84
  let t = x.current;
81
85
  if (!t) return 0;
82
86
  let n = t.getBoundingClientRect();
83
- return Math.max(0, Math.min(1, (F(e) - n.left) / n.width));
84
- }, []), K = t((e) => {
87
+ return Math.max(0, Math.min(1, (R(e) - n.left) / n.width));
88
+ }, []), q = t((e) => {
85
89
  let t = b.current;
86
90
  t && t.duration && (t.currentTime = e * t.duration);
87
- }, []), q = (e) => {
91
+ }, []), J = (e) => {
88
92
  e.stopPropagation(), A(!0);
89
- let t = G(e);
90
- D(t), K(t);
91
- }, J = t((e) => {
92
- e.key === "ArrowRight" && K(Math.min(1, E + .05)), e.key === "ArrowLeft" && K(Math.max(0, E - .05));
93
- }, [K, E]);
93
+ let t = K(e);
94
+ D(t), q(t);
95
+ }, Y = t((e) => {
96
+ e.key === "ArrowRight" && q(Math.min(1, E + .05)), e.key === "ArrowLeft" && q(Math.max(0, E - .05));
97
+ }, [q, E]);
94
98
  n(() => {
95
99
  d !== void 0 && d !== C.current && (C.current = d, T(d));
96
100
  }, [d]), n(() => {
@@ -108,33 +112,33 @@ var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
108
112
  }, [w, k]), n(() => {
109
113
  let e = b.current;
110
114
  e && (w ? e.play().catch((e) => {
111
- T(!1), L(!0), P() && console.debug("[MediaPlayer] play() failed", e);
115
+ T(!1), F(!0), L() && console.debug("[MediaPlayer] play() failed", e);
112
116
  }) : e.pause());
113
117
  }, [w]), n(() => {
114
118
  if (!k) return;
115
- let e = (e) => D(G(e)), t = (e) => {
116
- A(!1), K(G(e));
119
+ let e = (e) => D(K(e)), t = (e) => {
120
+ A(!1), q(K(e));
117
121
  };
118
122
  return window.addEventListener("mousemove", e), window.addEventListener("mouseup", t), window.addEventListener("touchmove", e, { passive: !0 }), window.addEventListener("touchend", t), () => {
119
123
  window.removeEventListener("mousemove", e), window.removeEventListener("mouseup", t), window.removeEventListener("touchmove", e), window.removeEventListener("touchend", t);
120
124
  };
121
125
  }, [
122
126
  k,
123
- G,
124
- K
127
+ K,
128
+ q
125
129
  ]);
126
- let Y = H ? { aspectRatio: String(H) } : void 0, X = H ? "" : " aspect-video", Z = Math.round(E * 100);
130
+ let X = U ? { aspectRatio: String(U) } : void 0, Z = U ? "" : " aspect-video", Q = Math.round(E * 100);
127
131
  return /* @__PURE__ */ o("div", {
128
132
  role: "button",
129
133
  tabIndex: 0,
130
- className: `relative cursor-pointer overflow-hidden bg-black ${X}`,
131
- style: Y,
134
+ className: `relative cursor-pointer overflow-hidden bg-black ${Z}`,
135
+ style: X,
132
136
  onClick: (e) => {
133
137
  if (g) {
134
138
  g(e);
135
139
  return;
136
140
  }
137
- I || p && T((e) => !e);
141
+ P || p && T((e) => !e);
138
142
  },
139
143
  onKeyDown: (e) => {
140
144
  if (e.key === "Enter" || e.key === " ") {
@@ -142,18 +146,18 @@ var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
142
146
  g(e);
143
147
  return;
144
148
  }
145
- I || p && T((e) => !e);
149
+ P || p && T((e) => !e);
146
150
  }
147
151
  },
148
152
  children: [
149
- l && (_ === "audio" || B) && /* @__PURE__ */ a("img", {
153
+ l && (_ === "audio" || V) && /* @__PURE__ */ a("img", {
150
154
  src: l,
151
155
  alt: "",
152
156
  className: "absolute inset-0 h-full w-full object-cover"
153
157
  }),
154
- !l && (_ === "audio" || B) && /* @__PURE__ */ a("div", {
158
+ !l && (_ === "audio" || V) && /* @__PURE__ */ a("div", {
155
159
  className: "absolute inset-0 flex items-center justify-center",
156
- children: N(c, {
160
+ children: I(c, {
157
161
  className: "size-12 text-black/20",
158
162
  weight: "regular"
159
163
  })
@@ -161,6 +165,7 @@ var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
161
165
  /* @__PURE__ */ a("div", {
162
166
  className: "absolute inset-0",
163
167
  children: _ === "audio" ? /* @__PURE__ */ a("audio", {
168
+ ...O,
164
169
  ref: b,
165
170
  src: e,
166
171
  loop: f,
@@ -169,12 +174,12 @@ var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
169
174
  width: "100%",
170
175
  height: "100%"
171
176
  },
172
- onLoadStart: () => z(!0),
177
+ onLoadStart: () => B(!0),
173
178
  onCanPlay: () => {
174
- z(!1), V(!1);
179
+ B(!1), H(!1);
175
180
  },
176
- onWaiting: () => z(!0),
177
- onPlay: () => L(!1),
181
+ onWaiting: () => B(!0),
182
+ onPlay: () => F(!1),
178
183
  onEnded: () => {
179
184
  f || (T(!1), D(0));
180
185
  },
@@ -189,15 +194,15 @@ var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
189
194
  width: "100%",
190
195
  height: "100%"
191
196
  },
192
- onLoadStart: () => z(!0),
197
+ onLoadStart: () => B(!0),
193
198
  onCanPlay: () => {
194
- z(!1), V(!1);
199
+ B(!1), H(!1);
195
200
  },
196
- onWaiting: () => z(!0),
197
- onPlay: () => L(!1),
201
+ onWaiting: () => B(!0),
202
+ onPlay: () => F(!1),
198
203
  onLoadedMetadata: () => {
199
204
  let e = b.current;
200
- e instanceof HTMLVideoElement && e.videoWidth && e.videoHeight && U(e.videoWidth / e.videoHeight);
205
+ e instanceof HTMLVideoElement && e.videoWidth && e.videoHeight && W(e.videoWidth / e.videoHeight);
201
206
  },
202
207
  onEnded: () => {
203
208
  f || (T(!1), D(0));
@@ -205,23 +210,23 @@ var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
205
210
  children: /* @__PURE__ */ a("track", { kind: "captions" })
206
211
  })
207
212
  }),
208
- R && !I && /* @__PURE__ */ a("div", {
213
+ z && !P && /* @__PURE__ */ a("div", {
209
214
  className: "absolute inset-0 z-10 flex items-center justify-center",
210
215
  children: /* @__PURE__ */ a(s, {
211
216
  className: "size-8 animate-spin text-white/80",
212
217
  weight: "bold"
213
218
  })
214
219
  }),
215
- I && !p && /* @__PURE__ */ a("div", {
220
+ P && !p && /* @__PURE__ */ a("div", {
216
221
  className: "absolute inset-0 z-30 flex cursor-pointer items-center justify-center bg-black/35",
217
222
  role: "button",
218
223
  tabIndex: 0,
219
224
  "aria-label": "Play preview",
220
225
  onClick: (e) => {
221
- e.stopPropagation(), W();
226
+ e.stopPropagation(), G();
222
227
  },
223
228
  onKeyDown: (e) => {
224
- (e.key === "Enter" || e.key === " ") && (e.preventDefault(), e.stopPropagation(), W());
229
+ (e.key === "Enter" || e.key === " ") && (e.preventDefault(), e.stopPropagation(), G());
225
230
  },
226
231
  children: /* @__PURE__ */ a("span", {
227
232
  className: "flex size-16 items-center justify-center rounded-full bg-white/20 text-white backdrop-blur-sm",
@@ -236,21 +241,21 @@ var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
236
241
  children: /* @__PURE__ */ a("div", {
237
242
  role: "slider",
238
243
  "aria-label": "Playback position",
239
- "aria-valuenow": Z,
244
+ "aria-valuenow": Q,
240
245
  "aria-valuemin": 0,
241
246
  "aria-valuemax": 100,
242
247
  tabIndex: 0,
243
248
  ref: x,
244
249
  className: "relative flex h-4 w-full cursor-pointer items-center",
245
- onMouseDown: q,
246
- onTouchStart: q,
250
+ onMouseDown: J,
251
+ onTouchStart: J,
247
252
  onClick: (e) => e.stopPropagation(),
248
- onKeyDown: J,
253
+ onKeyDown: Y,
249
254
  children: /* @__PURE__ */ a("div", {
250
255
  className: "w-full overflow-hidden rounded-full bg-white/30 h-1",
251
256
  children: /* @__PURE__ */ a("div", {
252
257
  className: "h-full rounded-full bg-white",
253
- style: { width: `${Z}%` }
258
+ style: { width: `${Q}%` }
254
259
  })
255
260
  })
256
261
  })
@@ -274,42 +279,42 @@ var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
274
279
  }), /* @__PURE__ */ o("div", {
275
280
  role: "slider",
276
281
  "aria-label": "Playback position",
277
- "aria-valuenow": Z,
282
+ "aria-valuenow": Q,
278
283
  "aria-valuemin": 0,
279
284
  "aria-valuemax": 100,
280
285
  tabIndex: 0,
281
286
  ref: x,
282
287
  className: "relative flex h-4 w-full cursor-pointer items-center",
283
- onMouseDown: q,
284
- onTouchStart: q,
288
+ onMouseDown: J,
289
+ onTouchStart: J,
285
290
  onClick: (e) => e.stopPropagation(),
286
- onMouseEnter: () => M(!0),
287
- onMouseLeave: () => M(!1),
288
- onKeyDown: J,
291
+ onMouseEnter: () => N(!0),
292
+ onMouseLeave: () => N(!1),
293
+ onKeyDown: Y,
289
294
  children: [/* @__PURE__ */ a("div", {
290
- className: `w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${j || k ? "h-1.5" : "h-1"}`,
295
+ className: `w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${M || k ? "h-1.5" : "h-1"}`,
291
296
  children: /* @__PURE__ */ a("div", {
292
297
  className: "h-full rounded-full bg-white",
293
- style: { width: `${Z}%` }
298
+ style: { width: `${Q}%` }
294
299
  })
295
300
  }), /* @__PURE__ */ a("div", {
296
- className: `absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${j || k ? "scale-100 opacity-100" : "scale-0 opacity-0"}`,
297
- style: { left: `${Z}%` }
301
+ className: `absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${M || k ? "scale-100 opacity-100" : "scale-0 opacity-0"}`,
302
+ style: { left: `${Q}%` }
298
303
  })]
299
304
  })]
300
305
  })
301
306
  ]
302
307
  });
303
- }, L = (e) => e === "dark" ? "size-12 text-white/20" : "size-12 text-black/20", R = (e) => e === "dark" ? "aspect-video overflow-hidden bg-white/10" : "aspect-video overflow-hidden bg-black/5", z = ({ mimeType: e, sourceUrl: t, thumbnailUrl: n, title: r, variant: o, mediaPlayerProps: s, containedImage: c = !1 }) => {
304
- let l = O(e), [u, d] = i(!1), f = E(t), p = E(n);
305
- return t && (l === "video" || l === "audio") ? /* @__PURE__ */ a(I, {
308
+ }, B = (e) => e === "dark" ? "size-12 text-white/20" : "size-12 text-black/20", V = (e) => e === "dark" ? "aspect-video overflow-hidden bg-white/10" : "aspect-video overflow-hidden bg-black/5", H = ({ mimeType: e, sourceUrl: t, thumbnailUrl: n, title: r, variant: o, mediaPlayerProps: s, containedImage: c = !1 }) => {
309
+ let l = j(e), [u, d] = i(!1), f = E(t), p = E(n);
310
+ return t && (l === "video" || l === "audio") ? /* @__PURE__ */ a(z, {
306
311
  source: t,
307
312
  mimeType: e,
308
313
  poster: p,
309
314
  controls: !0,
310
315
  ...s
311
316
  }) : t && l === "image" ? c ? /* @__PURE__ */ a("div", {
312
- className: `relative ${R(o)}`,
317
+ className: `relative ${V(o)}`,
313
318
  children: /* @__PURE__ */ a("img", {
314
319
  src: f ?? t,
315
320
  alt: r ?? "",
@@ -323,7 +328,7 @@ var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
323
328
  className: "block w-full",
324
329
  draggable: !1
325
330
  }) : t && l === "document" ? n ? c ? /* @__PURE__ */ a("div", {
326
- className: `relative ${R(o)}`,
331
+ className: `relative ${V(o)}`,
327
332
  children: /* @__PURE__ */ a("img", {
328
333
  src: p ?? n,
329
334
  alt: r ?? "",
@@ -338,12 +343,12 @@ var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
338
343
  draggable: !1
339
344
  }) : /* @__PURE__ */ a("div", {
340
345
  className: `flex aspect-video w-full items-center justify-center ${o === "dark" ? "bg-white/10" : "bg-black/5"}`,
341
- children: N(e, {
342
- className: L(o),
346
+ children: I(e, {
347
+ className: B(o),
343
348
  weight: "regular"
344
349
  })
345
350
  }) : n ? /* @__PURE__ */ a("div", {
346
- className: `relative ${R(o)}`,
351
+ className: `relative ${V(o)}`,
347
352
  children: /* @__PURE__ */ a("img", {
348
353
  src: p ?? n,
349
354
  alt: r ?? "",
@@ -352,13 +357,13 @@ var F = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
352
357
  })
353
358
  }) : /* @__PURE__ */ a("div", {
354
359
  className: `flex aspect-video w-full items-center justify-center ${o === "dark" ? "bg-white/10" : "bg-black/5"}`,
355
- children: N(e, {
356
- className: L(o),
360
+ children: I(e, {
361
+ className: B(o),
357
362
  weight: "regular"
358
363
  })
359
364
  });
360
365
  };
361
366
  //#endregion
362
- export { E as a, O as i, N as n, k as r, z as t };
367
+ export { O as a, j as i, I as n, k as o, M as r, E as s, H as t };
363
368
 
364
- //# sourceMappingURL=AttachmentCard-Pc93Wcd0.js.map
369
+ //# sourceMappingURL=AttachmentCard-BqwWgqvi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AttachmentCard-BqwWgqvi.js","names":[],"sources":["../src/utils/cdnImageUrl.ts","../src/utils/nativeMediaPlayers.ts","../src/components/AttachmentCard/utils/mimeType.ts","../src/components/AttachmentCard/utils/icons.ts","../src/utils/isDevBuild.ts","../src/components/AttachmentCard/MediaPlayer.tsx","../src/components/AttachmentCard/Thumbnail.tsx"],"sourcesContent":["const LINKTREE_CDN_HOSTS = ['linktr.ee']\n\nconst ATTACHMENT_IMAGE_SIZE_PRESET = 'messaging-attachment-v1_0'\n\nfunction hostnameFromUrl(url: string): string | null {\n try {\n return new URL(url).hostname.toLowerCase()\n } catch {\n return null\n }\n}\n\nfunction isLinktreeCdnHost(hostname: string): boolean {\n return LINKTREE_CDN_HOSTS.some(\n (host) => hostname === host || hostname.endsWith(`.${host}`)\n )\n}\n\nexport function optimizeMessagingAttachmentUrl(\n url: string | undefined | null\n): string | undefined {\n const trimmed = url?.trim()\n if (!trimmed) return undefined\n\n const hostname = hostnameFromUrl(trimmed)\n if (!hostname || !isLinktreeCdnHost(hostname)) return trimmed\n\n const parsedUrl = new URL(trimmed)\n const isAlreadyMessagingOptimized =\n parsedUrl.searchParams.get('io') === 'true' &&\n parsedUrl.searchParams.get('size') === ATTACHMENT_IMAGE_SIZE_PRESET\n\n if (isAlreadyMessagingOptimized) {\n return trimmed\n }\n\n parsedUrl.searchParams.set('io', 'true')\n parsedUrl.searchParams.set('size', ATTACHMENT_IMAGE_SIZE_PRESET)\n\n return parsedUrl.toString()\n}\n","/**\n * Attribute marking every native `<audio>` / `<video>` the toolkit\n * renders on a message surface, so opening one player can silence the\n * others.\n *\n * stream-chat-react's `AudioPlayerPool` — what `useActiveAudioPlayer()`\n * reads — only knows the players *it* mounts, i.e. voice recordings.\n * Everything the toolkit draws itself is a plain native element that\n * never registers there: `MessageAttachment.Audio`, a playable\n * `LinkAttachment` card, and `AttachmentCard`'s `MediaPlayer`. Pausing\n * the pool alone therefore left thread audio sounding underneath an\n * opened video viewer on the production `StreamAttachmentMessage` path,\n * which is exactly the surface the mutual exclusion exists for\n * (MES-1353).\n */\nexport const NATIVE_PLAYER_ATTRIBUTE = 'data-mes-native-player'\n\n/**\n * Spread onto a native player element to enrol it. Keyed off the\n * constant so the marker and the query below can't drift apart.\n */\nexport const nativePlayerProps = { [NATIVE_PLAYER_ATTRIBUTE]: '' } as const\n\n/**\n * Pauses every enrolled player except `except`.\n *\n * No `paused` check: pausing an already-paused element is a no-op per\n * spec, and reading `paused` first would only add a branch that jsdom\n * answers differently from a browser.\n */\nexport const pauseNativeMediaPlayers = (\n except?: HTMLMediaElement | null\n): void => {\n if (typeof document === 'undefined') return\n\n document\n .querySelectorAll<HTMLMediaElement>(`[${NATIVE_PLAYER_ATTRIBUTE}]`)\n .forEach((player) => {\n if (player !== except) player.pause()\n })\n}\n","export type AttachmentSourceType = 'image' | 'audio' | 'video' | 'document'\n\nexport type DocumentIconType =\n | 'pdf'\n | 'doc'\n | 'xls'\n | 'csv'\n | 'ppt'\n | 'zip'\n | 'text'\n | 'markdown'\n | 'generic'\n\nconst DOCUMENT_ICON_PATTERNS: Array<[RegExp, DocumentIconType]> = [\n [/pdf/, 'pdf'],\n [/wordprocessingml|msword|\\.doc/, 'doc'],\n [/spreadsheetml|ms-excel|\\.xls/, 'xls'],\n [/csv/, 'csv'],\n [/presentationml|ms-powerpoint|\\.ppt/, 'ppt'],\n [/zip|x-rar|x-7z|x-tar|x-gzip/, 'zip'],\n [/plain|rtf/, 'text'],\n [/markdown/, 'markdown'],\n]\n\nexport function getSourceType(mimeType: string): AttachmentSourceType {\n if (mimeType.startsWith('video/')) return 'video'\n if (mimeType.startsWith('audio/')) return 'audio'\n if (mimeType.startsWith('image/')) return 'image'\n return 'document'\n}\n\nexport function getDocumentIconType(mimeType: string): DocumentIconType {\n const match = DOCUMENT_ICON_PATTERNS.find(([pattern]) =>\n pattern.test(mimeType)\n )\n return match ? match[1] : 'generic'\n}\n","import {\n FileIcon,\n FileCsvIcon,\n FileDocIcon,\n FileMdIcon,\n FilePdfIcon,\n FilePptIcon,\n FileTextIcon,\n FileXlsIcon,\n FileZipIcon,\n ImageIcon,\n SpeakerHighIcon,\n VideoCameraIcon,\n IconProps,\n} from '@phosphor-icons/react'\nimport React from 'react'\n\nimport { getDocumentIconType, getSourceType } from './mimeType'\nimport type { AttachmentSourceType } from './mimeType'\n\nconst MEDIA_TYPE_ICON: Record<AttachmentSourceType, React.ElementType> = {\n video: VideoCameraIcon,\n audio: SpeakerHighIcon,\n image: ImageIcon,\n document: FileIcon,\n}\n\nconst DOCUMENT_ICON_COMPONENT = {\n pdf: FilePdfIcon,\n doc: FileDocIcon,\n xls: FileXlsIcon,\n csv: FileCsvIcon,\n ppt: FilePptIcon,\n zip: FileZipIcon,\n text: FileTextIcon,\n markdown: FileMdIcon,\n generic: FileIcon,\n} as const\n\nfunction getTypeIcon(mimeType: string): React.ElementType {\n const sourceType = getSourceType(mimeType)\n if (sourceType !== 'document') return MEDIA_TYPE_ICON[sourceType]\n return DOCUMENT_ICON_COMPONENT[getDocumentIconType(mimeType)]\n}\n\n/** Use instead of `<TypeIcon />` where TypeIcon = getTypeIcon(mime) to satisfy react-hooks/static-components. */\nexport function renderTypeIcon(\n mimeType: string,\n props: IconProps\n): React.ReactElement {\n return React.createElement(getTypeIcon(mimeType), props)\n}\n","/**\n * True in Vite dev builds (`import.meta.env.DEV`). Uses a type assertion so\n * `tsc` does not rely on ambient `ImportMeta` merging (vite/client).\n */\nexport function isDevBuild(): boolean {\n return (\n typeof import.meta !== 'undefined' &&\n (import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV === true\n )\n}\n","import { CircleNotchIcon, PauseIcon, PlayIcon } from '@phosphor-icons/react'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { isDevBuild } from '../../utils/isDevBuild'\nimport { nativePlayerProps } from '../../utils/nativeMediaPlayers'\n\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\ntype TouchEventUnion =\n MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent\n\nconst getClientXFromEvent = (e: TouchEventUnion): number => {\n if ('touches' in e) {\n return e.touches[0]?.clientX ?? e.changedTouches[0]?.clientX ?? 0\n }\n return e.clientX\n}\n\nexport interface MediaPlayerProps {\n source: string\n mimeType: string\n poster?: string\n autoPlay?: boolean\n /** Controlled playing state. When provided, syncs to internal play/pause. */\n playing?: boolean\n loop?: boolean\n controls?: boolean\n showProgress?: boolean\n /** When true, requests muted playback (helps autoplay policies on video). */\n muted?: boolean\n /**\n * When provided, overrides the default click-to-play-toggle behaviour on the\n * player container. The play/pause button (which calls stopPropagation) is\n * unaffected, so inline playback still works.\n */\n onContainerClick?: (e: React.MouseEvent) => void\n}\n\nconst MediaPlayer: React.FC<MediaPlayerProps> = ({\n source,\n mimeType,\n poster,\n autoPlay = false,\n playing: playingProp,\n loop = false,\n controls = true,\n showProgress = false,\n muted = false,\n onContainerClick,\n}) => {\n // --- Derived ---\n const sourceType = getSourceType(mimeType)\n\n // --- Refs ---\n const playerRef = useRef<HTMLMediaElement>(null)\n const trackRef = useRef<HTMLDivElement>(null)\n const rafRef = useRef<number | null>(null)\n const prevPlayingPropRef = useRef(playingProp)\n\n // --- State: playback ---\n const [playing, setPlaying] = useState(autoPlay)\n const [played, setPlayed] = useState(0)\n const [seeking, setSeeking] = useState(false)\n\n // --- State: UI ---\n const [scrubberHovered, setScrubberHovered] = useState(false)\n /** Set when autoplay/play() was rejected so user can start via gesture (no controls UI). */\n const [manualPlayRequired, setManualPlayRequired] = useState(false)\n\n // --- State: loading ---\n const [buffering, setBuffering] = useState(false)\n /** True until the first canPlay fires for the current source — hides controls/spinner behind poster. */\n const [initialLoad, setInitialLoad] = useState(true)\n const [videoAspect, setVideoAspect] = useState<number | null>(null)\n\n // --- Callbacks ---\n const startPlaybackFromGesture = useCallback(() => {\n setManualPlayRequired(false)\n setPlaying(true)\n }, [])\n\n const getFraction = useCallback((e: TouchEventUnion) => {\n const track = trackRef.current\n if (!track) return 0\n const rect = track.getBoundingClientRect()\n return Math.max(\n 0,\n Math.min(1, (getClientXFromEvent(e) - rect.left) / rect.width)\n )\n }, [])\n\n const seekTo = useCallback((fraction: number) => {\n const el = playerRef.current\n if (el && el.duration) el.currentTime = fraction * el.duration\n }, [])\n\n const handleTrackPointerDown = (\n e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>\n ) => {\n e.stopPropagation()\n setSeeking(true)\n const fraction = getFraction(e)\n setPlayed(fraction)\n seekTo(fraction)\n }\n\n const handleScrubberKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'ArrowRight') seekTo(Math.min(1, played + 0.05))\n if (e.key === 'ArrowLeft') seekTo(Math.max(0, played - 0.05))\n },\n [seekTo, played]\n )\n\n // --- Effects ---\n\n // Sync controlled playing prop to internal state\n useEffect(() => {\n if (\n playingProp !== undefined &&\n playingProp !== prevPlayingPropRef.current\n ) {\n prevPlayingPropRef.current = playingProp\n setPlaying(playingProp)\n }\n }, [playingProp])\n\n // RAF-driven progress updates\n useEffect(() => {\n if (!playing) {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n return\n }\n const tick = () => {\n const el = playerRef.current\n if (el && el.duration && !seeking) setPlayed(el.currentTime / el.duration)\n rafRef.current = requestAnimationFrame(tick)\n }\n rafRef.current = requestAnimationFrame(tick)\n return () => {\n if (rafRef.current !== null) cancelAnimationFrame(rafRef.current)\n }\n }, [playing, seeking])\n\n // ReactPlayer v3 uses native HTML media elements and does not support a\n // declarative `playing` prop — playback must be driven imperatively.\n useEffect(() => {\n const el = playerRef.current\n if (!el) return\n if (playing) {\n void el.play().catch((err) => {\n setPlaying(false)\n setManualPlayRequired(true)\n if (isDevBuild()) {\n console.debug('[MediaPlayer] play() failed', err)\n }\n })\n } else {\n el.pause()\n }\n }, [playing])\n\n // Global seeking listeners\n useEffect(() => {\n if (!seeking) return\n const onMove = (e: MouseEvent | TouchEvent) => setPlayed(getFraction(e))\n const onUp = (e: MouseEvent | TouchEvent) => {\n setSeeking(false)\n seekTo(getFraction(e))\n }\n window.addEventListener('mousemove', onMove)\n window.addEventListener('mouseup', onUp)\n window.addEventListener('touchmove', onMove, { passive: true })\n window.addEventListener('touchend', onUp)\n return () => {\n window.removeEventListener('mousemove', onMove)\n window.removeEventListener('mouseup', onUp)\n window.removeEventListener('touchmove', onMove)\n window.removeEventListener('touchend', onUp)\n }\n }, [seeking, getFraction, seekTo])\n\n // --- Derived render values ---\n // Use natural aspect ratio once metadata loads, fall back to 16:9 before then.\n const aspectStyle = videoAspect\n ? { aspectRatio: String(videoAspect) }\n : undefined\n const aspectClass = !videoAspect ? ' aspect-video' : ''\n const scrubberPercent = Math.round(played * 100)\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n className={`relative cursor-pointer overflow-hidden bg-black ${aspectClass}`}\n style={aspectStyle}\n onClick={(e) => {\n if (onContainerClick) {\n onContainerClick(e)\n return\n }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n if (onContainerClick) {\n onContainerClick(e as unknown as React.MouseEvent)\n return\n }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n >\n {/* For audio, poster persists as a visual background. For video, hide once loaded. */}\n {poster && (sourceType === 'audio' || initialLoad) && (\n <img\n src={poster}\n alt=\"\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n )}\n {!poster && (sourceType === 'audio' || initialLoad) && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <div className=\"absolute inset-0\">\n {sourceType === 'audio' ? (\n <audio\n {...nativePlayerProps}\n ref={playerRef as React.RefObject<HTMLAudioElement>}\n src={source}\n loop={loop}\n muted={muted}\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </audio>\n ) : (\n <video\n ref={playerRef as React.RefObject<HTMLVideoElement>}\n src={source}\n loop={loop}\n muted={muted}\n playsInline\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onLoadedMetadata={() => {\n const el = playerRef.current\n if (\n el instanceof HTMLVideoElement &&\n el.videoWidth &&\n el.videoHeight\n ) {\n setVideoAspect(el.videoWidth / el.videoHeight)\n }\n }}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </video>\n )}\n </div>\n\n {buffering && !manualPlayRequired && (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center\">\n <CircleNotchIcon\n className=\"size-8 animate-spin text-white/80\"\n weight=\"bold\"\n />\n </div>\n )}\n\n {manualPlayRequired && !controls && (\n <div\n className=\"absolute inset-0 z-30 flex cursor-pointer items-center justify-center bg-black/35\"\n role=\"button\"\n tabIndex={0}\n aria-label=\"Play preview\"\n onClick={(e) => {\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n >\n <span className=\"flex size-16 items-center justify-center rounded-full bg-white/20 text-white backdrop-blur-sm\">\n <PlayIcon className=\"size-9 translate-x-0.5\" weight=\"fill\" />\n </span>\n </div>\n )}\n\n {showProgress && !controls && (\n <div className=\"absolute inset-x-0 bottom-0 px-3 pb-2.5 pt-6 bg-gradient-to-t from-black/40 to-transparent\">\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={handleScrubberKeyDown}\n >\n <div className=\"w-full overflow-hidden rounded-full bg-white/30 h-1\">\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n </div>\n )}\n\n {controls && (\n <div className=\"absolute inset-x-0 bottom-0 flex items-center gap-2 bg-gradient-to-t from-black/60 to-transparent px-3 pb-2.5 pt-6 transition-all duration-200\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n setPlaying((p) => !p)\n }}\n className=\"shrink-0 text-white\"\n aria-label={playing ? 'Pause' : 'Play'}\n >\n {playing ? (\n <PauseIcon className=\"size-5\" weight=\"fill\" />\n ) : (\n <PlayIcon className=\"size-5 translate-x-px\" weight=\"fill\" />\n )}\n </button>\n\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onMouseEnter={() => setScrubberHovered(true)}\n onMouseLeave={() => setScrubberHovered(false)}\n onKeyDown={handleScrubberKeyDown}\n >\n <div\n className={`w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${scrubberHovered || seeking ? 'h-1.5' : 'h-1'}`}\n >\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n <div\n className={`absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${scrubberHovered || seeking ? 'scale-100 opacity-100' : 'scale-0 opacity-0'}`}\n style={{ left: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default MediaPlayer\n","import React, { useState } from 'react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../utils/cdnImageUrl'\n\nimport MediaPlayer, { type MediaPlayerProps } from './MediaPlayer'\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\nexport type AttachmentThumbnailVariant = 'light' | 'dark'\n\nexport interface AttachmentThumbnailProps {\n mimeType: string\n sourceUrl?: string\n thumbnailUrl?: string\n title?: string\n variant: AttachmentThumbnailVariant\n /** Extra props passed to MediaPlayer when source is video or audio. */\n mediaPlayerProps?: Partial<\n Pick<\n MediaPlayerProps,\n 'autoPlay' | 'loop' | 'muted' | 'controls' | 'onContainerClick'\n >\n >\n /**\n * When true (Visitor unlocked image/document), use aspect-video + object-contain fade-in.\n */\n containedImage?: boolean\n}\n\nconst placeholderIconClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark' ? 'size-12 text-white/20' : 'size-12 text-black/20'\n\nconst posterShellClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark'\n ? 'aspect-video overflow-hidden bg-white/10'\n : 'aspect-video overflow-hidden bg-black/5'\n\n/**\n * Renders the media preview area for attachment cards (LockedAttachment, MediaMessage).\n * Overlays (dim, lock, eye toggle) are composed by the parent.\n */\nconst AttachmentThumbnail: React.FC<AttachmentThumbnailProps> = ({\n mimeType,\n sourceUrl,\n thumbnailUrl,\n title,\n variant,\n mediaPlayerProps,\n containedImage = false,\n}) => {\n const sourceType = getSourceType(mimeType)\n const [sourceReady, setSourceReady] = useState(false)\n const optimizedSourceUrl = optimizeMessagingAttachmentUrl(sourceUrl)\n const optimizedThumbnailUrl = optimizeMessagingAttachmentUrl(thumbnailUrl)\n\n if (sourceUrl && (sourceType === 'video' || sourceType === 'audio')) {\n return (\n <MediaPlayer\n source={sourceUrl}\n mimeType={mimeType}\n poster={optimizedThumbnailUrl}\n controls\n {...mediaPlayerProps}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'image') {\n if (containedImage) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'document') {\n if (thumbnailUrl) {\n if (containedImage) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt=\"\"\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n }\n\n // Poster-only or empty (no sourceUrl)\n if (thumbnailUrl) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n draggable={false}\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n </div>\n )\n }\n\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n}\n\nexport default AttachmentThumbnail\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require("./rolldown-runtime-BocRIvOZ.cjs");let t=require("react");t=e.t(t,1);let n=require("react/jsx-runtime"),r=require("classnames");r=e.t(r,1);let i=require("@phosphor-icons/react");var a=[`linktr.ee`],o=`messaging-attachment-v1_0`;function s(e){try{return new URL(e).hostname.toLowerCase()}catch{return null}}function c(e){return a.some(t=>e===t||e.endsWith(`.${t}`))}function l(e){let t=e?.trim();if(!t)return;let n=s(t);if(!n||!c(n))return t;let r=new URL(t);return r.searchParams.get(`io`)===`true`&&r.searchParams.get(`size`)===o?t:(r.searchParams.set(`io`,`true`),r.searchParams.set(`size`,o),r.toString())}var u=`data-mes-native-player`,d={[u]:``},f=e=>{typeof document>`u`||document.querySelectorAll(`[${u}]`).forEach(t=>{t!==e&&t.pause()})},p=[[/pdf/,`pdf`],[/wordprocessingml|msword|\.doc/,`doc`],[/spreadsheetml|ms-excel|\.xls/,`xls`],[/csv/,`csv`],[/presentationml|ms-powerpoint|\.ppt/,`ppt`],[/zip|x-rar|x-7z|x-tar|x-gzip/,`zip`],[/plain|rtf/,`text`],[/markdown/,`markdown`]];function m(e){return e.startsWith(`video/`)?`video`:e.startsWith(`audio/`)?`audio`:e.startsWith(`image/`)?`image`:`document`}function h(e){let t=p.find(([t])=>t.test(e));return t?t[1]:`generic`}var g={video:i.VideoCameraIcon,audio:i.SpeakerHighIcon,image:i.ImageIcon,document:i.FileIcon},_={pdf:i.FilePdfIcon,doc:i.FileDocIcon,xls:i.FileXlsIcon,csv:i.FileCsvIcon,ppt:i.FilePptIcon,zip:i.FileZipIcon,text:i.FileTextIcon,markdown:i.FileMdIcon,generic:i.FileIcon};function v(e){let t=m(e);return t===`document`?_[h(e)]:g[t]}function y(e,n){return t.default.createElement(v(e),n)}function b(){return!1}var x=e=>`touches`in e?e.touches[0]?.clientX??e.changedTouches[0]?.clientX??0:e.clientX,S=({source:e,mimeType:r,poster:a,autoPlay:o=!1,playing:s,loop:c=!1,controls:l=!0,showProgress:u=!1,muted:f=!1,onContainerClick:p})=>{let h=m(r),g=(0,t.useRef)(null),_=(0,t.useRef)(null),v=(0,t.useRef)(null),S=(0,t.useRef)(s),[C,w]=(0,t.useState)(o),[T,E]=(0,t.useState)(0),[D,O]=(0,t.useState)(!1),[k,A]=(0,t.useState)(!1),[j,M]=(0,t.useState)(!1),[N,P]=(0,t.useState)(!1),[F,I]=(0,t.useState)(!0),[L,R]=(0,t.useState)(null),z=(0,t.useCallback)(()=>{M(!1),w(!0)},[]),B=(0,t.useCallback)(e=>{let t=_.current;if(!t)return 0;let n=t.getBoundingClientRect();return Math.max(0,Math.min(1,(x(e)-n.left)/n.width))},[]),V=(0,t.useCallback)(e=>{let t=g.current;t&&t.duration&&(t.currentTime=e*t.duration)},[]),H=e=>{e.stopPropagation(),O(!0);let t=B(e);E(t),V(t)},U=(0,t.useCallback)(e=>{e.key===`ArrowRight`&&V(Math.min(1,T+.05)),e.key===`ArrowLeft`&&V(Math.max(0,T-.05))},[V,T]);(0,t.useEffect)(()=>{s!==void 0&&s!==S.current&&(S.current=s,w(s))},[s]),(0,t.useEffect)(()=>{if(!C){v.current!==null&&(cancelAnimationFrame(v.current),v.current=null);return}let e=()=>{let t=g.current;t&&t.duration&&!D&&E(t.currentTime/t.duration),v.current=requestAnimationFrame(e)};return v.current=requestAnimationFrame(e),()=>{v.current!==null&&cancelAnimationFrame(v.current)}},[C,D]),(0,t.useEffect)(()=>{let e=g.current;e&&(C?e.play().catch(e=>{w(!1),M(!0),b()&&console.debug(`[MediaPlayer] play() failed`,e)}):e.pause())},[C]),(0,t.useEffect)(()=>{if(!D)return;let e=e=>E(B(e)),t=e=>{O(!1),V(B(e))};return window.addEventListener(`mousemove`,e),window.addEventListener(`mouseup`,t),window.addEventListener(`touchmove`,e,{passive:!0}),window.addEventListener(`touchend`,t),()=>{window.removeEventListener(`mousemove`,e),window.removeEventListener(`mouseup`,t),window.removeEventListener(`touchmove`,e),window.removeEventListener(`touchend`,t)}},[D,B,V]);let W=L?{aspectRatio:String(L)}:void 0,G=L?``:` aspect-video`,K=Math.round(T*100);return(0,n.jsxs)(`div`,{role:`button`,tabIndex:0,className:`relative cursor-pointer overflow-hidden bg-black ${G}`,style:W,onClick:e=>{if(p){p(e);return}j||l&&w(e=>!e)},onKeyDown:e=>{if(e.key===`Enter`||e.key===` `){if(e.preventDefault(),p){p(e);return}j||l&&w(e=>!e)}},children:[a&&(h===`audio`||F)&&(0,n.jsx)(`img`,{src:a,alt:``,className:`absolute inset-0 h-full w-full object-cover`}),!a&&(h===`audio`||F)&&(0,n.jsx)(`div`,{className:`absolute inset-0 flex items-center justify-center`,children:y(r,{className:`size-12 text-black/20`,weight:`regular`})}),(0,n.jsx)(`div`,{className:`absolute inset-0`,children:h===`audio`?(0,n.jsx)(`audio`,{...d,ref:g,src:e,loop:c,muted:f,style:{width:`100%`,height:`100%`},onLoadStart:()=>P(!0),onCanPlay:()=>{P(!1),I(!1)},onWaiting:()=>P(!0),onPlay:()=>M(!1),onEnded:()=>{c||(w(!1),E(0))},children:(0,n.jsx)(`track`,{kind:`captions`})}):(0,n.jsx)(`video`,{ref:g,src:e,loop:c,muted:f,playsInline:!0,style:{width:`100%`,height:`100%`},onLoadStart:()=>P(!0),onCanPlay:()=>{P(!1),I(!1)},onWaiting:()=>P(!0),onPlay:()=>M(!1),onLoadedMetadata:()=>{let e=g.current;e instanceof HTMLVideoElement&&e.videoWidth&&e.videoHeight&&R(e.videoWidth/e.videoHeight)},onEnded:()=>{c||(w(!1),E(0))},children:(0,n.jsx)(`track`,{kind:`captions`})})}),N&&!j&&(0,n.jsx)(`div`,{className:`absolute inset-0 z-10 flex items-center justify-center`,children:(0,n.jsx)(i.CircleNotchIcon,{className:`size-8 animate-spin text-white/80`,weight:`bold`})}),j&&!l&&(0,n.jsx)(`div`,{className:`absolute inset-0 z-30 flex cursor-pointer items-center justify-center bg-black/35`,role:`button`,tabIndex:0,"aria-label":`Play preview`,onClick:e=>{e.stopPropagation(),z()},onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),e.stopPropagation(),z())},children:(0,n.jsx)(`span`,{className:`flex size-16 items-center justify-center rounded-full bg-white/20 text-white backdrop-blur-sm`,children:(0,n.jsx)(i.PlayIcon,{className:`size-9 translate-x-0.5`,weight:`fill`})})}),u&&!l&&(0,n.jsx)(`div`,{className:`absolute inset-x-0 bottom-0 px-3 pb-2.5 pt-6 bg-gradient-to-t from-black/40 to-transparent`,children:(0,n.jsx)(`div`,{role:`slider`,"aria-label":`Playback position`,"aria-valuenow":K,"aria-valuemin":0,"aria-valuemax":100,tabIndex:0,ref:_,className:`relative flex h-4 w-full cursor-pointer items-center`,onMouseDown:H,onTouchStart:H,onClick:e=>e.stopPropagation(),onKeyDown:U,children:(0,n.jsx)(`div`,{className:`w-full overflow-hidden rounded-full bg-white/30 h-1`,children:(0,n.jsx)(`div`,{className:`h-full rounded-full bg-white`,style:{width:`${K}%`}})})})}),l&&(0,n.jsxs)(`div`,{className:`absolute inset-x-0 bottom-0 flex items-center gap-2 bg-gradient-to-t from-black/60 to-transparent px-3 pb-2.5 pt-6 transition-all duration-200`,children:[(0,n.jsx)(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),w(e=>!e)},className:`shrink-0 text-white`,"aria-label":C?`Pause`:`Play`,children:C?(0,n.jsx)(i.PauseIcon,{className:`size-5`,weight:`fill`}):(0,n.jsx)(i.PlayIcon,{className:`size-5 translate-x-px`,weight:`fill`})}),(0,n.jsxs)(`div`,{role:`slider`,"aria-label":`Playback position`,"aria-valuenow":K,"aria-valuemin":0,"aria-valuemax":100,tabIndex:0,ref:_,className:`relative flex h-4 w-full cursor-pointer items-center`,onMouseDown:H,onTouchStart:H,onClick:e=>e.stopPropagation(),onMouseEnter:()=>A(!0),onMouseLeave:()=>A(!1),onKeyDown:U,children:[(0,n.jsx)(`div`,{className:`w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${k||D?`h-1.5`:`h-1`}`,children:(0,n.jsx)(`div`,{className:`h-full rounded-full bg-white`,style:{width:`${K}%`}})}),(0,n.jsx)(`div`,{className:`absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${k||D?`scale-100 opacity-100`:`scale-0 opacity-0`}`,style:{left:`${K}%`}})]})]})]})},C=e=>e===`dark`?`size-12 text-white/20`:`size-12 text-black/20`,w=e=>e===`dark`?`aspect-video overflow-hidden bg-white/10`:`aspect-video overflow-hidden bg-black/5`,T=({mimeType:e,sourceUrl:r,thumbnailUrl:i,title:a,variant:o,mediaPlayerProps:s,containedImage:c=!1})=>{let u=m(e),[d,f]=(0,t.useState)(!1),p=l(r),h=l(i);return r&&(u===`video`||u===`audio`)?(0,n.jsx)(S,{source:r,mimeType:e,poster:h,controls:!0,...s}):r&&u===`image`?c?(0,n.jsx)(`div`,{className:`relative ${w(o)}`,children:(0,n.jsx)(`img`,{src:p??r,alt:a??``,className:`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${d?`opacity-100`:`opacity-0`}`,draggable:!1,onLoad:()=>f(!0)})}):(0,n.jsx)(`img`,{src:p??r,alt:a??``,className:`block w-full`,draggable:!1}):r&&u===`document`?i?c?(0,n.jsx)(`div`,{className:`relative ${w(o)}`,children:(0,n.jsx)(`img`,{src:h??i,alt:a??``,className:`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${d?`opacity-100`:`opacity-0`}`,draggable:!1,onLoad:()=>f(!0)})}):(0,n.jsx)(`img`,{src:h??i,alt:``,className:`block w-full`,draggable:!1}):(0,n.jsx)(`div`,{className:`flex aspect-video w-full items-center justify-center ${o===`dark`?`bg-white/10`:`bg-black/5`}`,children:y(e,{className:C(o),weight:`regular`})}):i?(0,n.jsx)(`div`,{className:`relative ${w(o)}`,children:(0,n.jsx)(`img`,{src:h??i,alt:a??``,draggable:!1,className:`absolute inset-0 h-full w-full object-cover`})}):(0,n.jsx)(`div`,{className:`flex aspect-video w-full items-center justify-center ${o===`dark`?`bg-white/10`:`bg-black/5`}`,children:y(e,{className:C(o),weight:`regular`})})};Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return T}});
2
+ //# sourceMappingURL=AttachmentCard-DUrgGRsq.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AttachmentCard-DUrgGRsq.cjs","names":[],"sources":["../src/utils/cdnImageUrl.ts","../src/utils/nativeMediaPlayers.ts","../src/components/AttachmentCard/utils/mimeType.ts","../src/components/AttachmentCard/utils/icons.ts","../src/utils/isDevBuild.ts","../src/components/AttachmentCard/MediaPlayer.tsx","../src/components/AttachmentCard/Thumbnail.tsx"],"sourcesContent":["const LINKTREE_CDN_HOSTS = ['linktr.ee']\n\nconst ATTACHMENT_IMAGE_SIZE_PRESET = 'messaging-attachment-v1_0'\n\nfunction hostnameFromUrl(url: string): string | null {\n try {\n return new URL(url).hostname.toLowerCase()\n } catch {\n return null\n }\n}\n\nfunction isLinktreeCdnHost(hostname: string): boolean {\n return LINKTREE_CDN_HOSTS.some(\n (host) => hostname === host || hostname.endsWith(`.${host}`)\n )\n}\n\nexport function optimizeMessagingAttachmentUrl(\n url: string | undefined | null\n): string | undefined {\n const trimmed = url?.trim()\n if (!trimmed) return undefined\n\n const hostname = hostnameFromUrl(trimmed)\n if (!hostname || !isLinktreeCdnHost(hostname)) return trimmed\n\n const parsedUrl = new URL(trimmed)\n const isAlreadyMessagingOptimized =\n parsedUrl.searchParams.get('io') === 'true' &&\n parsedUrl.searchParams.get('size') === ATTACHMENT_IMAGE_SIZE_PRESET\n\n if (isAlreadyMessagingOptimized) {\n return trimmed\n }\n\n parsedUrl.searchParams.set('io', 'true')\n parsedUrl.searchParams.set('size', ATTACHMENT_IMAGE_SIZE_PRESET)\n\n return parsedUrl.toString()\n}\n","/**\n * Attribute marking every native `<audio>` / `<video>` the toolkit\n * renders on a message surface, so opening one player can silence the\n * others.\n *\n * stream-chat-react's `AudioPlayerPool` — what `useActiveAudioPlayer()`\n * reads — only knows the players *it* mounts, i.e. voice recordings.\n * Everything the toolkit draws itself is a plain native element that\n * never registers there: `MessageAttachment.Audio`, a playable\n * `LinkAttachment` card, and `AttachmentCard`'s `MediaPlayer`. Pausing\n * the pool alone therefore left thread audio sounding underneath an\n * opened video viewer on the production `StreamAttachmentMessage` path,\n * which is exactly the surface the mutual exclusion exists for\n * (MES-1353).\n */\nexport const NATIVE_PLAYER_ATTRIBUTE = 'data-mes-native-player'\n\n/**\n * Spread onto a native player element to enrol it. Keyed off the\n * constant so the marker and the query below can't drift apart.\n */\nexport const nativePlayerProps = { [NATIVE_PLAYER_ATTRIBUTE]: '' } as const\n\n/**\n * Pauses every enrolled player except `except`.\n *\n * No `paused` check: pausing an already-paused element is a no-op per\n * spec, and reading `paused` first would only add a branch that jsdom\n * answers differently from a browser.\n */\nexport const pauseNativeMediaPlayers = (\n except?: HTMLMediaElement | null\n): void => {\n if (typeof document === 'undefined') return\n\n document\n .querySelectorAll<HTMLMediaElement>(`[${NATIVE_PLAYER_ATTRIBUTE}]`)\n .forEach((player) => {\n if (player !== except) player.pause()\n })\n}\n","export type AttachmentSourceType = 'image' | 'audio' | 'video' | 'document'\n\nexport type DocumentIconType =\n | 'pdf'\n | 'doc'\n | 'xls'\n | 'csv'\n | 'ppt'\n | 'zip'\n | 'text'\n | 'markdown'\n | 'generic'\n\nconst DOCUMENT_ICON_PATTERNS: Array<[RegExp, DocumentIconType]> = [\n [/pdf/, 'pdf'],\n [/wordprocessingml|msword|\\.doc/, 'doc'],\n [/spreadsheetml|ms-excel|\\.xls/, 'xls'],\n [/csv/, 'csv'],\n [/presentationml|ms-powerpoint|\\.ppt/, 'ppt'],\n [/zip|x-rar|x-7z|x-tar|x-gzip/, 'zip'],\n [/plain|rtf/, 'text'],\n [/markdown/, 'markdown'],\n]\n\nexport function getSourceType(mimeType: string): AttachmentSourceType {\n if (mimeType.startsWith('video/')) return 'video'\n if (mimeType.startsWith('audio/')) return 'audio'\n if (mimeType.startsWith('image/')) return 'image'\n return 'document'\n}\n\nexport function getDocumentIconType(mimeType: string): DocumentIconType {\n const match = DOCUMENT_ICON_PATTERNS.find(([pattern]) =>\n pattern.test(mimeType)\n )\n return match ? match[1] : 'generic'\n}\n","import {\n FileIcon,\n FileCsvIcon,\n FileDocIcon,\n FileMdIcon,\n FilePdfIcon,\n FilePptIcon,\n FileTextIcon,\n FileXlsIcon,\n FileZipIcon,\n ImageIcon,\n SpeakerHighIcon,\n VideoCameraIcon,\n IconProps,\n} from '@phosphor-icons/react'\nimport React from 'react'\n\nimport { getDocumentIconType, getSourceType } from './mimeType'\nimport type { AttachmentSourceType } from './mimeType'\n\nconst MEDIA_TYPE_ICON: Record<AttachmentSourceType, React.ElementType> = {\n video: VideoCameraIcon,\n audio: SpeakerHighIcon,\n image: ImageIcon,\n document: FileIcon,\n}\n\nconst DOCUMENT_ICON_COMPONENT = {\n pdf: FilePdfIcon,\n doc: FileDocIcon,\n xls: FileXlsIcon,\n csv: FileCsvIcon,\n ppt: FilePptIcon,\n zip: FileZipIcon,\n text: FileTextIcon,\n markdown: FileMdIcon,\n generic: FileIcon,\n} as const\n\nfunction getTypeIcon(mimeType: string): React.ElementType {\n const sourceType = getSourceType(mimeType)\n if (sourceType !== 'document') return MEDIA_TYPE_ICON[sourceType]\n return DOCUMENT_ICON_COMPONENT[getDocumentIconType(mimeType)]\n}\n\n/** Use instead of `<TypeIcon />` where TypeIcon = getTypeIcon(mime) to satisfy react-hooks/static-components. */\nexport function renderTypeIcon(\n mimeType: string,\n props: IconProps\n): React.ReactElement {\n return React.createElement(getTypeIcon(mimeType), props)\n}\n","/**\n * True in Vite dev builds (`import.meta.env.DEV`). Uses a type assertion so\n * `tsc` does not rely on ambient `ImportMeta` merging (vite/client).\n */\nexport function isDevBuild(): boolean {\n return (\n typeof import.meta !== 'undefined' &&\n (import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV === true\n )\n}\n","import { CircleNotchIcon, PauseIcon, PlayIcon } from '@phosphor-icons/react'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { isDevBuild } from '../../utils/isDevBuild'\nimport { nativePlayerProps } from '../../utils/nativeMediaPlayers'\n\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\ntype TouchEventUnion =\n MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent\n\nconst getClientXFromEvent = (e: TouchEventUnion): number => {\n if ('touches' in e) {\n return e.touches[0]?.clientX ?? e.changedTouches[0]?.clientX ?? 0\n }\n return e.clientX\n}\n\nexport interface MediaPlayerProps {\n source: string\n mimeType: string\n poster?: string\n autoPlay?: boolean\n /** Controlled playing state. When provided, syncs to internal play/pause. */\n playing?: boolean\n loop?: boolean\n controls?: boolean\n showProgress?: boolean\n /** When true, requests muted playback (helps autoplay policies on video). */\n muted?: boolean\n /**\n * When provided, overrides the default click-to-play-toggle behaviour on the\n * player container. The play/pause button (which calls stopPropagation) is\n * unaffected, so inline playback still works.\n */\n onContainerClick?: (e: React.MouseEvent) => void\n}\n\nconst MediaPlayer: React.FC<MediaPlayerProps> = ({\n source,\n mimeType,\n poster,\n autoPlay = false,\n playing: playingProp,\n loop = false,\n controls = true,\n showProgress = false,\n muted = false,\n onContainerClick,\n}) => {\n // --- Derived ---\n const sourceType = getSourceType(mimeType)\n\n // --- Refs ---\n const playerRef = useRef<HTMLMediaElement>(null)\n const trackRef = useRef<HTMLDivElement>(null)\n const rafRef = useRef<number | null>(null)\n const prevPlayingPropRef = useRef(playingProp)\n\n // --- State: playback ---\n const [playing, setPlaying] = useState(autoPlay)\n const [played, setPlayed] = useState(0)\n const [seeking, setSeeking] = useState(false)\n\n // --- State: UI ---\n const [scrubberHovered, setScrubberHovered] = useState(false)\n /** Set when autoplay/play() was rejected so user can start via gesture (no controls UI). */\n const [manualPlayRequired, setManualPlayRequired] = useState(false)\n\n // --- State: loading ---\n const [buffering, setBuffering] = useState(false)\n /** True until the first canPlay fires for the current source — hides controls/spinner behind poster. */\n const [initialLoad, setInitialLoad] = useState(true)\n const [videoAspect, setVideoAspect] = useState<number | null>(null)\n\n // --- Callbacks ---\n const startPlaybackFromGesture = useCallback(() => {\n setManualPlayRequired(false)\n setPlaying(true)\n }, [])\n\n const getFraction = useCallback((e: TouchEventUnion) => {\n const track = trackRef.current\n if (!track) return 0\n const rect = track.getBoundingClientRect()\n return Math.max(\n 0,\n Math.min(1, (getClientXFromEvent(e) - rect.left) / rect.width)\n )\n }, [])\n\n const seekTo = useCallback((fraction: number) => {\n const el = playerRef.current\n if (el && el.duration) el.currentTime = fraction * el.duration\n }, [])\n\n const handleTrackPointerDown = (\n e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>\n ) => {\n e.stopPropagation()\n setSeeking(true)\n const fraction = getFraction(e)\n setPlayed(fraction)\n seekTo(fraction)\n }\n\n const handleScrubberKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'ArrowRight') seekTo(Math.min(1, played + 0.05))\n if (e.key === 'ArrowLeft') seekTo(Math.max(0, played - 0.05))\n },\n [seekTo, played]\n )\n\n // --- Effects ---\n\n // Sync controlled playing prop to internal state\n useEffect(() => {\n if (\n playingProp !== undefined &&\n playingProp !== prevPlayingPropRef.current\n ) {\n prevPlayingPropRef.current = playingProp\n setPlaying(playingProp)\n }\n }, [playingProp])\n\n // RAF-driven progress updates\n useEffect(() => {\n if (!playing) {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n return\n }\n const tick = () => {\n const el = playerRef.current\n if (el && el.duration && !seeking) setPlayed(el.currentTime / el.duration)\n rafRef.current = requestAnimationFrame(tick)\n }\n rafRef.current = requestAnimationFrame(tick)\n return () => {\n if (rafRef.current !== null) cancelAnimationFrame(rafRef.current)\n }\n }, [playing, seeking])\n\n // ReactPlayer v3 uses native HTML media elements and does not support a\n // declarative `playing` prop — playback must be driven imperatively.\n useEffect(() => {\n const el = playerRef.current\n if (!el) return\n if (playing) {\n void el.play().catch((err) => {\n setPlaying(false)\n setManualPlayRequired(true)\n if (isDevBuild()) {\n console.debug('[MediaPlayer] play() failed', err)\n }\n })\n } else {\n el.pause()\n }\n }, [playing])\n\n // Global seeking listeners\n useEffect(() => {\n if (!seeking) return\n const onMove = (e: MouseEvent | TouchEvent) => setPlayed(getFraction(e))\n const onUp = (e: MouseEvent | TouchEvent) => {\n setSeeking(false)\n seekTo(getFraction(e))\n }\n window.addEventListener('mousemove', onMove)\n window.addEventListener('mouseup', onUp)\n window.addEventListener('touchmove', onMove, { passive: true })\n window.addEventListener('touchend', onUp)\n return () => {\n window.removeEventListener('mousemove', onMove)\n window.removeEventListener('mouseup', onUp)\n window.removeEventListener('touchmove', onMove)\n window.removeEventListener('touchend', onUp)\n }\n }, [seeking, getFraction, seekTo])\n\n // --- Derived render values ---\n // Use natural aspect ratio once metadata loads, fall back to 16:9 before then.\n const aspectStyle = videoAspect\n ? { aspectRatio: String(videoAspect) }\n : undefined\n const aspectClass = !videoAspect ? ' aspect-video' : ''\n const scrubberPercent = Math.round(played * 100)\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n className={`relative cursor-pointer overflow-hidden bg-black ${aspectClass}`}\n style={aspectStyle}\n onClick={(e) => {\n if (onContainerClick) {\n onContainerClick(e)\n return\n }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n if (onContainerClick) {\n onContainerClick(e as unknown as React.MouseEvent)\n return\n }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n >\n {/* For audio, poster persists as a visual background. For video, hide once loaded. */}\n {poster && (sourceType === 'audio' || initialLoad) && (\n <img\n src={poster}\n alt=\"\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n )}\n {!poster && (sourceType === 'audio' || initialLoad) && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <div className=\"absolute inset-0\">\n {sourceType === 'audio' ? (\n <audio\n {...nativePlayerProps}\n ref={playerRef as React.RefObject<HTMLAudioElement>}\n src={source}\n loop={loop}\n muted={muted}\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </audio>\n ) : (\n <video\n ref={playerRef as React.RefObject<HTMLVideoElement>}\n src={source}\n loop={loop}\n muted={muted}\n playsInline\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onLoadedMetadata={() => {\n const el = playerRef.current\n if (\n el instanceof HTMLVideoElement &&\n el.videoWidth &&\n el.videoHeight\n ) {\n setVideoAspect(el.videoWidth / el.videoHeight)\n }\n }}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </video>\n )}\n </div>\n\n {buffering && !manualPlayRequired && (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center\">\n <CircleNotchIcon\n className=\"size-8 animate-spin text-white/80\"\n weight=\"bold\"\n />\n </div>\n )}\n\n {manualPlayRequired && !controls && (\n <div\n className=\"absolute inset-0 z-30 flex cursor-pointer items-center justify-center bg-black/35\"\n role=\"button\"\n tabIndex={0}\n aria-label=\"Play preview\"\n onClick={(e) => {\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n >\n <span className=\"flex size-16 items-center justify-center rounded-full bg-white/20 text-white backdrop-blur-sm\">\n <PlayIcon className=\"size-9 translate-x-0.5\" weight=\"fill\" />\n </span>\n </div>\n )}\n\n {showProgress && !controls && (\n <div className=\"absolute inset-x-0 bottom-0 px-3 pb-2.5 pt-6 bg-gradient-to-t from-black/40 to-transparent\">\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={handleScrubberKeyDown}\n >\n <div className=\"w-full overflow-hidden rounded-full bg-white/30 h-1\">\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n </div>\n )}\n\n {controls && (\n <div className=\"absolute inset-x-0 bottom-0 flex items-center gap-2 bg-gradient-to-t from-black/60 to-transparent px-3 pb-2.5 pt-6 transition-all duration-200\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n setPlaying((p) => !p)\n }}\n className=\"shrink-0 text-white\"\n aria-label={playing ? 'Pause' : 'Play'}\n >\n {playing ? (\n <PauseIcon className=\"size-5\" weight=\"fill\" />\n ) : (\n <PlayIcon className=\"size-5 translate-x-px\" weight=\"fill\" />\n )}\n </button>\n\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onMouseEnter={() => setScrubberHovered(true)}\n onMouseLeave={() => setScrubberHovered(false)}\n onKeyDown={handleScrubberKeyDown}\n >\n <div\n className={`w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${scrubberHovered || seeking ? 'h-1.5' : 'h-1'}`}\n >\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n <div\n className={`absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${scrubberHovered || seeking ? 'scale-100 opacity-100' : 'scale-0 opacity-0'}`}\n style={{ left: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default MediaPlayer\n","import React, { useState } from 'react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../utils/cdnImageUrl'\n\nimport MediaPlayer, { type MediaPlayerProps } from './MediaPlayer'\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\nexport type AttachmentThumbnailVariant = 'light' | 'dark'\n\nexport interface AttachmentThumbnailProps {\n mimeType: string\n sourceUrl?: string\n thumbnailUrl?: string\n title?: string\n variant: AttachmentThumbnailVariant\n /** Extra props passed to MediaPlayer when source is video or audio. */\n mediaPlayerProps?: Partial<\n Pick<\n MediaPlayerProps,\n 'autoPlay' | 'loop' | 'muted' | 'controls' | 'onContainerClick'\n >\n >\n /**\n * When true (Visitor unlocked image/document), use aspect-video + object-contain fade-in.\n */\n containedImage?: boolean\n}\n\nconst placeholderIconClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark' ? 'size-12 text-white/20' : 'size-12 text-black/20'\n\nconst posterShellClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark'\n ? 'aspect-video overflow-hidden bg-white/10'\n : 'aspect-video overflow-hidden bg-black/5'\n\n/**\n * Renders the media preview area for attachment cards (LockedAttachment, MediaMessage).\n * Overlays (dim, lock, eye toggle) are composed by the parent.\n */\nconst AttachmentThumbnail: React.FC<AttachmentThumbnailProps> = ({\n mimeType,\n sourceUrl,\n thumbnailUrl,\n title,\n variant,\n mediaPlayerProps,\n containedImage = false,\n}) => {\n const sourceType = getSourceType(mimeType)\n const [sourceReady, setSourceReady] = useState(false)\n const optimizedSourceUrl = optimizeMessagingAttachmentUrl(sourceUrl)\n const optimizedThumbnailUrl = optimizeMessagingAttachmentUrl(thumbnailUrl)\n\n if (sourceUrl && (sourceType === 'video' || sourceType === 'audio')) {\n return (\n <MediaPlayer\n source={sourceUrl}\n mimeType={mimeType}\n poster={optimizedThumbnailUrl}\n controls\n {...mediaPlayerProps}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'image') {\n if (containedImage) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'document') {\n if (thumbnailUrl) {\n if (containedImage) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt=\"\"\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n }\n\n // Poster-only or empty (no sourceUrl)\n if (thumbnailUrl) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n draggable={false}\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n </div>\n )\n }\n\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n}\n\nexport default AttachmentThumbnail\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./AttachmentCard-DI2chsB_.cjs"),n=require("./LoadingDots-BSk_UeS0.cjs");let r=require("react");r=e.t(r,1);let i=require("react/jsx-runtime"),a=require("classnames");a=e.t(a,1);let o=require("@phosphor-icons/react");var s=({variant:e,title:n,placeholderTitle:r=`Attachment title`,mimeType:o,detail:s,statusBadge:c,action:l,icon:u,trailingAction:d})=>{let f=e===`dark`,p=n||r,m=!n,h=u??t.n(o,{className:(0,a.default)(`size-5 shrink-0`,f?`text-white/55`:`text-black/55`),weight:`regular`});return(0,i.jsxs)(`div`,{className:`px-4 py-3`,children:[(0,i.jsxs)(`div`,{className:`flex items-end gap-3`,children:[(0,i.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-1`,children:[p.trim()!==``&&(0,i.jsx)(`p`,{className:(0,a.default)(`truncate text-base font-medium leading-6`,{"text-black/90":!f&&!m,"text-black/30":!f&&m,"text-white/30":f&&m,"text-white":f&&!m}),children:p}),(0,i.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1`,children:[h,s!=null&&s!==``&&(0,i.jsx)(`span`,{className:(0,a.default)(`text-xs font-medium`,f?`text-white/55`:`text-black/55`),children:s}),c]})]}),d&&(0,i.jsx)(`div`,{className:`shrink-0`,children:d})]}),l]})},c=({paymentStatus:e,mimeType:n,isPlayable:r,isLocked:s})=>{let c=n?t.i(n):void 0,l=(r??(c===`video`||c===`audio`))&&!s?o.PlayIcon:e===`paid`?o.LockOpenIcon:o.LockSimpleIcon;return(0,i.jsx)(`div`,{className:`pointer-events-none absolute inset-0 flex items-center justify-center`,children:(0,i.jsx)(`div`,{className:(0,a.default)(`flex size-12 items-center justify-center rounded-full bg-black/30 text-white`,l===o.PlayIcon&&`group-hover:bg-black/40`),children:(0,i.jsx)(l,{className:`size-6`,weight:`fill`})})})};function l(e){let n=t.i(e.mimeType);return n===`video`||n===`audio`}var u=({variant:e,gallery:n,title:s,showLocked:u,paymentStatus:d,topRight:f})=>{let[p,m]=(0,r.useState)(0),h=n.length,g=Math.min(p,h-1),_=n[g],v=l(_),y=t.a(_.thumbnailUrl),b=e=>{e.stopPropagation(),m(e=>Math.max(0,e-1))},x=e=>{e.stopPropagation(),m(e=>Math.min(h-1,e+1))},S=g===0,C=g===h-1,w=e===`dark`;return(0,i.jsxs)(`div`,{className:(0,a.default)(`group relative overflow-hidden rounded-t-md`,u?`aspect-[337/386]`:void 0),children:[u?(0,i.jsx)(`div`,{className:(0,a.default)(`absolute inset-0`,w?`bg-white/10`:`bg-black/5`),children:_.thumbnailUrl&&(0,i.jsx)(`img`,{src:y??_.thumbnailUrl,alt:``,"aria-hidden":!0,draggable:!1,className:`absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]`})}):(0,i.jsx)(t.t,{mimeType:_.mimeType,sourceUrl:_.sourceUrl,thumbnailUrl:_.thumbnailUrl,title:s,variant:e,mediaPlayerProps:{autoPlay:!0}},g),u&&(0,i.jsx)(c,{paymentStatus:d,isPlayable:v,isLocked:u}),h>1&&(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`button`,{type:`button`,onClick:b,disabled:S,"aria-label":`Previous item`,className:(0,a.default)(`absolute left-3 top-1/2 -translate-y-1/2 flex size-7 items-center justify-center rounded-full bg-black/30 text-white transition-opacity`,S?`opacity-40`:`hover:bg-black/40`),children:(0,i.jsx)(o.CaretLeftIcon,{className:`size-5`,weight:`bold`})}),(0,i.jsx)(`button`,{type:`button`,onClick:x,disabled:C,"aria-label":`Next item`,className:(0,a.default)(`absolute right-3 top-1/2 -translate-y-1/2 flex size-7 items-center justify-center rounded-full bg-black/30 text-white transition-opacity`,C?`opacity-40`:`hover:bg-black/40`),children:(0,i.jsx)(o.CaretRightIcon,{className:`size-5`,weight:`bold`})}),(0,i.jsx)(`div`,{className:`pointer-events-none absolute bottom-10 left-1/2 flex size-8 -translate-x-1/2 items-center justify-center rounded-full bg-black/30`,children:(0,i.jsxs)(`span`,{className:`text-xs font-medium leading-none text-white`,children:[g+1,`/`,h]})})]}),f&&(0,i.jsx)(`div`,{className:`pointer-events-auto absolute right-3 top-3 z-10`,children:f})]})},d=({variant:e,mimeType:n,thumbnailUrl:r,title:o,source:s,showLocked:l,paymentStatus:u,topRight:d,containedImage:f=!1})=>{let p=l?void 0:s?.sourceUrl,m=l?r:s?.thumbnailUrl??r,h=t.a(m),g=e===`dark`;return(0,i.jsxs)(`div`,{className:`relative overflow-hidden rounded-t-md`,children:[l?(0,i.jsxs)(`div`,{className:(0,a.default)(`relative aspect-video overflow-hidden`,g?`bg-white/10`:`bg-black/5`),children:[m?(0,i.jsx)(`img`,{src:h??m,alt:``,"aria-hidden":!0,draggable:!1,className:`absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]`}):(0,i.jsx)(`div`,{className:`absolute inset-0 flex items-center justify-center`,children:t.n(n,{className:g?`size-12 text-white/20`:`size-12 text-black/20`,weight:`regular`})}),(0,i.jsx)(c,{paymentStatus:u,mimeType:n,isLocked:l})]}):(0,i.jsx)(t.t,{mimeType:n,sourceUrl:p,thumbnailUrl:m,title:o,variant:e,containedImage:f,mediaPlayerProps:p?{autoPlay:!0,loop:!0,controls:!0,muted:!1}:void 0}),d&&(0,i.jsx)(`div`,{className:`pointer-events-auto absolute right-3 top-3 z-10`,children:d})]})},f=e=>e.length>=2,p=e=>(0,i.jsx)(o.ImagesIcon,{className:e===`dark`?`size-5 shrink-0 text-white/55`:`size-5 shrink-0 text-black/55`}),m=({variant:e,gallery:t,title:n,showLocked:r,paymentStatus:a,mimeType:o,thumbnailUrl:s,source:c,containedImage:l,topRight:p})=>f(t)?(0,i.jsx)(u,{variant:e,gallery:t,title:n,showLocked:r,paymentStatus:a,topRight:p}):(0,i.jsx)(d,{variant:e,mimeType:o,thumbnailUrl:s,title:n,source:c,showLocked:r,paymentStatus:a,topRight:p,containedImage:l}),h=({variant:e,children:t,rootRef:n,"data-testid":r})=>(0,i.jsx)(`div`,{ref:n,"data-testid":r,className:(0,a.default)(`relative w-[280px] select-none overflow-hidden rounded-md`,e===`dark`?`bg-[#1e2330]`:`bg-white`,`shadow-[0_1px_2px_rgba(0,0,0,0.08)]`),children:t}),g=({onToggle:e,isBusy:t,isPreviewVisible:n,children:a})=>e?(0,i.jsx)(`div`,{role:`button`,tabIndex:t?-1:0,"aria-label":`Toggle preview`,"aria-busy":t,"aria-pressed":n,"aria-disabled":t||void 0,onClick:t?void 0:e,onKeyDown:n=>{t||n.target===n.currentTarget&&(n.key===`Enter`||n.key===` `)&&(n.preventDefault(),e())},className:t?`block w-full text-left`:`block w-full cursor-pointer text-left`,children:a}):(0,i.jsx)(r.default.Fragment,{children:a});function _({isGallery:e,onFetchSource:t,onPreviewClick:n}){let[i,a]=(0,r.useState)(),[o,s]=(0,r.useState)(!1),[c,l]=(0,r.useState)(!1),u=(0,r.useRef)(!1),d=(0,r.useCallback)(async()=>{if(n?.(),o){s(!1);return}if(e){s(!0);return}if(i){s(!0);return}if(t&&!u.current){u.current=!0,l(!0);try{let e=await t();e&&(a(e),s(!0))}finally{u.current=!1,l(!1)}}},[o,e,i,n,t]);return{source:i,isPreviewVisible:o,isLoadingPreview:c,handleToggle:d,togglePreview:e||t!=null||n!=null?d:void 0}}function v({paymentStatus:e,onFetchSource:t,onUnlockClick:n}){let[i,a]=(0,r.useState)(),o=(0,r.useRef)(null),s=(0,r.useRef)(!1),c=(0,r.useRef)(t);c.current=t;let l=(0,r.useCallback)(async()=>{if(!s.current){s.current=!0;try{let e=await c.current?.();e&&a(e)}finally{s.current=!1}}},[]),u=(0,r.useCallback)(()=>{e===`paid`?l():n?.()},[e,l,n]);return(0,r.useEffect)(()=>{if(!o.current||e!==`paid`||i!==void 0)return;let t=new IntersectionObserver(([e])=>{e.isIntersecting&&(l(),t.disconnect())},{threshold:1});return t.observe(o.current),()=>t.disconnect()},[e,i,l]),{source:i,cardRef:o,handleUnlockClick:u}}var y=`mt-3 inline-flex h-10 w-full items-center justify-center gap-2 rounded-full bg-[#121110] px-4 text-sm font-medium leading-none text-white hover:bg-[#2a2928]`,b=({isLocked:e,sourceUrl:t,redeemUrl:a,onUnlockClicked:s,onDownloadClicked:c,isUnlocking:l=!1})=>{if(e&&s!=null)return(0,i.jsx)(`button`,{type:`button`,onClick:s,disabled:l,"aria-label":l?`Unlocking`:`Unlock`,"aria-busy":l,title:l?`Unlocking`:`Unlock`,className:y,children:l?(0,i.jsx)(n.t,{}):(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(o.LockSimpleIcon,{className:`size-4`,weight:`fill`}),`Unlock`]})});if(!e&&c!=null){let e=a??t;return e==null?(0,i.jsxs)(`button`,{type:`button`,onClick:c,"aria-label":`Download`,className:y,children:[(0,i.jsx)(o.DownloadSimpleIcon,{className:`size-4`,weight:`bold`}),`Download`]}):(0,i.jsxs)(`a`,{href:e,"aria-label":`Download`,target:`_blank`,rel:`noopener noreferrer`,onClick:c,className:`${y} !text-white`,children:[(0,i.jsx)(o.DownloadSimpleIcon,{className:`size-4`,weight:`bold`}),`Download`]})}return null},x=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:n,detail:a,amountText:c,placeholderTitle:l,placeholderAmountText:u,gallery:d=[],onDismiss:v,onPreviewClick:y,onFetchSource:b,onEditClick:x})=>{let S=f(d),{source:C,isPreviewVisible:w,isLoadingPreview:T,togglePreview:E}=_({isGallery:S,onFetchSource:b,onPreviewClick:y}),D=!w,O=T,k=(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`span`,{className:`text-xs font-medium text-white/55`,children:`•`}),(0,i.jsx)(`span`,{className:c?`text-xs font-medium text-white/55`:`text-xs font-medium text-white/30`,children:c||u})]}),A=v?(0,i.jsx)(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),v()},className:`flex size-6 items-center justify-center rounded-full bg-[#121110] text-white`,"aria-label":`Dismiss attachment`,children:(0,i.jsx)(o.XIcon,{className:`size-3`,weight:`bold`})}):void 0,j=x?(0,i.jsx)(`button`,{type:`button`,onClick:x,"aria-label":`Edit attachment`,className:`flex size-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/15`,children:(0,i.jsx)(o.PencilSimpleIcon,{className:`size-5`,weight:`regular`})}):void 0;return(0,i.jsxs)(h,{variant:`dark`,children:[(0,i.jsx)(g,{onToggle:E,isBusy:O,isPreviewVisible:!D,children:(0,i.jsx)(m,{variant:`dark`,gallery:d,title:e,showLocked:D,mimeType:t,thumbnailUrl:n,source:C,topRight:A})}),(0,i.jsx)(s,{variant:`dark`,title:e,placeholderTitle:l,mimeType:t,detail:a,statusBadge:k,icon:S?p(`dark`):void 0,trailingAction:j})]})},S=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:n,detail:a,amountText:o,placeholderTitle:c,placeholderAmountText:l,gallery:u=[]})=>{let d=f(u),g=(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`span`,{className:`text-xs font-medium text-black/55`,children:`•`}),(0,i.jsx)(`span`,{className:o?`text-xs font-medium text-black/55`:`text-xs font-medium text-black/30`,children:o||l})]});return(0,i.jsxs)(h,{variant:`light`,children:[(0,i.jsx)(m,{variant:`light`,gallery:u,title:e,showLocked:!0,mimeType:t,thumbnailUrl:n}),(0,i.jsx)(s,{variant:`light`,title:e,placeholderTitle:c,mimeType:t,detail:a,statusBadge:g,icon:d?p(`light`):void 0})]})},C=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:r,detail:a,amountText:o,placeholderTitle:c,paymentStatus:l=`pending`,gallery:u=[],onPreviewClick:d,onFetchSource:v})=>{let y=f(u),{source:b,isPreviewVisible:x,isLoadingPreview:S,togglePreview:C}=_({isGallery:y,onFetchSource:v,onPreviewClick:d}),w=!x;return(0,i.jsxs)(h,{variant:`dark`,children:[(0,i.jsx)(g,{onToggle:C,isBusy:S,isPreviewVisible:!w,children:(0,i.jsx)(m,{variant:`dark`,gallery:u,title:e,showLocked:w,paymentStatus:l,mimeType:t,thumbnailUrl:r,source:b})}),(0,i.jsx)(s,{variant:`dark`,title:e,placeholderTitle:c,mimeType:t,detail:a,statusBadge:(0,i.jsx)(n.n,{isMine:!0,paymentStatus:l,amountText:o}),icon:y?p(`dark`):void 0})]})},w=({title:e,amountText:r,thumbnailUrl:a,mimeType:o=`application/octet-stream`,detail:c,gallery:l=[],onUnlockClick:u,onFetchSource:d,onDownloadClick:g,paymentStatus:_,isUnlocking:y=!1})=>{let x=f(l),{source:S,cardRef:C,handleUnlockClick:w}=v({paymentStatus:_,onFetchSource:d,onUnlockClick:u}),T=S?.sourceUrl,E=S?.redeemUrl,D=x?_!==`paid`:T===void 0,O=t.i(o),k=x?void 0:T;return(0,i.jsxs)(h,{variant:`light`,rootRef:C,"data-testid":`locked-attachment`,children:[(0,i.jsx)(m,{variant:`light`,gallery:l,title:e,showLocked:D,paymentStatus:_,mimeType:o,thumbnailUrl:a,source:S,containedImage:!D&&O===`document`}),(0,i.jsx)(s,{variant:`light`,title:e,mimeType:o,detail:c,statusBadge:(0,i.jsx)(n.n,{isMine:!1,paymentStatus:_,amountText:r}),icon:x?p(`light`):void 0,action:(0,i.jsx)(b,{isLocked:D,isUnlocking:y,sourceUrl:k,redeemUrl:E,onUnlockClicked:w,onDownloadClicked:g})})]})},T=e=>e.isDraft?(0,i.jsx)(x,{...e}):e.isPreview?(0,i.jsx)(S,{...e}):e.isMine?(0,i.jsx)(C,{...e}):(0,i.jsx)(w,{...e});exports.default=T;
2
- //# sourceMappingURL=Card-ByU9P9GA.cjs.map
1
+ const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./AttachmentCard-DUrgGRsq.cjs"),n=require("./LoadingDots-BSk_UeS0.cjs");let r=require("react");r=e.t(r,1);let i=require("react/jsx-runtime"),a=require("classnames");a=e.t(a,1);let o=require("@phosphor-icons/react");var s=({variant:e,title:n,placeholderTitle:r=`Attachment title`,mimeType:o,detail:s,statusBadge:c,action:l,icon:u,trailingAction:d})=>{let f=e===`dark`,p=n||r,m=!n,h=u??t.n(o,{className:(0,a.default)(`size-5 shrink-0`,f?`text-white/55`:`text-black/55`),weight:`regular`});return(0,i.jsxs)(`div`,{className:`px-4 py-3`,children:[(0,i.jsxs)(`div`,{className:`flex items-end gap-3`,children:[(0,i.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-1`,children:[p.trim()!==``&&(0,i.jsx)(`p`,{className:(0,a.default)(`truncate text-base font-medium leading-6`,{"text-black/90":!f&&!m,"text-black/30":!f&&m,"text-white/30":f&&m,"text-white":f&&!m}),children:p}),(0,i.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1`,children:[h,s!=null&&s!==``&&(0,i.jsx)(`span`,{className:(0,a.default)(`text-xs font-medium`,f?`text-white/55`:`text-black/55`),children:s}),c]})]}),d&&(0,i.jsx)(`div`,{className:`shrink-0`,children:d})]}),l]})},c=({paymentStatus:e,mimeType:n,isPlayable:r,isLocked:s})=>{let c=n?t.i(n):void 0,l=(r??(c===`video`||c===`audio`))&&!s?o.PlayIcon:e===`paid`?o.LockOpenIcon:o.LockSimpleIcon;return(0,i.jsx)(`div`,{className:`pointer-events-none absolute inset-0 flex items-center justify-center`,children:(0,i.jsx)(`div`,{className:(0,a.default)(`flex size-12 items-center justify-center rounded-full bg-black/30 text-white`,l===o.PlayIcon&&`group-hover:bg-black/40`),children:(0,i.jsx)(l,{className:`size-6`,weight:`fill`})})})};function l(e){let n=t.i(e.mimeType);return n===`video`||n===`audio`}var u=({variant:e,gallery:n,title:s,showLocked:u,paymentStatus:d,topRight:f})=>{let[p,m]=(0,r.useState)(0),h=n.length,g=Math.min(p,h-1),_=n[g],v=l(_),y=t.s(_.thumbnailUrl),b=e=>{e.stopPropagation(),m(e=>Math.max(0,e-1))},x=e=>{e.stopPropagation(),m(e=>Math.min(h-1,e+1))},S=g===0,C=g===h-1,w=e===`dark`;return(0,i.jsxs)(`div`,{className:(0,a.default)(`group relative overflow-hidden rounded-t-md`,u?`aspect-[337/386]`:void 0),children:[u?(0,i.jsx)(`div`,{className:(0,a.default)(`absolute inset-0`,w?`bg-white/10`:`bg-black/5`),children:_.thumbnailUrl&&(0,i.jsx)(`img`,{src:y??_.thumbnailUrl,alt:``,"aria-hidden":!0,draggable:!1,className:`absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]`})}):(0,i.jsx)(t.t,{mimeType:_.mimeType,sourceUrl:_.sourceUrl,thumbnailUrl:_.thumbnailUrl,title:s,variant:e,mediaPlayerProps:{autoPlay:!0}},g),u&&(0,i.jsx)(c,{paymentStatus:d,isPlayable:v,isLocked:u}),h>1&&(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`button`,{type:`button`,onClick:b,disabled:S,"aria-label":`Previous item`,className:(0,a.default)(`absolute left-3 top-1/2 -translate-y-1/2 flex size-7 items-center justify-center rounded-full bg-black/30 text-white transition-opacity`,S?`opacity-40`:`hover:bg-black/40`),children:(0,i.jsx)(o.CaretLeftIcon,{className:`size-5`,weight:`bold`})}),(0,i.jsx)(`button`,{type:`button`,onClick:x,disabled:C,"aria-label":`Next item`,className:(0,a.default)(`absolute right-3 top-1/2 -translate-y-1/2 flex size-7 items-center justify-center rounded-full bg-black/30 text-white transition-opacity`,C?`opacity-40`:`hover:bg-black/40`),children:(0,i.jsx)(o.CaretRightIcon,{className:`size-5`,weight:`bold`})}),(0,i.jsx)(`div`,{className:`pointer-events-none absolute bottom-10 left-1/2 flex size-8 -translate-x-1/2 items-center justify-center rounded-full bg-black/30`,children:(0,i.jsxs)(`span`,{className:`text-xs font-medium leading-none text-white`,children:[g+1,`/`,h]})})]}),f&&(0,i.jsx)(`div`,{className:`pointer-events-auto absolute right-3 top-3 z-10`,children:f})]})},d=({variant:e,mimeType:n,thumbnailUrl:r,title:o,source:s,showLocked:l,paymentStatus:u,topRight:d,containedImage:f=!1})=>{let p=l?void 0:s?.sourceUrl,m=l?r:s?.thumbnailUrl??r,h=t.s(m),g=e===`dark`;return(0,i.jsxs)(`div`,{className:`relative overflow-hidden rounded-t-md`,children:[l?(0,i.jsxs)(`div`,{className:(0,a.default)(`relative aspect-video overflow-hidden`,g?`bg-white/10`:`bg-black/5`),children:[m?(0,i.jsx)(`img`,{src:h??m,alt:``,"aria-hidden":!0,draggable:!1,className:`absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]`}):(0,i.jsx)(`div`,{className:`absolute inset-0 flex items-center justify-center`,children:t.n(n,{className:g?`size-12 text-white/20`:`size-12 text-black/20`,weight:`regular`})}),(0,i.jsx)(c,{paymentStatus:u,mimeType:n,isLocked:l})]}):(0,i.jsx)(t.t,{mimeType:n,sourceUrl:p,thumbnailUrl:m,title:o,variant:e,containedImage:f,mediaPlayerProps:p?{autoPlay:!0,loop:!0,controls:!0,muted:!1}:void 0}),d&&(0,i.jsx)(`div`,{className:`pointer-events-auto absolute right-3 top-3 z-10`,children:d})]})},f=e=>e.length>=2,p=e=>(0,i.jsx)(o.ImagesIcon,{className:e===`dark`?`size-5 shrink-0 text-white/55`:`size-5 shrink-0 text-black/55`}),m=({variant:e,gallery:t,title:n,showLocked:r,paymentStatus:a,mimeType:o,thumbnailUrl:s,source:c,containedImage:l,topRight:p})=>f(t)?(0,i.jsx)(u,{variant:e,gallery:t,title:n,showLocked:r,paymentStatus:a,topRight:p}):(0,i.jsx)(d,{variant:e,mimeType:o,thumbnailUrl:s,title:n,source:c,showLocked:r,paymentStatus:a,topRight:p,containedImage:l}),h=({variant:e,children:t,rootRef:n,"data-testid":r})=>(0,i.jsx)(`div`,{ref:n,"data-testid":r,className:(0,a.default)(`relative w-[280px] select-none overflow-hidden rounded-md`,e===`dark`?`bg-[#1e2330]`:`bg-white`,`shadow-[0_1px_2px_rgba(0,0,0,0.08)]`),children:t}),g=({onToggle:e,isBusy:t,isPreviewVisible:n,children:a})=>e?(0,i.jsx)(`div`,{role:`button`,tabIndex:t?-1:0,"aria-label":`Toggle preview`,"aria-busy":t,"aria-pressed":n,"aria-disabled":t||void 0,onClick:t?void 0:e,onKeyDown:n=>{t||n.target===n.currentTarget&&(n.key===`Enter`||n.key===` `)&&(n.preventDefault(),e())},className:t?`block w-full text-left`:`block w-full cursor-pointer text-left`,children:a}):(0,i.jsx)(r.default.Fragment,{children:a});function _({isGallery:e,onFetchSource:t,onPreviewClick:n}){let[i,a]=(0,r.useState)(),[o,s]=(0,r.useState)(!1),[c,l]=(0,r.useState)(!1),u=(0,r.useRef)(!1),d=(0,r.useCallback)(async()=>{if(n?.(),o){s(!1);return}if(e){s(!0);return}if(i){s(!0);return}if(t&&!u.current){u.current=!0,l(!0);try{let e=await t();e&&(a(e),s(!0))}finally{u.current=!1,l(!1)}}},[o,e,i,n,t]);return{source:i,isPreviewVisible:o,isLoadingPreview:c,handleToggle:d,togglePreview:e||t!=null||n!=null?d:void 0}}function v({paymentStatus:e,onFetchSource:t,onUnlockClick:n}){let[i,a]=(0,r.useState)(),o=(0,r.useRef)(null),s=(0,r.useRef)(!1),c=(0,r.useRef)(t);c.current=t;let l=(0,r.useCallback)(async()=>{if(!s.current){s.current=!0;try{let e=await c.current?.();e&&a(e)}finally{s.current=!1}}},[]),u=(0,r.useCallback)(()=>{e===`paid`?l():n?.()},[e,l,n]);return(0,r.useEffect)(()=>{if(!o.current||e!==`paid`||i!==void 0)return;let t=new IntersectionObserver(([e])=>{e.isIntersecting&&(l(),t.disconnect())},{threshold:1});return t.observe(o.current),()=>t.disconnect()},[e,i,l]),{source:i,cardRef:o,handleUnlockClick:u}}var y=`mt-3 inline-flex h-10 w-full items-center justify-center gap-2 rounded-full bg-[#121110] px-4 text-sm font-medium leading-none text-white hover:bg-[#2a2928]`,b=({isLocked:e,sourceUrl:t,redeemUrl:a,onUnlockClicked:s,onDownloadClicked:c,isUnlocking:l=!1})=>{if(e&&s!=null)return(0,i.jsx)(`button`,{type:`button`,onClick:s,disabled:l,"aria-label":l?`Unlocking`:`Unlock`,"aria-busy":l,title:l?`Unlocking`:`Unlock`,className:y,children:l?(0,i.jsx)(n.t,{}):(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(o.LockSimpleIcon,{className:`size-4`,weight:`fill`}),`Unlock`]})});if(!e&&c!=null){let e=a??t;return e==null?(0,i.jsxs)(`button`,{type:`button`,onClick:c,"aria-label":`Download`,className:y,children:[(0,i.jsx)(o.DownloadSimpleIcon,{className:`size-4`,weight:`bold`}),`Download`]}):(0,i.jsxs)(`a`,{href:e,"aria-label":`Download`,target:`_blank`,rel:`noopener noreferrer`,onClick:c,className:`${y} !text-white`,children:[(0,i.jsx)(o.DownloadSimpleIcon,{className:`size-4`,weight:`bold`}),`Download`]})}return null},x=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:n,detail:a,amountText:c,placeholderTitle:l,placeholderAmountText:u,gallery:d=[],onDismiss:v,onPreviewClick:y,onFetchSource:b,onEditClick:x})=>{let S=f(d),{source:C,isPreviewVisible:w,isLoadingPreview:T,togglePreview:E}=_({isGallery:S,onFetchSource:b,onPreviewClick:y}),D=!w,O=T,k=(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`span`,{className:`text-xs font-medium text-white/55`,children:`•`}),(0,i.jsx)(`span`,{className:c?`text-xs font-medium text-white/55`:`text-xs font-medium text-white/30`,children:c||u})]}),A=v?(0,i.jsx)(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),v()},className:`flex size-6 items-center justify-center rounded-full bg-[#121110] text-white`,"aria-label":`Dismiss attachment`,children:(0,i.jsx)(o.XIcon,{className:`size-3`,weight:`bold`})}):void 0,j=x?(0,i.jsx)(`button`,{type:`button`,onClick:x,"aria-label":`Edit attachment`,className:`flex size-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/15`,children:(0,i.jsx)(o.PencilSimpleIcon,{className:`size-5`,weight:`regular`})}):void 0;return(0,i.jsxs)(h,{variant:`dark`,children:[(0,i.jsx)(g,{onToggle:E,isBusy:O,isPreviewVisible:!D,children:(0,i.jsx)(m,{variant:`dark`,gallery:d,title:e,showLocked:D,mimeType:t,thumbnailUrl:n,source:C,topRight:A})}),(0,i.jsx)(s,{variant:`dark`,title:e,placeholderTitle:l,mimeType:t,detail:a,statusBadge:k,icon:S?p(`dark`):void 0,trailingAction:j})]})},S=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:n,detail:a,amountText:o,placeholderTitle:c,placeholderAmountText:l,gallery:u=[]})=>{let d=f(u),g=(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`span`,{className:`text-xs font-medium text-black/55`,children:`•`}),(0,i.jsx)(`span`,{className:o?`text-xs font-medium text-black/55`:`text-xs font-medium text-black/30`,children:o||l})]});return(0,i.jsxs)(h,{variant:`light`,children:[(0,i.jsx)(m,{variant:`light`,gallery:u,title:e,showLocked:!0,mimeType:t,thumbnailUrl:n}),(0,i.jsx)(s,{variant:`light`,title:e,placeholderTitle:c,mimeType:t,detail:a,statusBadge:g,icon:d?p(`light`):void 0})]})},C=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:r,detail:a,amountText:o,placeholderTitle:c,paymentStatus:l=`pending`,gallery:u=[],onPreviewClick:d,onFetchSource:v})=>{let y=f(u),{source:b,isPreviewVisible:x,isLoadingPreview:S,togglePreview:C}=_({isGallery:y,onFetchSource:v,onPreviewClick:d}),w=!x;return(0,i.jsxs)(h,{variant:`dark`,children:[(0,i.jsx)(g,{onToggle:C,isBusy:S,isPreviewVisible:!w,children:(0,i.jsx)(m,{variant:`dark`,gallery:u,title:e,showLocked:w,paymentStatus:l,mimeType:t,thumbnailUrl:r,source:b})}),(0,i.jsx)(s,{variant:`dark`,title:e,placeholderTitle:c,mimeType:t,detail:a,statusBadge:(0,i.jsx)(n.n,{isMine:!0,paymentStatus:l,amountText:o}),icon:y?p(`dark`):void 0})]})},w=({title:e,amountText:r,thumbnailUrl:a,mimeType:o=`application/octet-stream`,detail:c,gallery:l=[],onUnlockClick:u,onFetchSource:d,onDownloadClick:g,paymentStatus:_,isUnlocking:y=!1})=>{let x=f(l),{source:S,cardRef:C,handleUnlockClick:w}=v({paymentStatus:_,onFetchSource:d,onUnlockClick:u}),T=S?.sourceUrl,E=S?.redeemUrl,D=x?_!==`paid`:T===void 0,O=t.i(o),k=x?void 0:T;return(0,i.jsxs)(h,{variant:`light`,rootRef:C,"data-testid":`locked-attachment`,children:[(0,i.jsx)(m,{variant:`light`,gallery:l,title:e,showLocked:D,paymentStatus:_,mimeType:o,thumbnailUrl:a,source:S,containedImage:!D&&O===`document`}),(0,i.jsx)(s,{variant:`light`,title:e,mimeType:o,detail:c,statusBadge:(0,i.jsx)(n.n,{isMine:!1,paymentStatus:_,amountText:r}),icon:x?p(`light`):void 0,action:(0,i.jsx)(b,{isLocked:D,isUnlocking:y,sourceUrl:k,redeemUrl:E,onUnlockClicked:w,onDownloadClicked:g})})]})},T=e=>e.isDraft?(0,i.jsx)(x,{...e}):e.isPreview?(0,i.jsx)(S,{...e}):e.isMine?(0,i.jsx)(C,{...e}):(0,i.jsx)(w,{...e});exports.default=T;
2
+ //# sourceMappingURL=Card-BIbqWagz.cjs.map