@burdenoff/microfe-conversations 2026.601.1 → 2026.602.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.
@@ -0,0 +1,99 @@
1
+ import { useTr as e } from "../utils/i18n.js";
2
+ import { cn as t } from "../utils/cn.js";
3
+ import { useWorkspaceDirectory as n } from "../hooks/useConversationQueries.js";
4
+ import { useMemo as r, useState as i } from "react";
5
+ import { X as a } from "lucide-react";
6
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
7
+ import { Command as c, CommandEmpty as l, CommandGroup as u, CommandInput as d, CommandItem as f, CommandList as p } from "@burdenoff/fe-libs/ui";
8
+ //#region src/conversations/components/MemberPicker.tsx
9
+ function m(e) {
10
+ let t = e.trim().split(/\s+/).filter(Boolean);
11
+ return t.length === 0 ? "?" : t.length === 1 ? t[0].slice(0, 2).toUpperCase() : `${t[0][0] ?? ""}${t[t.length - 1][0] ?? ""}`.toUpperCase();
12
+ }
13
+ function h({ member: e, size: n = "md" }) {
14
+ let r = n === "sm" ? "size-5 text-[10px]" : "size-8 text-xs";
15
+ return e.avatar ? /* @__PURE__ */ o("img", {
16
+ src: e.avatar,
17
+ alt: "",
18
+ className: t("rounded-full object-cover", r)
19
+ }) : /* @__PURE__ */ o("span", {
20
+ "aria-hidden": "true",
21
+ className: t("inline-flex items-center justify-center rounded-full bg-muted font-medium text-muted-foreground", r),
22
+ children: m(e.name)
23
+ });
24
+ }
25
+ function g({ selected: t, onAdd: m, onRemove: g, single: _ = !1, excludeIds: v = [] }) {
26
+ let y = e(), [b, x] = i(""), { members: S, loading: C } = n(b), w = r(() => {
27
+ let e = new Set(v);
28
+ for (let n of t) e.add(n.id);
29
+ return e;
30
+ }, [v, t]), T = r(() => S.filter((e) => !w.has(e.id)), [S, w]), E = (e) => {
31
+ m(e), x("");
32
+ };
33
+ return /* @__PURE__ */ s("div", {
34
+ className: "space-y-2",
35
+ children: [
36
+ t.length > 0 && /* @__PURE__ */ o("div", {
37
+ className: "flex flex-wrap gap-2",
38
+ children: t.map((e) => /* @__PURE__ */ s("span", {
39
+ className: "inline-flex items-center gap-1.5 rounded-full bg-primary/10 py-1 pl-1 pr-2 text-xs font-medium text-primary",
40
+ children: [
41
+ /* @__PURE__ */ o(h, {
42
+ member: e,
43
+ size: "sm"
44
+ }),
45
+ e.name,
46
+ /* @__PURE__ */ o("button", {
47
+ type: "button",
48
+ "aria-label": y("conversations.removeParticipant", "Remove participant"),
49
+ onClick: () => g(e.id),
50
+ className: "rounded-full p-0.5 hover:bg-primary/20",
51
+ children: /* @__PURE__ */ o(a, { size: 12 })
52
+ })
53
+ ]
54
+ }, e.id))
55
+ }),
56
+ /* @__PURE__ */ s(c, {
57
+ shouldFilter: !1,
58
+ className: "rounded-lg border border-border bg-background",
59
+ children: [/* @__PURE__ */ o(d, {
60
+ value: b,
61
+ onValueChange: x,
62
+ placeholder: y("conversations.memberSearchPlaceholder", "Search members by name or email…")
63
+ }), /* @__PURE__ */ s(p, { children: [
64
+ C && T.length === 0 ? /* @__PURE__ */ o("div", {
65
+ className: "py-6 text-center text-sm text-muted-foreground",
66
+ children: y("conversations.memberSearchLoading", "Loading members…")
67
+ }) : null,
68
+ !C && T.length === 0 ? /* @__PURE__ */ o(l, { children: b.trim() ? y("conversations.memberSearchNoResults", "No members found.") : y("conversations.memberSearchEmpty", "No more members to add.") }) : null,
69
+ T.length > 0 ? /* @__PURE__ */ o(u, {
70
+ heading: y("conversations.members", "Members"),
71
+ children: T.map((e) => /* @__PURE__ */ s(f, {
72
+ value: `${e.name} ${e.email ?? ""} ${e.id}`,
73
+ onSelect: () => E(e),
74
+ className: "gap-2",
75
+ children: [/* @__PURE__ */ o(h, { member: e }), /* @__PURE__ */ s("span", {
76
+ className: "flex min-w-0 flex-col",
77
+ children: [/* @__PURE__ */ o("span", {
78
+ className: "truncate text-sm text-foreground",
79
+ children: e.name
80
+ }), e.email ? /* @__PURE__ */ o("span", {
81
+ className: "truncate text-xs text-muted-foreground",
82
+ children: e.email
83
+ }) : null]
84
+ })]
85
+ }, e.id))
86
+ }) : null
87
+ ] })]
88
+ }),
89
+ _ && t.length > 0 ? /* @__PURE__ */ o("p", {
90
+ className: "text-xs text-muted-foreground",
91
+ children: y("conversations.directMessageSingleHint", "A direct message has exactly one recipient. Selecting another replaces the current one.")
92
+ }) : null
93
+ ]
94
+ });
95
+ }
96
+ //#endregion
97
+ export { g as MemberPicker };
98
+
99
+ //# sourceMappingURL=MemberPicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemberPicker.js","names":[],"sources":["../../../src/conversations/components/MemberPicker.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"@burdenoff/fe-libs/ui\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\nimport {\n useWorkspaceDirectory,\n type WorkspaceDirectoryMember,\n} from \"../hooks/useConversationQueries\";\n\nexport interface MemberPickerProps {\n /** Currently selected members (controlled by the parent). */\n selected: WorkspaceDirectoryMember[];\n /** Add a member to the selection. */\n onAdd: (member: WorkspaceDirectoryMember) => void;\n /** Remove a member from the selection by user id. */\n onRemove: (userId: string) => void;\n /**\n * Single-select mode: only one member may be chosen at a time (e.g. for a\n * direct message). Defaults to multi-select.\n */\n single?: boolean;\n /**\n * Extra user ids to hide from the suggestion list (e.g. the current user).\n * Selected members are always hidden.\n */\n excludeIds?: string[];\n}\n\n/** Two-letter initials derived from a member's display name. */\nfunction initials(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return \"?\";\n if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase();\n return `${parts[0]![0] ?? \"\"}${parts[parts.length - 1]![0] ?? \"\"}`.toUpperCase();\n}\n\ninterface MemberAvatarProps {\n member: WorkspaceDirectoryMember;\n size?: \"sm\" | \"md\";\n}\n\nfunction MemberAvatar({ member, size = \"md\" }: MemberAvatarProps) {\n const dimension = size === \"sm\" ? \"size-5 text-[10px]\" : \"size-8 text-xs\";\n if (member.avatar) {\n return (\n <img\n src={member.avatar}\n alt=\"\"\n className={cn(\"rounded-full object-cover\", dimension)}\n />\n );\n }\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n \"inline-flex items-center justify-center rounded-full bg-muted font-medium text-muted-foreground\",\n dimension,\n )}\n >\n {initials(member.name)}\n </span>\n );\n}\n\n/**\n * MemberPicker — search-as-you-type workspace-member selector.\n *\n * Lists the current workspace's members via the conversations\n * `workspaceDirectory` query (server-side search, debounced in\n * {@link useWorkspaceDirectory}) and renders each as an avatar + name + email\n * row inside the canonical `Command` palette from `@burdenoff/fe-libs/ui`.\n *\n * Selection is controlled by the parent: the picker reports adds/removes by\n * user id so the host owns the `participantIds` it ultimately submits.\n */\nexport function MemberPicker({\n selected,\n onAdd,\n onRemove,\n single = false,\n excludeIds = [],\n}: MemberPickerProps) {\n const tr = useTr();\n const [input, setInput] = useState(\"\");\n const { members, loading } = useWorkspaceDirectory(input);\n\n const hiddenIds = useMemo(() => {\n const ids = new Set<string>(excludeIds);\n for (const member of selected) {\n ids.add(member.id);\n }\n return ids;\n }, [excludeIds, selected]);\n\n const visibleMembers = useMemo(\n () => members.filter((member) => !hiddenIds.has(member.id)),\n [members, hiddenIds],\n );\n\n const handleSelect = (member: WorkspaceDirectoryMember) => {\n onAdd(member);\n setInput(\"\");\n };\n\n return (\n <div className=\"space-y-2\">\n {selected.length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {selected.map((member) => (\n <span\n key={member.id}\n className=\"inline-flex items-center gap-1.5 rounded-full bg-primary/10 py-1 pl-1 pr-2 text-xs font-medium text-primary\"\n >\n <MemberAvatar member={member} size=\"sm\" />\n {member.name}\n <button\n type=\"button\"\n aria-label={tr(\n \"conversations.removeParticipant\",\n \"Remove participant\",\n )}\n onClick={() => onRemove(member.id)}\n className=\"rounded-full p-0.5 hover:bg-primary/20\"\n >\n <X size={12} />\n </button>\n </span>\n ))}\n </div>\n )}\n\n <Command\n shouldFilter={false}\n className=\"rounded-lg border border-border bg-background\"\n >\n <CommandInput\n value={input}\n onValueChange={setInput}\n placeholder={tr(\n \"conversations.memberSearchPlaceholder\",\n \"Search members by name or email…\",\n )}\n />\n <CommandList>\n {loading && visibleMembers.length === 0 ? (\n <div className=\"py-6 text-center text-sm text-muted-foreground\">\n {tr(\"conversations.memberSearchLoading\", \"Loading members…\")}\n </div>\n ) : null}\n\n {!loading && visibleMembers.length === 0 ? (\n <CommandEmpty>\n {input.trim()\n ? tr(\"conversations.memberSearchNoResults\", \"No members found.\")\n : tr(\n \"conversations.memberSearchEmpty\",\n \"No more members to add.\",\n )}\n </CommandEmpty>\n ) : null}\n\n {visibleMembers.length > 0 ? (\n <CommandGroup heading={tr(\"conversations.members\", \"Members\")}>\n {visibleMembers.map((member) => (\n <CommandItem\n key={member.id}\n value={`${member.name} ${member.email ?? \"\"} ${member.id}`}\n onSelect={() => handleSelect(member)}\n className=\"gap-2\"\n >\n <MemberAvatar member={member} />\n <span className=\"flex min-w-0 flex-col\">\n <span className=\"truncate text-sm text-foreground\">\n {member.name}\n </span>\n {member.email ? (\n <span className=\"truncate text-xs text-muted-foreground\">\n {member.email}\n </span>\n ) : null}\n </span>\n </CommandItem>\n ))}\n </CommandGroup>\n ) : null}\n </CommandList>\n </Command>\n\n {single && selected.length > 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n {tr(\n \"conversations.directMessageSingleHint\",\n \"A direct message has exactly one recipient. Selecting another replaces the current one.\",\n )}\n </p>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,285 +1,257 @@
1
- import { useTr as e } from "../utils/i18n.js";
2
- import { cn as t } from "../utils/cn.js";
3
- import { useCreateConversation as n } from "../hooks/useConversationQueries.js";
4
- import { nativeImpact as r, nativeNotify as i } from "../../utils/nativeBridge.js";
5
- import { useCallback as a, useMemo as o, useState as s } from "react";
6
- import { Globe as c, Hash as l, Lock as u, Megaphone as d, MessageCircle as ee, Shield as f, Users as p, X as m } from "lucide-react";
7
- import { useEventBus as h } from "@burdenoff/fe-libs/shared/events";
8
- import { jsx as g, jsxs as _ } from "react/jsx-runtime";
9
- import { Dialog as v, DialogContent as y, DialogDescription as b, DialogFooter as x, DialogHeader as S, DialogTitle as C } from "@burdenoff/fe-libs/ui";
1
+ import { useConversations as e } from "../providers/ConversationsProvider.js";
2
+ import { useTr as t } from "../utils/i18n.js";
3
+ import { cn as n } from "../utils/cn.js";
4
+ import { useCreateConversation as r } from "../hooks/useConversationQueries.js";
5
+ import { nativeImpact as i, nativeNotify as a } from "../../utils/nativeBridge.js";
6
+ import { MemberPicker as o } from "./MemberPicker.js";
7
+ import { useCallback as s, useMemo as c, useState as l } from "react";
8
+ import { Globe as u, Hash as d, Lock as f, Megaphone as p, MessageCircle as m, Shield as h, Users as ee } from "lucide-react";
9
+ import { useEventBus as g } from "@burdenoff/fe-libs/shared/events";
10
+ import { jsx as _, jsxs as v } from "react/jsx-runtime";
11
+ import { Dialog as y, DialogContent as b, DialogDescription as x, DialogFooter as S, DialogHeader as C, DialogTitle as te } from "@burdenoff/fe-libs/ui";
10
12
  //#region src/conversations/components/NewConversationDialog.tsx
