@burdenoff/microfe-conversations 2026.924.1 → 2026.928.1

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.
@@ -3,291 +3,331 @@ import { useTr as t } from "../utils/i18n.js";
3
3
  import { cn as n } from "../utils/cn.js";
4
4
  import { useConversationsStore as r } from "../store/conversationsStore.js";
5
5
  import { MessageBubble as i } from "../components/MessageBubble.js";
6
- import { useConversationActions as ee, useGetConversation as te } from "../hooks/useConversationQueries.js";
7
- import { useEditMessage as ne, useGetMessages as re, useMessageActions as ie, useSendMessage as ae } from "../hooks/useMessageQueries.js";
8
- import { useMessageStreamForConversation as oe } from "../hooks/useMessageSubscriptions.js";
6
+ import { useConversationActions as ee, useGetConversation as te, useMarkConversationAsRead as ne } from "../hooks/useConversationQueries.js";
7
+ import { useEditMessage as re, useGetMessages as ie, useMessageActions as ae, useSendMessage as oe } from "../hooks/useMessageQueries.js";
8
+ import { useMessageStreamForConversation as se } from "../hooks/useMessageSubscriptions.js";
9
9
  import { PermissionGuard as a } from "../components/PermissionGuard.js";
10
- import { QuotaExhaustedDialog as se } from "../components/QuotaExhaustedDialog.js";
10
+ import { QuotaExhaustedDialog as ce } from "../components/QuotaExhaustedDialog.js";
11
11
  import { CONVERSATIONS_PERMISSIONS as o } from "../constants/permissions.js";
12
- import { nativeImpact as ce, nativeNotify as s } from "../../utils/nativeBridge.js";
12
+ import { nativeImpact as le, nativeNotify as s } from "../../utils/nativeBridge.js";
13
13
  import { useCallback as c, useEffect as l, useMemo as u, useRef as d, useState as f } from "react";
14
- import { Archive as le, ArrowLeft as ue, Bell as de, BellOff as fe, ExternalLink as pe, Hash as me, Loader2 as he, LogOut as ge, MoreVertical as _e, Pin as p, PinOff as ve, SendHorizontal as m, Users as ye, X as be } from "lucide-react";
15
- import { useNavigate as xe, useParams as Se } from "react-router";
16
- import { isQuotaExhaustedError as Ce } from "@burdenoff/fe-libs/shared/utils";
17
- import { useEventBus as we } from "@burdenoff/fe-libs/shared/events";
14
+ import { Archive as ue, ArrowLeft as de, Bell as fe, BellOff as pe, ExternalLink as me, Hash as he, Loader2 as ge, LogOut as _e, MoreVertical as ve, Pin as p, PinOff as ye, SendHorizontal as m, Users as be, X as xe } from "lucide-react";
15
+ import { useNavigate as Se, useParams as Ce } from "react-router";
16
+ import { isQuotaExhaustedError as we } from "@burdenoff/fe-libs/shared/utils";
17
+ import { useEventBus as Te } from "@burdenoff/fe-libs/shared/events";
18
18
  import { jsx as h, jsxs as g } from "react/jsx-runtime";
19
- import { Button as Te, IllustratedEmptyState as Ee, NextSteps as De } from "@burdenoff/fe-libs/ui";
19
+ import { Button as Ee, IllustratedEmptyState as De, NextSteps as Oe } from "@burdenoff/fe-libs/ui";
20
20
  //#region src/conversations/pages/ConversationDetailPage.tsx
