@burdenoff/microfe-conversations 2026.601.2 → 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.
- package/dist/conversations/components/MemberPicker.js +99 -0
- package/dist/conversations/components/MemberPicker.js.map +1 -0
- package/dist/conversations/components/NewConversationDialog.js +138 -166
- package/dist/conversations/components/NewConversationDialog.js.map +1 -1
- package/dist/conversations/hooks/useConversationQueries.js +58 -31
- package/dist/conversations/hooks/useConversationQueries.js.map +1 -1
- package/dist/generated/wspace-operations.js +30 -10
- package/dist/generated/wspace-operations.js.map +1 -1
- package/package.json +1 -1
|
@@ -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 {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
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
|
|
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
|
|
19
|
-
let { createConversation:
|
|
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:
|
|
23
|
-
description:
|
|
24
|
-
icon: /* @__PURE__ */
|
|
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:
|
|
29
|
-
description:
|
|
30
|
-
icon: /* @__PURE__ */
|
|
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:
|
|
35
|
-
description:
|
|
36
|
-
icon: /* @__PURE__ */
|
|
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:
|
|
41
|
-
description:
|
|
42
|
-
icon: /* @__PURE__ */
|
|
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
|
-
], [
|
|
46
|
+
], [N]), P = c(() => [
|
|
45
47
|
{
|
|
46
48
|
value: "PUBLIC",
|
|
47
|
-
label:
|
|
48
|
-
description:
|
|
49
|
-
icon: /* @__PURE__ */
|
|
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:
|
|
54
|
-
description:
|
|
55
|
-
icon: /* @__PURE__ */
|
|
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:
|
|
60
|
-
description:
|
|
61
|
-
icon: /* @__PURE__ */
|
|
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
|
-
], [
|
|
64
|
-
|
|
65
|
-
}, []), Y =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
|
81
|
-
type:
|
|
82
|
-
title:
|
|
83
|
-
description:
|
|
84
|
-
participantIds:
|
|
85
|
-
visibility:
|
|
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
|
-
|
|
85
|
+
a("error");
|
|
89
86
|
return;
|
|
90
87
|
}
|
|
91
|
-
|
|
88
|
+
a("success"), M.emit("conversations.conversation.created", {
|
|
92
89
|
conversationId: e.id,
|
|
93
|
-
conversationType:
|
|
90
|
+
conversationType: F,
|
|
94
91
|
source: "new-conversation-dialog"
|
|
95
|
-
}), J(),
|
|
92
|
+
}), J(), E(!1), D?.(e.id);
|
|
96
93
|
} catch (e) {
|
|
97
|
-
throw
|
|
94
|
+
throw a("error"), e;
|
|
98
95
|
}
|
|
99
96
|
}
|
|
100
97
|
}, [
|
|
101
|
-
|
|
98
|
+
M,
|
|
102
99
|
Z,
|
|
103
|
-
W,
|
|
104
100
|
q,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
101
|
+
K,
|
|
102
|
+
L,
|
|
103
|
+
O,
|
|
104
|
+
F,
|
|
105
|
+
z,
|
|
106
|
+
V,
|
|
110
107
|
J,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
]), $ = (!Z ||
|
|
114
|
-
return /* @__PURE__ */
|
|
115
|
-
open:
|
|
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__ */
|
|
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__ */
|
|
122
|
-
/* @__PURE__ */
|
|
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__ */
|
|
122
|
+
/* @__PURE__ */ v("section", {
|
|
126
123
|
"data-tour": "conversation-type-selector",
|
|
127
124
|
className: "space-y-3",
|
|
128
|
-
children: [/* @__PURE__ */
|
|
125
|
+
children: [/* @__PURE__ */ _("h3", {
|
|
129
126
|
className: "text-sm font-semibold text-foreground",
|
|
130
|
-
children:
|
|
131
|
-
}), /* @__PURE__ */
|
|
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:
|
|
130
|
+
children: ne.map((e) => /* @__PURE__ */ v("button", {
|
|
134
131
|
type: "button",
|
|
135
132
|
onClick: () => {
|
|
136
|
-
|
|
133
|
+
I(e.type), e.type === "DIRECT" && W((e) => e.slice(0, 1));
|
|
137
134
|
},
|
|
138
|
-
className:
|
|
139
|
-
children: [/* @__PURE__ */
|
|
140
|
-
className:
|
|
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__ */
|
|
139
|
+
}), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
|
|
143
140
|
className: "text-sm font-medium text-foreground",
|
|
144
141
|
children: e.label
|
|
145
|
-
}), /* @__PURE__ */
|
|
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
|
-
!
|
|
149
|
+
!G && /* @__PURE__ */ v("section", {
|
|
153
150
|
"data-tour": "conversation-visibility-selector",
|
|
154
151
|
className: "space-y-3",
|
|
155
152
|
children: [
|
|
156
|
-
/* @__PURE__ */
|
|
153
|
+
/* @__PURE__ */ _("h3", {
|
|
157
154
|
className: "text-sm font-semibold text-foreground",
|
|
158
|
-
children:
|
|
155
|
+
children: N("conversations.visibility", "Visibility")
|
|
159
156
|
}),
|
|
160
|
-
/* @__PURE__ */
|
|
157
|
+
/* @__PURE__ */ _("div", {
|
|
161
158
|
className: "flex gap-2 flex-wrap",
|
|
162
|
-
children:
|
|
159
|
+
children: P.map((e) => /* @__PURE__ */ v("button", {
|
|
163
160
|
type: "button",
|
|
164
|
-
onClick: () =>
|
|
165
|
-
className:
|
|
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__ */
|
|
166
|
+
/* @__PURE__ */ _("p", {
|
|
170
167
|
className: "text-xs text-muted-foreground",
|
|
171
|
-
children:
|
|
168
|
+
children: P.find((e) => e.value === V)?.description
|
|
172
169
|
})
|
|
173
170
|
]
|
|
174
171
|
}),
|
|
175
|
-
|
|
172
|
+
K && /* @__PURE__ */ v("section", {
|
|
176
173
|
"data-tour": "conversation-create-details",
|
|
177
174
|
className: "space-y-3",
|
|
178
|
-
children: [/* @__PURE__ */
|
|
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
|
-
|
|
179
|
+
N("conversations.name", "Name"),
|
|
183
180
|
" ",
|
|
184
|
-
/* @__PURE__ */
|
|
181
|
+
/* @__PURE__ */ _("span", {
|
|
185
182
|
className: "text-destructive",
|
|
186
183
|
children: "*"
|
|
187
184
|
})
|
|
188
185
|
]
|
|
189
|
-
}), /* @__PURE__ */
|
|
186
|
+
}), /* @__PURE__ */ _("input", {
|
|
190
187
|
id: "conv-title",
|
|
191
188
|
type: "text",
|
|
192
|
-
value:
|
|
193
|
-
onChange: (e) =>
|
|
194
|
-
placeholder:
|
|
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__ */
|
|
194
|
+
})] }), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("label", {
|
|
198
195
|
htmlFor: "conv-desc",
|
|
199
196
|
className: "text-sm font-semibold text-foreground",
|
|
200
|
-
children:
|
|
201
|
-
}), /* @__PURE__ */
|
|
197
|
+
children: N("conversations.description", "Description")
|
|
198
|
+
}), /* @__PURE__ */ _("textarea", {
|
|
202
199
|
id: "conv-desc",
|
|
203
|
-
value:
|
|
204
|
-
onChange: (e) =>
|
|
205
|
-
placeholder:
|
|
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__ */
|
|
208
|
+
/* @__PURE__ */ v("section", {
|
|
212
209
|
"data-tour": "conversation-participants",
|
|
213
210
|
className: "space-y-3",
|
|
214
|
-
children: [
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
|
|
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:
|
|
234
|
+
children: w(A)
|
|
263
235
|
})
|
|
264
236
|
]
|
|
265
237
|
}),
|
|
266
|
-
/* @__PURE__ */
|
|
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:
|
|
271
|
-
}), /* @__PURE__ */
|
|
242
|
+
children: N("conversations.cancel", "Cancel")
|
|
243
|
+
}), /* @__PURE__ */ _("button", {
|
|
272
244
|
type: "button",
|
|
273
|
-
onClick: () => void
|
|
274
|
-
disabled: !$ ||
|
|
275
|
-
className:
|
|
276
|
-
children:
|
|
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 {
|
|
255
|
+
export { T as NewConversationDialog };
|
|
284
256
|
|
|
285
257
|
//# sourceMappingURL=NewConversationDialog.js.map
|