11
- function te(e) {
13
+ function w(e) {
12
14
  if ("graphQLErrors" in e) {
13
15
  let t = e.graphQLErrors;
14
16
  if (t && t.length > 0 && t[0]?.message) return t[0].message;
15
17
  }
16
18
  return e.message;
17
19
  }
18
- function w({ open: w, onOpenChange: T, onCreated: E }) {
19
- let { createConversation: D, loading: O, error: k } = n(), A = h(), j = e(), M = o(() => [
20
+ function T({ open: T, onOpenChange: E, onCreated: D }) {
21
+ let { createConversation: O, loading: k, error: A } = r(), { currentUser: j } = e(), M = g(), N = t(), ne = c(() => [
20
22
  {
21
23
  type: "DIRECT",
22
- label: j("conversations.directMessage", "Direct Message"),
23
- description: j("conversations.directMessageDescription", "One-on-one private conversation"),
24
- icon: /* @__PURE__ */ g(ee, { size: 20 })
24
+ label: N("conversations.directMessage", "Direct Message"),
25
+ description: N("conversations.directMessageDescription", "One-on-one private conversation"),
26
+ icon: /* @__PURE__ */ _(m, { size: 20 })
25
27
  },
26
28
  {
27
29
  type: "GROUP",
28
- label: j("conversations.groupChat", "Group Chat"),
29
- description: j("conversations.groupChatDescription", "Invite multiple people to a group conversation"),
30
- icon: /* @__PURE__ */ g(p, { size: 20 })
30
+ label: N("conversations.groupChat", "Group Chat"),
31
+ description: N("conversations.groupChatDescription", "Invite multiple people to a group conversation"),
32
+ icon: /* @__PURE__ */ _(ee, { size: 20 })
31
33
  },
32
34
  {
33
35
  type: "CHANNEL",
34
- label: j("conversations.channel", "Channel"),
35
- description: j("conversations.channelDescription", "A topic-based channel that anyone can join"),
36
- icon: /* @__PURE__ */ g(l, { size: 20 })
36
+ label: N("conversations.channel", "Channel"),
37
+ description: N("conversations.channelDescription", "A topic-based channel that anyone can join"),
38
+ icon: /* @__PURE__ */ _(d, { size: 20 })
37
39
  },
38
40
  {
39
41
  type: "ANNOUNCEMENT",
40
- label: j("conversations.announcement", "Announcement"),
41
- description: j("conversations.announcementDescription", "Broadcast messages to a large audience"),
42
- icon: /* @__PURE__ */ g(d, { size: 20 })
42
+ label: N("conversations.announcement", "Announcement"),
43
+ description: N("conversations.announcementDescription", "Broadcast messages to a large audience"),
44
+ icon: /* @__PURE__ */ _(p, { size: 20 })
43
45
  }
44
- ], [j]), N = o(() => [
46
+ ], [N]), P = c(() => [
45
47
  {
46
48
  value: "PUBLIC",
47
- label: j("conversations.public", "Public"),
48
- description: j("conversations.publicDescription", "Anyone in the workspace can discover and join"),
49
- icon: /* @__PURE__ */ g(c, { size: 16 })
49
+ label: N("conversations.public", "Public"),
50
+ description: N("conversations.publicDescription", "Anyone in the workspace can discover and join"),
51
+ icon: /* @__PURE__ */ _(u, { size: 16 })
50
52
  },
51
53
  {
52
54
  value: "PRIVATE",
53
- label: j("conversations.private", "Private"),
54
- description: j("conversations.privateDescription", "Only invited members can access"),
55
- icon: /* @__PURE__ */ g(u, { size: 16 })
55
+ label: N("conversations.private", "Private"),
56
+ description: N("conversations.privateDescription", "Only invited members can access"),
57
+ icon: /* @__PURE__ */ _(f, { size: 16 })
56
58
  },
57
59
  {
58
60
  value: "PROTECTED",
59
- label: j("conversations.protected", "Protected"),
60
- description: j("conversations.protectedDescription", "Discoverable but requires approval to join"),
61
- icon: /* @__PURE__ */ g(f, { size: 16 })
61
+ label: N("conversations.protected", "Protected"),
62
+ description: N("conversations.protectedDescription", "Discoverable but requires approval to join"),
63
+ icon: /* @__PURE__ */ _(h, { size: 16 })
62
64
  }
63
- ], [j]), [P, F] = s("GROUP"), [I, L] = s(""), [R, z] = s(""), [B, V] = s("PRIVATE"), [H, U] = s(""), [W, G] = s([]), K = P === "DIRECT", q = !K, J = a(() => {
64
- F("GROUP"), L(""), z(""), V("PRIVATE"), U(""), G([]);
65
- }, []), Y = a(() => {
66
- let e = H.trim();
67
- !e || W.includes(e) || (G(K ? [e] : (t) => [...t, e]), U(""));
68
- }, [
69
- H,
70
- W,
71
- K
72
- ]), X = a((e) => {
73
- G((t) => t.filter((t) => t !== e));
74
- }, []), Z = P === "DIRECT" || P === "GROUP", Q = a((e) => {
75
- e || J(), T(e);
76
- }, [T, J]), ne = a(async () => {
77
- if (!(Z && W.length === 0) && !(q && !I.trim())) {
78
- r("light");
65
+ ], [N]), [F, I] = l("GROUP"), [L, R] = l(""), [z, B] = l(""), [V, H] = l("PRIVATE"), [U, W] = l([]), G = F === "DIRECT", K = !G, q = c(() => U.map((e) => e.id), [U]), J = s(() => {
66
+ I("GROUP"), R(""), B(""), H("PRIVATE"), W([]);
67
+ }, []), Y = s((e) => {
68
+ W((t) => t.some((t) => t.id === e.id) ? t : G ? [e] : [...t, e]);
69
+ }, [G]), X = s((e) => {
70
+ W((t) => t.filter((t) => t.id !== e));
71
+ }, []), Z = F === "DIRECT" || F === "GROUP", re = c(() => j?.id ? [j.id] : [], [j?.id]), Q = s((e) => {
72
+ e || J(), E(e);
73
+ }, [E, J]), ie = s(async () => {
74
+ if (!(Z && q.length === 0) && !(K && !L.trim())) {
75
+ i("light");
79
76
  try {
80
- let e = await D({
81
- type: P,
82
- title: q ? I.trim() : void 0,
83
- description: R.trim() || void 0,
84
- participantIds: W,
85
- visibility: B
77
+ let e = await O({
78
+ type: F,
79
+ title: K ? L.trim() : void 0,
80
+ description: z.trim() || void 0,
81
+ participantIds: q,
82
+ visibility: V
86
83
  });
87
84
  if (!e) {
88
- i("error");
85
+ a("error");
89
86
  return;
90
87
  }
91
- i("success"), A.emit("conversations.conversation.created", {
88
+ a("success"), M.emit("conversations.conversation.created", {
92
89
  conversationId: e.id,
93
- conversationType: P,
90
+ conversationType: F,
94
91
  source: "new-conversation-dialog"
95
- }), J(), T(!1), E?.(e.id);
92
+ }), J(), E(!1), D?.(e.id);
96
93
  } catch (e) {
97
- throw i("error"), e;
94
+ throw a("error"), e;
98
95
  }
99
96
  }
100
97
  }, [
101
- A,
98
+ M,
102
99
  Z,
103
- W,
104
100
  q,
105
- I,
106
- D,
107
- P,
108
- R,
109
- B,
101
+ K,
102
+ L,
103
+ O,
104
+ F,
105
+ z,
106
+ V,
110
107
  J,
111
- T,
112
- E
113
- ]), $ = (!Z || W.length > 0) && (!q || I.trim().length > 0);
114
- return /* @__PURE__ */ g(v, {
115
- open: w,
108
+ E,
109
+ D
110
+ ]), $ = (!Z || q.length > 0) && (!K || L.trim().length > 0);
111
+ return /* @__PURE__ */ _(y, {
112
+ open: T,
116
113
  onOpenChange: Q,
117
- children: /* @__PURE__ */ _(y, {
114
+ children: /* @__PURE__ */ v(b, {
118
115
  className: "sm:max-w-[640px] max-h-[90vh] overflow-y-auto",
119
116
  "data-tour": "new-conversation-dialog",
120
117
  children: [
121
- /* @__PURE__ */ _(S, { children: [/* @__PURE__ */ g(C, { children: j("conversations.newConversation", "New Conversation") }), /* @__PURE__ */ g(b, { children: j("conversations.newConversationSubtitle", "Start a new conversation with your team") })] }),
122
- /* @__PURE__ */ _("div", {
118
+ /* @__PURE__ */ v(C, { children: [/* @__PURE__ */ _(te, { children: N("conversations.newConversation", "New Conversation") }), /* @__PURE__ */ _(x, { children: N("conversations.newConversationSubtitle", "Start a new conversation with your team") })] }),
119
+ /* @__PURE__ */ v("div", {
123
120
  className: "space-y-6",
124
121
  children: [
125
- /* @__PURE__ */ _("section", {
122
+ /* @__PURE__ */ v("section", {
126
123
  "data-tour": "conversation-type-selector",
127
124
  className: "space-y-3",
128
- children: [/* @__PURE__ */ g("h3", {
125
+ children: [/* @__PURE__ */ _("h3", {
129
126
  className: "text-sm font-semibold text-foreground",
130
- children: j("conversations.conversationType", "Conversation Type")
131
- }), /* @__PURE__ */ g("div", {
127
+ children: N("conversations.conversationType", "Conversation Type")
128
+ }), /* @__PURE__ */ _("div", {
132
129
  className: "grid grid-cols-1 sm:grid-cols-2 gap-3",
133
- children: M.map((e) => /* @__PURE__ */ _("button", {
130
+ children: ne.map((e) => /* @__PURE__ */ v("button", {
134
131
  type: "button",
135
132
  onClick: () => {
136
- F(e.type), e.type === "DIRECT" && G((e) => e.slice(0, 1));
133
+ I(e.type), e.type === "DIRECT" && W((e) => e.slice(0, 1));
137
134
  },
138
- className: t("flex items-start gap-3 p-4 rounded-xl border text-left transition-all duration-150", P === e.type ? "border-primary bg-primary/5 ring-1 ring-primary/20" : "border-border hover:border-muted-foreground/30 hover:bg-muted/30"),
139
- children: [/* @__PURE__ */ g("div", {
140
- className: t("p-2 rounded-lg", P === e.type ? "bg-primary/10 text-primary" : "bg-muted text-muted-foreground"),
135
+ className: n("flex items-start gap-3 p-4 rounded-xl border text-left transition-all duration-150", F === e.type ? "border-primary bg-primary/5 ring-1 ring-primary/20" : "border-border hover:border-muted-foreground/30 hover:bg-muted/30"),
136
+ children: [/* @__PURE__ */ _("div", {
137
+ className: n("p-2 rounded-lg", F === e.type ? "bg-primary/10 text-primary" : "bg-muted text-muted-foreground"),
141
138
  children: e.icon
142
- }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("p", {
139
+ }), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
143
140
  className: "text-sm font-medium text-foreground",
144
141
  children: e.label
145
- }), /* @__PURE__ */ g("p", {
142
+ }), /* @__PURE__ */ _("p", {
146
143
  className: "text-xs text-muted-foreground mt-0.5",
147
144
  children: e.description
148
145
  })] })]
149
146
  }, e.type))
150
147
  })]
151
148
  }),
152
- !K && /* @__PURE__ */ _("section", {
149
+ !G && /* @__PURE__ */ v("section", {
153
150
  "data-tour": "conversation-visibility-selector",
154
151
  className: "space-y-3",
155
152
  children: [
156
- /* @__PURE__ */ g("h3", {
153
+ /* @__PURE__ */ _("h3", {
157
154
  className: "text-sm font-semibold text-foreground",
158
- children: j("conversations.visibility", "Visibility")
155
+ children: N("conversations.visibility", "Visibility")
159
156
  }),
160
- /* @__PURE__ */ g("div", {
157
+ /* @__PURE__ */ _("div", {
161
158
  className: "flex gap-2 flex-wrap",
162
- children: N.map((e) => /* @__PURE__ */ _("button", {
159
+ children: P.map((e) => /* @__PURE__ */ v("button", {
163
160
  type: "button",
164
- onClick: () => V(e.value),
165
- className: t("flex items-center gap-2 px-4 py-2.5 rounded-lg border text-sm transition-all", B === e.value ? "border-primary bg-primary/5 text-primary font-medium" : "border-border text-muted-foreground hover:text-foreground hover:bg-muted/30"),
161
+ onClick: () => H(e.value),
162
+ className: n("flex items-center gap-2 px-4 py-2.5 rounded-lg border text-sm transition-all", V === e.value ? "border-primary bg-primary/5 text-primary font-medium" : "border-border text-muted-foreground hover:text-foreground hover:bg-muted/30"),
166
163
  children: [e.icon, e.label]
167
164
  }, e.value))
168
165
  }),
169
- /* @__PURE__ */ g("p", {
166
+ /* @__PURE__ */ _("p", {
170
167
  className: "text-xs text-muted-foreground",
171
- children: N.find((e) => e.value === B)?.description
168
+ children: P.find((e) => e.value === V)?.description
172
169
  })
173
170
  ]
174
171
  }),
175
- q && /* @__PURE__ */ _("section", {
172
+ K && /* @__PURE__ */ v("section", {
176
173
  "data-tour": "conversation-create-details",
177
174
  className: "space-y-3",
178
- children: [/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ _("label", {
175
+ children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ v("label", {
179
176
  htmlFor: "conv-title",
180
177
  className: "text-sm font-semibold text-foreground",
181
178
  children: [
182
- j("conversations.name", "Name"),
179
+ N("conversations.name", "Name"),
183
180
  " ",
184
- /* @__PURE__ */ g("span", {
181
+ /* @__PURE__ */ _("span", {
185
182
  className: "text-destructive",
186
183
  children: "*"
187
184
  })
188
185
  ]
189
- }), /* @__PURE__ */ g("input", {
186
+ }), /* @__PURE__ */ _("input", {
190
187
  id: "conv-title",
191
188
  type: "text",
192
- value: I,
193
- onChange: (e) => L(e.target.value),
194
- placeholder: P === "CHANNEL" ? j("conversations.channelNamePlaceholder", "e.g., engineering-general") : j("conversations.conversationNamePlaceholder", "e.g., Product Launch Q1"),
189
+ value: L,
190
+ onChange: (e) => R(e.target.value),
191
+ placeholder: F === "CHANNEL" ? N("conversations.channelNamePlaceholder", "e.g., engineering-general") : N("conversations.conversationNamePlaceholder", "e.g., Product Launch Q1"),
195
192
  maxLength: 200,
196
193
  className: "mt-1.5 w-full px-3 py-2 text-sm rounded-lg border border-border bg-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
197
- })] }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
194
+ })] }), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
198
195
  htmlFor: "conv-desc",
199
196
  className: "text-sm font-semibold text-foreground",
200
- children: j("conversations.description", "Description")
201
- }), /* @__PURE__ */ g("textarea", {
197
+ children: N("conversations.description", "Description")
198
+ }), /* @__PURE__ */ _("textarea", {
202
199
  id: "conv-desc",
203
- value: R,
204
- onChange: (e) => z(e.target.value),
205
- placeholder: j("conversations.descriptionPlaceholder", "What is this conversation about?"),
200
+ value: z,
201
+ onChange: (e) => B(e.target.value),
202
+ placeholder: N("conversations.descriptionPlaceholder", "What is this conversation about?"),
206
203
  rows: 2,
207
204
  maxLength: 1e3,
208
205
  className: "mt-1.5 w-full px-3 py-2 text-sm rounded-lg border border-border bg-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring resize-none"
209
206
  })] })]
210
207
  }),
211
- /* @__PURE__ */ _("section", {
208
+ /* @__PURE__ */ v("section", {
212
209
  "data-tour": "conversation-participants",
213
210
  className: "space-y-3",
214
- children: [
215
- /* @__PURE__ */ _("h3", {
216
- className: "text-sm font-semibold text-foreground",
217
- children: [K ? j("conversations.participantId", "Participant ID") : j("conversations.participantIds", "Participant IDs"), !Z && /* @__PURE__ */ _("span", {
218
- className: "ml-1.5 text-xs font-normal text-muted-foreground",
219
- children: [
220
- "(",
221
- j("conversations.optional", "optional"),
222
- ")"
223
- ]
224
- })]
225
- }),
226
- W.length > 0 && /* @__PURE__ */ g("div", {
227
- className: "flex flex-wrap gap-2",
228
- children: W.map((e) => /* @__PURE__ */ _("span", {
229
- className: "inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-primary/10 text-primary text-xs font-medium",
230
- children: [e, /* @__PURE__ */ g("button", {
231
- type: "button",
232
- "aria-label": j("conversations.removeParticipant", "Remove participant"),
233
- onClick: () => X(e),
234
- className: "p-0.5 rounded-full hover:bg-primary/20",
235
- children: /* @__PURE__ */ g(m, { size: 12 })
236
- })]
237
- }, e))
238
- }),
239
- /* @__PURE__ */ _("div", {
240
- className: "flex items-center gap-2",
241
- children: [/* @__PURE__ */ g("input", {
242
- type: "text",
243
- "aria-label": j("conversations.participantInputLabel", "Add participant"),
244
- value: H,
245
- onChange: (e) => U(e.target.value),
246
- onKeyDown: (e) => {
247
- e.key === "Enter" && (e.preventDefault(), Y());
248
- },
249
- placeholder: j("conversations.participantInputPlaceholder", "Enter user ID and press Enter"),
250
- className: "w-full px-3 py-2 text-sm rounded-lg border border-border bg-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
251
- }), /* @__PURE__ */ g("button", {
252
- type: "button",
253
- onClick: Y,
254
- className: "px-3 py-2 text-sm rounded-lg border border-border hover:bg-muted/50",
255
- children: j("conversations.add", "Add")
256
- })]
257
- })
258
- ]
211
+ children: [/* @__PURE__ */ v("h3", {
212
+ className: "text-sm font-semibold text-foreground",
213
+ children: [G ? N("conversations.recipient", "Recipient") : N("conversations.participants", "Participants"), Z ? /* @__PURE__ */ _("span", {
214
+ className: "ml-1 text-destructive",
215
+ children: "*"
216
+ }) : /* @__PURE__ */ v("span", {
217
+ className: "ml-1.5 text-xs font-normal text-muted-foreground",
218
+ children: [
219
+ "(",
220
+ N("conversations.optional", "optional"),
221
+ ")"
222
+ ]
223
+ })]
224
+ }), /* @__PURE__ */ _(o, {
225
+ selected: U,
226
+ onAdd: Y,
227
+ onRemove: X,
228
+ single: G,
229
+ excludeIds: re
230
+ })]
259
231
  }),
260
- k && /* @__PURE__ */ g("div", {
232
+ A && /* @__PURE__ */ _("div", {
261
233
  className: "text-xs text-destructive rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2",
262
- children: te(k)
234
+ children: w(A)
263
235
  })
264
236
  ]
265
237
  }),
266
- /* @__PURE__ */ _(x, { children: [/* @__PURE__ */ g("button", {
238
+ /* @__PURE__ */ v(S, { children: [/* @__PURE__ */ _("button", {
267
239
  type: "button",
268
240
  onClick: () => Q(!1),
269
241
  className: "px-4 py-2 text-sm font-medium rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors",
270
- children: j("conversations.cancel", "Cancel")
271
- }), /* @__PURE__ */ g("button", {
242
+ children: N("conversations.cancel", "Cancel")
243
+ }), /* @__PURE__ */ _("button", {
272
244
  type: "button",
273
- onClick: () => void ne(),
274
- disabled: !$ || O,
275
- className: t("inline-flex items-center gap-2 px-5 py-2 text-sm font-medium rounded-lg transition-all", $ && !O ? "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm" : "bg-muted text-muted-foreground cursor-not-allowed"),
276
- children: O ? j("conversations.creating", "Creating...") : j("conversations.createConversation", "Create Conversation")
245
+ onClick: () => void ie(),
246
+ disabled: !$ || k,
247
+ className: n("inline-flex items-center gap-2 px-5 py-2 text-sm font-medium rounded-lg transition-all", $ && !k ? "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm" : "bg-muted text-muted-foreground cursor-not-allowed"),
248
+ children: k ? N("conversations.creating", "Creating...") : N("conversations.createConversation", "Create Conversation")
277
249
  })] })
278
250
  ]
279
251
  })
280
252
  });
281
253
  }
282
254
  //#endregion
283
- export { w as NewConversationDialog };
255
+ export { T as NewConversationDialog };
284
256
 
285
257
  //# sourceMappingURL=NewConversationDialog.js.map