21
- var _ = 100, Oe = 3e4;
22
- function v() {
23
- let { conversationId: a } = Se(), o = xe(), { basePath: v, currentUser: ke } = e(), x = we(), S = t(), { clearMessageDraft: C, isParticipantsPanelOpen: w, messageDrafts: Ae, setMessageDraft: je, toggleParticipantsPanel: T } = r(), [E, Me] = f(Ae[a ?? ""] ?? ""), [Ne, D] = f(!1), [O, k] = f([]), Pe = d(null), A = d(null), j = c(() => {
24
- A.current?.focus(), A.current?.scrollIntoView({ behavior: "smooth" });
25
- }, []), { conversation: M, members: N, membersTotalCount: Fe, loading: Ie, error: P } = te(a ?? ""), { messages: F, loading: Le, error: Re, refetch: ze } = re(a ?? "", {
26
- first: _,
27
- pollInterval: Oe
21
+ var ke = 100, Ae = 3e4, je = 3;
22
+ function _() {
23
+ let { conversationId: a } = Ce(), o = Se(), { basePath: _, currentUser: Me } = e(), b = Te(), x = t(), { clearMessageDraft: S, isParticipantsPanelOpen: C, messageDrafts: Ne, setMessageDraft: Pe, toggleParticipantsPanel: w } = r(), [T, Fe] = f(Ne[a ?? ""] ?? ""), [Ie, E] = f(!1), [D, O] = f([]), Le = d(null), k = d(null), A = c(() => {
24
+ k.current?.focus(), k.current?.scrollIntoView({ behavior: "smooth" });
25
+ }, []), { conversation: j, members: M, membersTotalCount: Re, loading: N, error: P } = te(a ?? ""), { markConversationAsRead: F } = ne(), ze = d(null), I = d(/* @__PURE__ */ new Set()), Be = d(0), L = d(null), R = d(0), [Ve, He] = f(0), { messages: z, loading: B, error: V, refetch: Ue } = ie(a ?? "", {
26
+ first: ke,
27
+ pollInterval: Ae
28
28
  });
29
- oe(a, _);
30
- let { sendMessage: Be, loading: I } = ae(), { editMessage: Ve, loading: L } = ne(), { deleteMessage: He, addReaction: Ue, removeReaction: We, pinMessage: Ge, unpinMessage: Ke } = ie(), { archiveConversation: qe, pinConversation: Je, unpinConversation: Ye, muteConversation: Xe, unmuteConversation: Ze, leaveConversation: Qe } = ee(), [R, z] = f(!1), [B, V] = f(null), [H, U] = f(""), [W, G] = f(null), K = d(null), q = ke?.id ?? "", J = M?.sourceContext, Y = u(() => {
29
+ se(a, ke);
30
+ let { sendMessage: We, loading: H } = oe(), { editMessage: Ge, loading: U } = re(), { deleteMessage: Ke, addReaction: qe, removeReaction: Je, pinMessage: Ye, unpinMessage: Xe } = ae(), { archiveConversation: Ze, pinConversation: Qe, unpinConversation: $e, muteConversation: et, unmuteConversation: tt, leaveConversation: nt } = ee(), [W, G] = f(!1), [K, q] = f(null), [J, Y] = f(""), [X, rt] = f(null), it = d(null), Z = Me?.id ?? "", Q = j?.sourceContext, $ = u(() => {
31
31
  let e = /* @__PURE__ */ new Map();
32
- for (let t of O) t.conversationId === a && e.set(t.id, t);
33
- for (let t of F) e.set(t.id, t);
32
+ for (let t of D) t.conversationId === a && e.set(t.id, t);
33
+ for (let t of z) e.set(t.id, t);
34
34
  return Array.from(e.values()).sort((e, t) => new Date(e.createdAt).getTime() - new Date(t.createdAt).getTime());
35
35
  }, [
36
36
  a,
37
- O,
38
- F
37
+ D,
38
+ z
39
39
  ]);
40
40
  l(() => {
41
- Pe.current?.scrollIntoView({ behavior: "smooth" });
42
- }, [Y.length]), l(() => {
43
- k([]);
41
+ Le.current?.scrollIntoView({ behavior: "smooth" });
42
+ }, [$.length]), l(() => {
43
+ O([]);
44
44
  }, [a]), l(() => {
45
- if (O.length === 0 || F.length === 0) return;
46
- let e = new Set(F.map((e) => e.id));
47
- k((t) => {
45
+ if (D.length === 0 || z.length === 0) return;
46
+ let e = new Set(z.map((e) => e.id));
47
+ O((t) => {
48
48
  let n = t.filter((t) => !e.has(t.id));
49
49
  return n.length === t.length ? t : n;
50
50
  });
51
51
  }, [
52
- O.length,
53
- F,
54
- k
52
+ D.length,
53
+ z,
54
+ O
55
55
  ]), l(() => {
56
56
  if (a) {
57
- if (E.trim()) {
58
- je(a, E);
57
+ if (T.trim()) {
58
+ Pe(a, T);
59
59
  return;
60
60
  }
61
- C(a);
61
+ S(a);
62
62
  }
63
63
  }, [
64
- E,
64
+ T,
65
65
  a,
66
- je,
67
- C
66
+ Pe,
67
+ S
68
68
  ]);
69
- let X = u(() => {
69
+ let at = u(() => {
70
70
  let e = /* @__PURE__ */ new Map();
71
- for (let t of Y) !t.authorId || e.has(t.authorId) || t.sender.name && e.set(t.authorId, t.sender.name);
71
+ for (let t of $) !t.authorId || e.has(t.authorId) || t.sender.name && e.set(t.authorId, t.sender.name);
72
72
  return e;
73
- }, [Y]), Z = u(() => N.length > 0 ? N.filter((e) => e.status === "ACTIVE" && !e.leftAt).map((e) => ({
73
+ }, [$]), ot = u(() => M.length > 0 ? M.filter((e) => e.status === "ACTIVE" && !e.leftAt).map((e) => ({
74
74
  id: e.userId,
75
- name: X.get(e.userId) || e.customTitle || S("conversations.member", "Member"),
75
+ name: at.get(e.userId) || e.customTitle || x("conversations.member", "Member"),
76
76
  role: e.role
77
- })) : Array.from(X.entries()).map(([e, t]) => ({
77
+ })) : Array.from(at.entries()).map(([e, t]) => ({
78
78
  id: e,
79
79
  name: t,
80
- role: S("conversations.member", "Member")
80
+ role: x("conversations.member", "Member")
81
81
  })), [
82
- N,
83
- X,
84
- S
85
- ]), $e = M?.memberCount ? Math.max(M.memberCount - Z.length, 0) : 0, Q = c(async () => {
86
- if (!a || !E.trim() || I) return;
82
+ M,
83
+ at,
84
+ x
85
+ ]), st = j?.memberCount ? Math.max(j.memberCount - ot.length, 0) : 0, ct = c(async () => {
86
+ if (!a || !T.trim() || H) return;
87
87
  let e;
88
88
  try {
89
- e = await Be({
89
+ e = await We({
90
90
  conversationId: a,
91
- content: E.trim(),
91
+ content: T.trim(),
92
92
  type: "TEXT",
93
- parentMessageId: W?.id,
94
- refetchFirst: _
93
+ parentMessageId: X?.id,
94
+ refetchFirst: ke
95
95
  });
96
96
  } catch (e) {
97
- if (Ce(e)) {
98
- D(!0);
97
+ if (we(e)) {
98
+ E(!0);
99
99
  return;
100
100
  }
101
101
  throw s("error"), e;
102
102
  }
103
- e && (k((t) => [...t, e]), x.emit("conversations.message.sent", {
103
+ e && (O((t) => [...t, e]), b.emit("conversations.message.sent", {
104
104
  messageId: e.id,
105
105
  conversationId: a
106
- }), Me(""), G(null), C(a));
106
+ }), Fe(""), rt(null), S(a));
107
107
  }, [
108
- x,
108
+ b,
109
109
  a,
110
- E,
111
- I,
112
- Be,
113
- C,
114
- W
115
- ]), et = c((e) => {
116
- e.key !== "Enter" || e.shiftKey || (e.preventDefault(), Q());
117
- }, [Q]);
110
+ T,
111
+ H,
112
+ We,
113
+ S,
114
+ X
115
+ ]), lt = c((e) => {
116
+ e.key !== "Enter" || e.shiftKey || (e.preventDefault(), ct());
117
+ }, [ct]);
118
118
  l(() => {
119
- a && x.emit("conversations.conversation.opened", { conversationId: a });
120
- }, [x, a]), l(() => {
121
- if (!R) return;
119
+ a && b.emit("conversations.conversation.opened", { conversationId: a });
120
+ }, [b, a]), l(() => {
121
+ ze.current = null, I.current.clear(), Be.current = 0, L.current = null, R.current = 0;
122
+ }, [a]), l(() => {
123
+ if (!a || N || B || V) return;
124
+ let e = z[z.length - 1]?.id, t = j?.lastReadMessageId ?? "", n = (j?.unreadCount ?? 0) > 0;
125
+ if (e) {
126
+ if (L.current !== e && (L.current = e, R.current = 0), !n && (e === t || e === ze.current) || I.current.has(e)) return;
127
+ let r = e, i = ++Be.current;
128
+ I.current.add(r), F({
129
+ conversationId: a,
130
+ messageId: r
131
+ }).then((e) => {
132
+ if (!e) throw Error("markConversationAsRead returned no membership");
133
+ Be.current === i && (ze.current = r, R.current = 0);
134
+ }).catch((e) => {
135
+ console.warn("[conversations] markConversationAsRead failed:", e), R.current < je && (R.current += 1, He((e) => e + 1));
136
+ }).finally(() => {
137
+ I.current.delete(r);
138
+ });
139
+ return;
140
+ }
141
+ let r = "conversation";
142
+ L.current !== r && (L.current = r, R.current = 0), !(!n || I.current.has(r)) && (I.current.add(r), F({ conversationId: a }).then((e) => {
143
+ if (!e) throw Error("markConversationAsRead returned no membership");
144
+ R.current = 0;
145
+ }).catch((e) => {
146
+ console.warn("[conversations] markConversationAsRead failed:", e), R.current < je && (R.current += 1, He((e) => e + 1));
147
+ }).finally(() => {
148
+ I.current.delete(r);
149
+ }));
150
+ }, [
151
+ a,
152
+ j?.lastReadMessageId,
153
+ j?.unreadCount,
154
+ N,
155
+ F,
156
+ z,
157
+ V,
158
+ B,
159
+ Ve
160
+ ]), l(() => {
161
+ if (!W) return;
122
162
  let e = (e) => {
123
- K.current && !K.current.contains(e.target) && z(!1);
163
+ it.current && !it.current.contains(e.target) && G(!1);
124
164
  };
125
165
  return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
126
- }, [R]);
127
- let tt = c((e) => {
128
- G({
166
+ }, [W]);
167
+ let ut = c((e) => {
168
+ rt({
129
169
  id: e.id,
130
170
  content: e.content,
131
171
  sender: e.sender.name
132
172
  });
133
- }, []), nt = c(async (e, t) => {
173
+ }, []), dt = c(async (e, t) => {
134
174
  try {
135
- await Ue(e, t);
175
+ await qe(e, t);
136
176
  } catch {
137
- await We(e, t).catch(() => {});
177
+ await Je(e, t).catch(() => {});
138
178
  }
139
- }, [Ue, We]), rt = c((e) => {
140
- V(e.id), U(e.content);
141
- }, []), it = c(async () => {
142
- !B || !H.trim() || L || (await Ve(B, H.trim()), V(null), U(""));
179
+ }, [qe, Je]), ft = c((e) => {
180
+ q(e.id), Y(e.content);
181
+ }, []), pt = c(async () => {
182
+ !K || !J.trim() || U || (await Ge(K, J.trim()), q(null), Y(""));
143
183
  }, [
144
- B,
145
- H,
146
- L,
147
- Ve
148
- ]), at = c(() => {
149
- V(null), U("");
150
- }, []), ot = c(async (e) => {
151
- if (window.confirm(S("conversations.confirmDeleteMessage", "Delete this message? This action cannot be undone."))) {
152
- ce("medium");
184
+ K,
185
+ J,
186
+ U,
187
+ Ge
188
+ ]), mt = c(() => {
189
+ q(null), Y("");
190
+ }, []), ht = c(async (e) => {
191
+ if (window.confirm(x("conversations.confirmDeleteMessage", "Delete this message? This action cannot be undone."))) {
192
+ le("medium");
153
193
  try {
154
- await He(e), ze(), s("success");
194
+ await Ke(e), Ue(), s("success");
155
195
  } catch (e) {
156
196
  console.error("[microfe-conversations] message delete failed", e), s("error");
157
197
  }
158
198
  }
159
199
  }, [
160
- He,
161
- ze,
162
- S
163
- ]), st = c(async (e, t) => {
200
+ Ke,
201
+ Ue,
202
+ x
203
+ ]), gt = c(async (e, t) => {
164
204
  if (t) {
165
- await Ke(e);
205
+ await Xe(e);
166
206
  return;
167
207
  }
168
- await Ge(e);
169
- }, [Ge, Ke]), $ = c(async () => {
170
- a && (M?.isPinned ? await Ye(a) : await Je(a), z(!1));
208
+ await Ye(e);
209
+ }, [Ye, Xe]), _t = c(async () => {
210
+ a && (j?.isPinned ? await $e(a) : await Qe(a), G(!1));
171
211
  }, [
172
212
  a,
173
- M?.isPinned,
174
- Je,
175
- Ye
176
- ]), ct = c(async () => {
177
- a && (M?.isMuted ? await Ze(a) : await Xe(a), z(!1));
213
+ j?.isPinned,
214
+ Qe,
215
+ $e
216
+ ]), vt = c(async () => {
217
+ a && (j?.isMuted ? await tt(a) : await et(a), G(!1));
178
218
  }, [
179
219
  a,
180
- M?.isMuted,
181
- Xe,
182
- Ze
183
- ]), lt = c(async () => {
220
+ j?.isMuted,
221
+ et,
222
+ tt
223
+ ]), yt = c(async () => {
184
224
  if (a) try {
185
- await qe(a), x.emit("conversations.conversation.archived", { conversationId: a }), z(!1), o(v || "/conversations");
225
+ await Ze(a), b.emit("conversations.conversation.archived", { conversationId: a }), G(!1), o(_ || "/conversations");
186
226
  } catch (e) {
187
227
  console.error("[microfe-conversations] conversation archive failed", e), s("error");
188
228
  }
189
229
  }, [
190
- qe,
191
- v,
192
- x,
230
+ Ze,
231
+ _,
232
+ b,
193
233
  a,
194
234
  o
195
- ]), ut = c(async () => {
196
- if (a && window.confirm(S("conversations.confirmLeaveConversation", "Leave this conversation? You will lose access unless someone adds you again."))) try {
197
- await Qe(a), q && x.emit("conversations.member.removed", {
235
+ ]), bt = c(async () => {
236
+ if (a && window.confirm(x("conversations.confirmLeaveConversation", "Leave this conversation? You will lose access unless someone adds you again."))) try {
237
+ await nt(a), Z && b.emit("conversations.member.removed", {
198
238
  conversationId: a,
199
- userId: q
200
- }), z(!1), o(v || "/conversations");
239
+ userId: Z
240
+ }), G(!1), o(_ || "/conversations");
201
241
  } catch (e) {
202
242
  console.error("[microfe-conversations] conversation leave failed", e), s("error");
203
243
  }
204
244
  }, [
205
- v,
206
- x,
245
+ _,
246
+ b,
207
247
  a,
208
- q,
209
- Qe,
248
+ Z,
249
+ nt,
210
250
  o,
211
- S
212
- ]), dt = c(() => {
213
- if (J?.contextHref) {
251
+ x
252
+ ]), xt = c(() => {
253
+ if (Q?.contextHref) {
214
254
  try {
215
- let e = new URL(J.contextHref);
255
+ let e = new URL(Q.contextHref);
216
256
  if (e.origin === window.location.origin) {
217
257
  o(`${e.pathname}${e.search}${e.hash}`);
218
258
  return;
219
259
  }
220
260
  } catch {}
221
- window.location.assign(J.contextHref);
261
+ window.location.assign(Q.contextHref);
222
262
  }
223
- }, [o, J?.contextHref]), ft = u(() => {
263
+ }, [o, Q?.contextHref]), St = u(() => {
224
264
  let e = [{
225
265
  id: "send-message",
226
- label: S("conversations.nextSteps.send.label", "Send your first reply"),
227
- description: S("conversations.nextSteps.send.description", "Jump to the composer and start the conversation."),
266
+ label: x("conversations.nextSteps.send.label", "Send your first reply"),
267
+ description: x("conversations.nextSteps.send.description", "Jump to the composer and start the conversation."),
228
268
  icon: /* @__PURE__ */ h(m, {
229
269
  size: 14,
230
270
  "aria-hidden": "true"
231
271
  }),
232
- onClick: j,
233
- done: Y.length > 0
272
+ onClick: A,
273
+ done: $.length > 0
234
274
  }];
235
- return M?.isGroup && e.push({
275
+ return j?.isGroup && e.push({
236
276
  id: "view-participants",
237
- label: S("conversations.nextSteps.participants.label", "Review participants"),
238
- description: S("conversations.nextSteps.participants.description", "See who can read and post in this conversation."),
239
- icon: /* @__PURE__ */ h(ye, {
277
+ label: x("conversations.nextSteps.participants.label", "Review participants"),
278
+ description: x("conversations.nextSteps.participants.description", "See who can read and post in this conversation."),
279
+ icon: /* @__PURE__ */ h(be, {
240
280
  size: 14,
241
281
  "aria-hidden": "true"
242
282
  }),
243
283
  onClick: () => {
244
- w || T();
284
+ C || w();
245
285
  }
246
- }), J?.contextHref && e.push({
286
+ }), Q?.contextHref && e.push({
247
287
  id: "open-context",
248
- label: S("conversations.nextSteps.context.label", "Open the related item"),
249
- description: S("conversations.nextSteps.context.description", "Jump to the page or record this conversation is about."),
250
- icon: /* @__PURE__ */ h(pe, {
288
+ label: x("conversations.nextSteps.context.label", "Open the related item"),
289
+ description: x("conversations.nextSteps.context.description", "Jump to the page or record this conversation is about."),
290
+ icon: /* @__PURE__ */ h(me, {
251
291
  size: 14,
252
292
  "aria-hidden": "true"
253
293
  }),
254
- onClick: dt
294
+ onClick: xt
255
295
  }), e.push({
256
296
  id: "pin-conversation",
257
- label: M?.isPinned ? S("conversations.nextSteps.unpin.label", "Unpin this conversation") : S("conversations.nextSteps.pin.label", "Pin for quick access"),
258
- description: S("conversations.nextSteps.pin.description", "Keep important conversations at the top of your inbox."),
297
+ label: j?.isPinned ? x("conversations.nextSteps.unpin.label", "Unpin this conversation") : x("conversations.nextSteps.pin.label", "Pin for quick access"),
298
+ description: x("conversations.nextSteps.pin.description", "Keep important conversations at the top of your inbox."),
259
299
  icon: /* @__PURE__ */ h(p, {
260
300
  size: 14,
261
301
  "aria-hidden": "true"
262
302
  }),
263
- onClick: () => void $(),
264
- done: M?.isPinned
303
+ onClick: () => void _t(),
304
+ done: j?.isPinned
265
305
  }), e;
266
306
  }, [
267
- M?.isGroup,
268
- M?.isPinned,
269
- Y.length,
270
- j,
271
- dt,
272
- $,
307
+ j?.isGroup,
308
+ j?.isPinned,
309
+ $.length,
310
+ A,
311
+ xt,
312
+ _t,
313
+ C,
314
+ Q?.contextHref,
273
315
  w,
274
- J?.contextHref,
275
- T,
276
- S
316
+ x
277
317
  ]);
278
- return !M && Ie ? /* @__PURE__ */ h("div", {
318
+ return !j && N ? /* @__PURE__ */ h("div", {
279
319
  className: "flex items-center justify-center h-[calc(100vh-64px)] text-sm text-text-secondary",
280
- children: S("conversations.loading", "Loading conversation...")
281
- }) : !M || P ? /* @__PURE__ */ h("div", {
320
+ children: x("conversations.loading", "Loading conversation...")
321
+ }) : !j || P ? /* @__PURE__ */ h("div", {
282
322
  className: "flex h-[calc(100vh-64px)] items-center justify-center p-8",
283
- children: /* @__PURE__ */ h(Ee, {
323
+ children: /* @__PURE__ */ h(De, {
284
324
  illustration: "empty-generic",
285
- title: P ? S("conversations.unavailableTitle", "Conversation unavailable") : S("conversations.notFound", "Conversation not found"),
286
- description: P ? S("conversations.unavailable", "We couldn't load this conversation. Please try again.") : S("conversations.notFoundDescription", "This conversation may have been deleted, archived, or you no longer have access to it."),
287
- action: /* @__PURE__ */ h(Te, {
325
+ title: P ? x("conversations.unavailableTitle", "Conversation unavailable") : x("conversations.notFound", "Conversation not found"),
326
+ description: P ? x("conversations.unavailable", "We couldn't load this conversation. Please try again.") : x("conversations.notFoundDescription", "This conversation may have been deleted, archived, or you no longer have access to it."),
327
+ action: /* @__PURE__ */ h(Ee, {
288
328
  type: "button",
289
- onClick: () => o(v || "/conversations"),
290
- children: S("conversations.back", "Back to conversations")
329
+ onClick: () => o(_ || "/conversations"),
330
+ children: x("conversations.back", "Back to conversations")
291
331
  })
292
332
  })
293
333
  }) : /* @__PURE__ */ g("div", {
@@ -303,73 +343,73 @@ function v() {
303
343
  className: "flex items-center gap-3 min-w-0",
304
344
  children: [/* @__PURE__ */ h("button", {
305
345
  type: "button",
306
- onClick: () => o(v || "/conversations"),
346
+ onClick: () => o(_ || "/conversations"),
307
347
  className: "flex min-h-10 min-w-10 items-center justify-center rounded-lg text-text-secondary transition-colors hover:bg-bg-sunken/50 hover:text-text-primary",
308
- children: /* @__PURE__ */ h(ue, { size: 18 })
348
+ children: /* @__PURE__ */ h(de, { size: 18 })
309
349
  }), /* @__PURE__ */ g("div", {
310
350
  className: "min-w-0",
311
351
  children: [/* @__PURE__ */ g("div", {
312
352
  className: "flex items-center gap-1.5",
313
- children: [M.type === "CHANNEL" && /* @__PURE__ */ h(me, {
353
+ children: [j.type === "CHANNEL" && /* @__PURE__ */ h(he, {
314
354
  size: 14,
315
355
  className: "text-text-secondary flex-shrink-0"
316
356
  }), /* @__PURE__ */ h("h2", {
317
357
  className: "text-sm font-semibold text-text-primary truncate",
318
- children: M.title
358
+ children: j.title
319
359
  })]
320
360
  }), /* @__PURE__ */ h("p", {
321
361
  className: "text-xs text-text-secondary",
322
- children: M.type === "DIRECT" ? S("conversations.directConversation", "Direct conversation") : M.type === "CHANNEL" ? `${S("conversations.channel", "Channel")} · ${M.memberCount} ${S("conversations.membersCountLabel", "members")}` : M.type === "ANNOUNCEMENT" ? `${S("conversations.announcement", "Announcement")} · ${M.memberCount} ${S("conversations.membersCountLabel", "members")}` : `${M.memberCount} ${S("conversations.membersCountLabel", "members")}`
362
+ children: j.type === "DIRECT" ? x("conversations.directConversation", "Direct conversation") : j.type === "CHANNEL" ? `${x("conversations.channel", "Channel")} · ${j.memberCount} ${x("conversations.membersCountLabel", "members")}` : j.type === "ANNOUNCEMENT" ? `${x("conversations.announcement", "Announcement")} · ${j.memberCount} ${x("conversations.membersCountLabel", "members")}` : `${j.memberCount} ${x("conversations.membersCountLabel", "members")}`
323
363
  })]
324
364
  })]
325
365
  }), /* @__PURE__ */ g("div", {
326
366
  className: "flex shrink-0 items-center gap-1",
327
367
  children: [
328
- J?.contextHref && /* @__PURE__ */ h(b, {
368
+ Q?.contextHref && /* @__PURE__ */ h(y, {
329
369
  dataTour: "conversation-open-context",
330
- icon: /* @__PURE__ */ h(pe, { size: 16 }),
331
- label: S("conversations.openContext", "Open context"),
332
- onClick: dt
370
+ icon: /* @__PURE__ */ h(me, { size: 16 }),
371
+ label: x("conversations.openContext", "Open context"),
372
+ onClick: xt
333
373
  }),
334
- M.isGroup && /* @__PURE__ */ h(b, {
374
+ j.isGroup && /* @__PURE__ */ h(y, {
335
375
  dataTour: "conversation-participants-button",
336
- icon: /* @__PURE__ */ h(ye, { size: 16 }),
337
- label: S("conversations.participants", "Participants"),
338
- active: w,
339
- onClick: T
376
+ icon: /* @__PURE__ */ h(be, { size: 16 }),
377
+ label: x("conversations.participants", "Participants"),
378
+ active: C,
379
+ onClick: w
340
380
  }),
341
381
  /* @__PURE__ */ g("div", {
342
382
  className: "relative",
343
- ref: K,
344
- children: [/* @__PURE__ */ h(b, {
345
- icon: /* @__PURE__ */ h(_e, { size: 16 }),
346
- label: S("conversations.moreOptions", "More options"),
347
- active: R,
348
- onClick: () => z((e) => !e)
349
- }), R && /* @__PURE__ */ g("div", {
383
+ ref: it,
384
+ children: [/* @__PURE__ */ h(y, {
385
+ icon: /* @__PURE__ */ h(ve, { size: 16 }),
386
+ label: x("conversations.moreOptions", "More options"),
387
+ active: W,
388
+ onClick: () => G((e) => !e)
389
+ }), W && /* @__PURE__ */ g("div", {
350
390
  className: "absolute right-0 top-full mt-1 w-48 bg-popover border border-border-subtle rounded-lg shadow-lg z-50 py-1 animate-in fade-in-0 zoom-in-95 duration-100",
351
391
  children: [
352
- /* @__PURE__ */ h(y, {
353
- icon: M.isPinned ? /* @__PURE__ */ h(ve, { size: 14 }) : /* @__PURE__ */ h(p, { size: 14 }),
354
- label: M.isPinned ? S("conversations.unpinConversation", "Unpin conversation") : S("conversations.pinConversation", "Pin conversation"),
355
- onClick: () => void $()
392
+ /* @__PURE__ */ h(v, {
393
+ icon: j.isPinned ? /* @__PURE__ */ h(ye, { size: 14 }) : /* @__PURE__ */ h(p, { size: 14 }),
394
+ label: j.isPinned ? x("conversations.unpinConversation", "Unpin conversation") : x("conversations.pinConversation", "Pin conversation"),
395
+ onClick: () => void _t()
356
396
  }),
357
- /* @__PURE__ */ h(y, {
358
- icon: M.isMuted ? /* @__PURE__ */ h(de, { size: 14 }) : /* @__PURE__ */ h(fe, { size: 14 }),
359
- label: M.isMuted ? S("conversations.unmuteConversation", "Unmute conversation") : S("conversations.muteConversation", "Mute conversation"),
360
- onClick: () => void ct()
397
+ /* @__PURE__ */ h(v, {
398
+ icon: j.isMuted ? /* @__PURE__ */ h(fe, { size: 14 }) : /* @__PURE__ */ h(pe, { size: 14 }),
399
+ label: j.isMuted ? x("conversations.unmuteConversation", "Unmute conversation") : x("conversations.muteConversation", "Mute conversation"),
400
+ onClick: () => void vt()
361
401
  }),
362
402
  /* @__PURE__ */ h("div", { className: "h-px bg-border my-1" }),
363
- /* @__PURE__ */ h(y, {
364
- icon: /* @__PURE__ */ h(le, { size: 14 }),
365
- label: S("conversations.archiveConversation", "Archive conversation"),
366
- onClick: () => void lt(),
403
+ /* @__PURE__ */ h(v, {
404
+ icon: /* @__PURE__ */ h(ue, { size: 14 }),
405
+ label: x("conversations.archiveConversation", "Archive conversation"),
406
+ onClick: () => void yt(),
367
407
  destructive: !0
368
408
  }),
369
- M.isGroup && /* @__PURE__ */ h(y, {
370
- icon: /* @__PURE__ */ h(ge, { size: 14 }),
371
- label: S("conversations.leaveConversation", "Leave conversation"),
372
- onClick: () => void ut(),
409
+ j.isGroup && /* @__PURE__ */ h(v, {
410
+ icon: /* @__PURE__ */ h(_e, { size: 14 }),
411
+ label: x("conversations.leaveConversation", "Leave conversation"),
412
+ onClick: () => void bt(),
373
413
  destructive: !0
374
414
  })
375
415
  ]
@@ -381,127 +421,127 @@ function v() {
381
421
  /* @__PURE__ */ g("div", {
382
422
  className: "flex-1 overflow-y-auto py-4 space-y-0.5",
383
423
  children: [
384
- J?.pagePath && /* @__PURE__ */ g("div", {
424
+ Q?.pagePath && /* @__PURE__ */ g("div", {
385
425
  className: "mx-4 mb-4 rounded-lg border border-border-subtle bg-bg-sunken/20 px-3 py-2 text-xs text-text-secondary",
386
426
  children: [/* @__PURE__ */ h("span", {
387
427
  className: "font-medium text-text-primary",
388
- children: J.contextTitle || J.pagePath
389
- }), J.entityType && J.entityId ? S("conversations.contextEntityMeta", " · {{entityType}} {{entityId}}", {
390
- entityType: J.entityType,
391
- entityId: J.entityId
428
+ children: Q.contextTitle || Q.pagePath
429
+ }), Q.entityType && Q.entityId ? x("conversations.contextEntityMeta", " · {{entityType}} {{entityId}}", {
430
+ entityType: Q.entityType,
431
+ entityId: Q.entityId
392
432
  }) : ""]
393
433
  }),
394
- Re && /* @__PURE__ */ h("div", {
434
+ V && /* @__PURE__ */ h("div", {
395
435
  className: "mx-4 mb-4 rounded-lg border border-status-warning-border bg-status-warning-bg px-3 py-2 text-sm text-status-warning-text",
396
- children: S("conversations.messagesUnavailable", "Messages couldn't be loaded right now. The conversation header and actions are still available.")
436
+ children: x("conversations.messagesUnavailable", "Messages couldn't be loaded right now. The conversation header and actions are still available.")
397
437
  }),
398
- Le && /* @__PURE__ */ g("div", {
438
+ B && /* @__PURE__ */ g("div", {
399
439
  className: "mx-4 mb-4 flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-sunken/20 px-3 py-2 text-sm text-text-secondary",
400
- children: [/* @__PURE__ */ h(he, {
440
+ children: [/* @__PURE__ */ h(ge, {
401
441
  size: 14,
402
442
  className: "animate-spin"
403
- }), S("conversations.loadingMessages", "Loading messages...")]
443
+ }), x("conversations.loadingMessages", "Loading messages...")]
404
444
  }),
405
- !Le && !Re && Y.length === 0 && /* @__PURE__ */ g("div", {
445
+ !B && !V && $.length === 0 && /* @__PURE__ */ g("div", {
406
446
  className: "mx-4 mb-4 flex flex-col items-center gap-5 py-6",
407
- children: [/* @__PURE__ */ h(Ee, {
447
+ children: [/* @__PURE__ */ h(De, {
408
448
  illustration: "empty-vibes",
409
- title: S("conversations.noMessagesTitle", "No messages yet"),
410
- description: S("conversations.noMessagesYet", "Start the conversation below — say hello, ask a question, or share an update."),
411
- action: /* @__PURE__ */ g(Te, {
449
+ title: x("conversations.noMessagesTitle", "No messages yet"),
450
+ description: x("conversations.noMessagesYet", "Start the conversation below — say hello, ask a question, or share an update."),
451
+ action: /* @__PURE__ */ g(Ee, {
412
452
  type: "button",
413
- onClick: j,
453
+ onClick: A,
414
454
  children: [/* @__PURE__ */ h(m, {
415
455
  size: 14,
416
456
  "aria-hidden": "true"
417
- }), S("conversations.writeFirstMessage", "Write a message")]
457
+ }), x("conversations.writeFirstMessage", "Write a message")]
418
458
  })
419
- }), /* @__PURE__ */ h(De, {
459
+ }), /* @__PURE__ */ h(Oe, {
420
460
  className: "w-full max-w-md",
421
461
  storageKey: "conversations-detail",
422
- title: S("conversations.nextSteps.title", "Get the most out of this conversation"),
423
- steps: ft
462
+ title: x("conversations.nextSteps.title", "Get the most out of this conversation"),
463
+ steps: St
424
464
  })]
425
465
  }),
426
- Y.map((e, t) => {
427
- let n = Y[t - 1], r = !n || n.authorId !== e.authorId || n.type === "SYSTEM";
428
- return /* @__PURE__ */ h("div", { children: B === e.id ? /* @__PURE__ */ g("div", {
466
+ $.map((e, t) => {
467
+ let n = $[t - 1], r = !n || n.authorId !== e.authorId || n.type === "SYSTEM";
468
+ return /* @__PURE__ */ h("div", { children: K === e.id ? /* @__PURE__ */ g("div", {
429
469
  className: "px-4 py-2",
430
470
  children: [/* @__PURE__ */ g("div", {
431
471
  className: "flex items-center gap-2 text-xs text-text-secondary mb-1",
432
- children: [/* @__PURE__ */ h("span", { children: S("conversations.editingMessage", "Editing message") }), /* @__PURE__ */ h("button", {
472
+ children: [/* @__PURE__ */ h("span", { children: x("conversations.editingMessage", "Editing message") }), /* @__PURE__ */ h("button", {
433
473
  type: "button",
434
- onClick: at,
474
+ onClick: mt,
435
475
  className: "hover:text-text-primary",
436
- children: /* @__PURE__ */ h(be, { size: 12 })
476
+ children: /* @__PURE__ */ h(xe, { size: 12 })
437
477
  })]
438
478
  }), /* @__PURE__ */ g("div", {
439
479
  className: "flex items-end gap-2",
440
480
  children: [/* @__PURE__ */ h("textarea", {
441
- "aria-label": S("conversations.editMessageAria", "Edit message"),
442
- value: H,
443
- onChange: (e) => U(e.target.value),
481
+ "aria-label": x("conversations.editMessageAria", "Edit message"),
482
+ value: J,
483
+ onChange: (e) => Y(e.target.value),
444
484
  onKeyDown: (e) => {
445
- e.key === "Enter" && !e.shiftKey && (e.preventDefault(), it()), e.key === "Escape" && at();
485
+ e.key === "Enter" && !e.shiftKey && (e.preventDefault(), pt()), e.key === "Escape" && mt();
446
486
  },
447
487
  className: "flex-1 px-3 py-2 text-sm rounded-lg border border-border-subtle bg-bg-sunken/30 resize-none focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
448
488
  rows: 2
449
489
  }), /* @__PURE__ */ h("button", {
450
490
  type: "button",
451
- onClick: () => void it(),
452
- disabled: !H.trim() || L,
491
+ onClick: () => void pt(),
492
+ disabled: !J.trim() || U,
453
493
  className: "px-3 py-2 text-xs font-medium rounded-lg bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
454
- children: S("conversations.save", "Save")
494
+ children: x("conversations.save", "Save")
455
495
  })]
456
496
  })]
457
497
  }) : /* @__PURE__ */ h(i, {
458
498
  message: e,
459
- isOwnMessage: e.authorId === q,
499
+ isOwnMessage: e.authorId === Z,
460
500
  showAvatar: r,
461
501
  showSender: r,
462
- onReply: tt,
463
- onReact: (e, t) => void nt(e, t),
464
- onEdit: rt,
465
- onDelete: (e) => void ot(e),
466
- onTogglePin: (e, t) => void st(e, t)
502
+ onReply: ut,
503
+ onReact: (e, t) => void dt(e, t),
504
+ onEdit: ft,
505
+ onDelete: (e) => void ht(e),
506
+ onTogglePin: (e, t) => void gt(e, t)
467
507
  }) }, e.id);
468
508
  }),
469
- /* @__PURE__ */ h("div", { ref: Pe })
509
+ /* @__PURE__ */ h("div", { ref: Le })
470
510
  ]
471
511
  }),
472
512
  /* @__PURE__ */ g("div", {
473
513
  "data-tour": "conversation-message-composer",
474
514
  className: "border-t border-border-seam px-4 py-3 bg-bg-surface",
475
- children: [W && /* @__PURE__ */ g("div", {
515
+ children: [X && /* @__PURE__ */ g("div", {
476
516
  className: "flex items-center gap-2 mb-2 px-3 py-1.5 rounded-lg bg-bg-sunken/50 text-xs text-text-secondary",
477
517
  children: [/* @__PURE__ */ g("span", { children: [
478
- S("conversations.replyingTo", "Replying to"),
518
+ x("conversations.replyingTo", "Replying to"),
479
519
  " ",
480
520
  /* @__PURE__ */ h("strong", {
481
521
  className: "text-text-primary",
482
- children: W.sender
522
+ children: X.sender
483
523
  }),
484
524
  ": ",
485
- W.content.slice(0, 80),
486
- W.content.length > 80 ? "…" : ""
525
+ X.content.slice(0, 80),
526
+ X.content.length > 80 ? "…" : ""
487
527
  ] }), /* @__PURE__ */ h("button", {
488
528
  type: "button",
489
- onClick: () => G(null),
490
- "aria-label": S("conversations.cancelReply", "Cancel reply"),
529
+ onClick: () => rt(null),
530
+ "aria-label": x("conversations.cancelReply", "Cancel reply"),
491
531
  className: "ml-auto flex min-h-9 min-w-9 items-center justify-center rounded-md hover:bg-bg-sunken/70 hover:text-text-primary",
492
- children: /* @__PURE__ */ h(be, { size: 12 })
532
+ children: /* @__PURE__ */ h(xe, { size: 12 })
493
533
  })]
494
534
  }), /* @__PURE__ */ g("div", {
495
535
  className: "flex items-end gap-2",
496
536
  children: [/* @__PURE__ */ h("div", {
497
537
  className: "flex-1 relative",
498
538
  children: /* @__PURE__ */ h("textarea", {
499
- "aria-label": S("conversations.messageComposer", "Message composer"),
500
- ref: A,
501
- value: E,
502
- onChange: (e) => Me(e.target.value),
503
- onKeyDown: et,
504
- placeholder: `${S("conversations.messageConversationPrefix", "Message")} ${M.title}...`,
539
+ "aria-label": x("conversations.messageComposer", "Message composer"),
540
+ ref: k,
541
+ value: T,
542
+ onChange: (e) => Fe(e.target.value),
543
+ onKeyDown: lt,
544
+ placeholder: `${x("conversations.messageConversationPrefix", "Message")} ${j.title}...`,
505
545
  rows: 1,
506
546
  className: n("w-full px-4 py-2.5 text-sm rounded-xl border border-border-subtle bg-bg-sunken/30", "resize-none overflow-hidden placeholder:text-text-secondary", "focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] focus:border-transparent max-h-32"),
507
547
  style: {
@@ -515,11 +555,11 @@ function v() {
515
555
  })
516
556
  }), /* @__PURE__ */ h("button", {
517
557
  type: "button",
518
- "aria-label": S("conversations.sendMessage", "Send message"),
519
- onClick: () => void Q(),
520
- disabled: !E.trim() || I,
521
- className: n("p-2.5 rounded-xl transition-all duration-150", E.trim() && !I ? "bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90 shadow-sm" : "bg-bg-sunken text-text-secondary cursor-not-allowed"),
522
- children: I ? /* @__PURE__ */ h(he, {
558
+ "aria-label": x("conversations.sendMessage", "Send message"),
559
+ onClick: () => void ct(),
560
+ disabled: !T.trim() || H,
561
+ className: n("p-2.5 rounded-xl transition-all duration-150", T.trim() && !H ? "bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90 shadow-sm" : "bg-bg-sunken text-text-secondary cursor-not-allowed"),
562
+ children: H ? /* @__PURE__ */ h(ge, {
523
563
  size: 18,
524
564
  className: "animate-spin"
525
565
  }) : /* @__PURE__ */ h(m, { size: 18 })
@@ -528,7 +568,7 @@ function v() {
528
568
  })
529
569
  ]
530
570
  }),
531
- w && M.isGroup && /* @__PURE__ */ h("aside", {
571
+ C && j.isGroup && /* @__PURE__ */ h("aside", {
532
572
  className: "absolute inset-y-0 right-0 z-20 w-full max-w-72 border-l border-border-seam bg-bg-surface shadow-lg animate-in slide-in-from-right-4 duration-200 md:relative md:z-auto md:w-64 md:shadow-none",
533
573
  children: /* @__PURE__ */ g("div", {
534
574
  className: "p-4",
@@ -537,20 +577,20 @@ function v() {
537
577
  children: [/* @__PURE__ */ g("h3", {
538
578
  className: "text-sm font-semibold text-text-primary",
539
579
  children: [
540
- S("conversations.members", "Members"),
580
+ x("conversations.members", "Members"),
541
581
  " (",
542
- M.memberCount ?? Z.length,
582
+ j.memberCount ?? ot.length,
543
583
  ")"
544
584
  ]
545
585
  }), /* @__PURE__ */ h("button", {
546
586
  type: "button",
547
- onClick: T,
587
+ onClick: w,
548
588
  className: "p-1 rounded text-text-secondary hover:text-text-primary",
549
589
  children: /* @__PURE__ */ h(p, { size: 14 })
550
590
  })]
551
591
  }), /* @__PURE__ */ g("div", {
552
592
  className: "space-y-1",
553
- children: [Z.map((e) => /* @__PURE__ */ g("div", {
593
+ children: [ot.map((e) => /* @__PURE__ */ g("div", {
554
594
  className: "flex items-center gap-2.5 px-2 py-1.5 rounded-lg hover:bg-bg-sunken/50",
555
595
  children: [/* @__PURE__ */ h("div", {
556
596
  className: "size-7 rounded-full bg-bg-sunken flex items-center justify-center text-xs font-medium text-text-secondary",
@@ -565,32 +605,32 @@ function v() {
565
605
  children: e.role
566
606
  })]
567
607
  })]
568
- }, e.id)), $e > 0 && /* @__PURE__ */ g("p", {
608
+ }, e.id)), st > 0 && /* @__PURE__ */ g("p", {
569
609
  className: "px-2 pt-2 text-xs text-text-secondary",
570
610
  children: [
571
- S("conversations.moreMembersPrefix", "and"),
611
+ x("conversations.moreMembersPrefix", "and"),
572
612
  " ",
573
- $e,
613
+ st,
574
614
  " ",
575
- S("conversations.moreMembersSuffix", "more")
615
+ x("conversations.moreMembersSuffix", "more")
576
616
  ]
577
617
  })]
578
618
  })]
579
619
  })
580
620
  }),
581
- /* @__PURE__ */ h(se, {
582
- open: Ne,
583
- title: S("conversations.quota.messages.title", "Message Quota Reached"),
584
- description: S("conversations.quota.messages.description", "You've reached the message limit for your current plan. View billing to upgrade or add more capacity."),
585
- onClose: () => D(!1),
621
+ /* @__PURE__ */ h(ce, {
622
+ open: Ie,
623
+ title: x("conversations.quota.messages.title", "Message Quota Reached"),
624
+ description: x("conversations.quota.messages.description", "You've reached the message limit for your current plan. View billing to upgrade or add more capacity."),
625
+ onClose: () => E(!1),
586
626
  onConfirm: () => {
587
- D(!1), o("/billing");
627
+ E(!1), o("/billing");
588
628
  }
589
629
  })
590
630
  ]
591
631
  });
592
632
  }
593
- function y({ icon: e, label: t, onClick: r, destructive: i }) {
633
+ function v({ icon: e, label: t, onClick: r, destructive: i }) {
594
634
  return /* @__PURE__ */ g("button", {
595
635
  type: "button",
596
636
  onClick: r,
@@ -598,7 +638,7 @@ function y({ icon: e, label: t, onClick: r, destructive: i }) {
598
638
  children: [e, /* @__PURE__ */ h("span", { children: t })]
599
639
  });
600
640
  }
601
- function b({ icon: e, label: t, active: r, dataTour: i, onClick: ee }) {
641
+ function y({ icon: e, label: t, active: r, dataTour: i, onClick: ee }) {
602
642
  return /* @__PURE__ */ h(a, {
603
643
  permission: o.CONVERSATION_READ,
604
644
  allowUnavailablePermissions: !0,
@@ -614,6 +654,6 @@ function b({ icon: e, label: t, active: r, dataTour: i, onClick: ee }) {
614
654
  });
615
655
  }
616
656
  //#endregion
617
- export { v as ConversationDetailPage };
657
+ export { _ as ConversationDetailPage };
618
658
 
619
659
  //# sourceMappingURL=ConversationDetailPage.js.map