@burdenoff/microfe-conversations 2026.625.2 → 2026.625.3

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