@adatechnology/conversations-ui 0.5.0 → 0.6.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/README.md +82 -20
- package/dist/{chunk-JXJCPN34.js → chunk-FAQLC3TX.js} +1 -1
- package/dist/{chunk-RJMSM3YA.js → chunk-O6457XHK.js} +17 -11
- package/dist/chunk-OVFCLRQQ.js +84 -0
- package/dist/index.d.ts +14 -4
- package/dist/index.js +7 -7
- package/dist/participant/index.d.ts +25 -1
- package/dist/participant/index.js +454 -194
- package/dist/preview/index.js +2 -2
- package/dist/styles.css +106 -0
- package/package.json +3 -3
- package/src/MessageBubble.test.tsx +2 -2
- package/src/MessageText.test.tsx +27 -10
- package/src/MessageText.tsx +25 -17
- package/src/MessageTextCopiedBadge.tsx +10 -2
- package/src/StatusTicks.test.tsx +27 -6
- package/src/StatusTicks.tsx +30 -15
- package/src/cssBlocks.test-helper.ts +31 -0
- package/src/legacyChannels.golden.test.ts +89 -0
- package/src/legacyDefaults.golden.test.tsx +127 -0
- package/src/legacyStyles.fixture.css +1121 -0
- package/src/legacyStyles.golden.test.ts +92 -0
- package/src/messageTextCopyInteraction.test.ts +75 -0
- package/src/messageTextCopyInteraction.ts +37 -0
- package/src/participant/ParticipantChannelBadges.test.tsx +59 -0
- package/src/participant/ParticipantChannelBadges.tsx +75 -0
- package/src/participant/ParticipantConversations.tsx +13 -6
- package/src/participant/ParticipantConversationsScreen.tsx +18 -7
- package/src/participant/ParticipantInbox.test.tsx +99 -2
- package/src/participant/ParticipantInbox.tsx +27 -46
- package/src/participant/ParticipantInboxRow.tsx +75 -0
- package/src/participant/ParticipantInboxSearchField.tsx +34 -0
- package/src/participant/ParticipantMessageBubble.test.tsx +2 -0
- package/src/participant/ParticipantMessageBubble.tsx +3 -3
- package/src/participant/ParticipantProtocolBadge.tsx +74 -0
- package/src/participant/ParticipantProtocolView.test.tsx +208 -0
- package/src/participant/ParticipantThread.test.tsx +19 -2
- package/src/participant/ParticipantThread.tsx +25 -15
- package/src/participant/index.ts +1 -0
- package/src/participant/participant.types.ts +9 -0
- package/src/participant/participantChannels.test.ts +42 -0
- package/src/participant/participantChannels.ts +33 -0
- package/src/participant/participantGrouping.test.ts +101 -3
- package/src/participant/participantGrouping.ts +20 -7
- package/src/participant/participantLabels.ts +29 -0
- package/src/participant/participantProtocol.test.ts +104 -0
- package/src/participant/participantProtocol.ts +52 -0
- package/src/participant/participantProtocolCopy.test.ts +45 -0
- package/src/participant/participantProtocolCopy.ts +32 -0
- package/src/participantLayoutShrink.test.ts +82 -0
- package/src/styles.css +22 -1
- package/dist/chunk-WSFGNR5R.js +0 -55
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MessageText
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-OVFCLRQQ.js";
|
|
4
4
|
import {
|
|
5
5
|
StatusTicks,
|
|
6
6
|
channelCapabilityFor,
|
|
7
7
|
formatFileSize,
|
|
8
8
|
formatTimestamp,
|
|
9
9
|
isSameDay
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-O6457XHK.js";
|
|
11
11
|
import "../chunk-CBYEHPX6.js";
|
|
12
12
|
|
|
13
13
|
// src/participant/ParticipantConversationsScreen.tsx
|
|
14
|
-
import { useMemo as useMemo4, useReducer as
|
|
14
|
+
import { useMemo as useMemo4, useReducer as useReducer3, useRef as useRef7, useState as useState7 } from "react";
|
|
15
|
+
|
|
16
|
+
// src/participant/participantLoadView.ts
|
|
17
|
+
function resolveLoadView({ status, hasItems }) {
|
|
18
|
+
return {
|
|
19
|
+
isLoading: (status === "idle" || status === "loading") && !hasItems,
|
|
20
|
+
hasError: status === "error",
|
|
21
|
+
isEmpty: status === "ready" && !hasItems
|
|
22
|
+
};
|
|
23
|
+
}
|
|
15
24
|
|
|
16
25
|
// src/participant/participantLabels.ts
|
|
17
26
|
var DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS = {
|
|
@@ -52,44 +61,171 @@ var DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS = {
|
|
|
52
61
|
notFound: "Conversation not found",
|
|
53
62
|
loading: "Loading\u2026",
|
|
54
63
|
loadError: "Could not load. Check your connection and try again.",
|
|
55
|
-
loadMore: "Load more"
|
|
64
|
+
loadMore: "Load more",
|
|
65
|
+
searchLabel: "Search conversations",
|
|
66
|
+
searchPlaceholder: "Search by title or protocol",
|
|
67
|
+
noResults: "No conversations found",
|
|
68
|
+
noResultsInFilter: "No results in this filter \u2014 try All",
|
|
69
|
+
noResultsLoadedOnly: "Nothing in the loaded conversations \u2014 load more",
|
|
70
|
+
protocolPrefix: "Protocol",
|
|
71
|
+
copyProtocol: "Copy protocol",
|
|
72
|
+
protocolCopied: "Protocol copied",
|
|
73
|
+
channelsGroup: "Channels in this conversation",
|
|
74
|
+
channelApp: "App",
|
|
75
|
+
channelWhatsapp: "WhatsApp",
|
|
76
|
+
channelEmail: "Email",
|
|
77
|
+
channelPortal: "Portal",
|
|
78
|
+
channelWebchat: "Web chat"
|
|
56
79
|
};
|
|
57
80
|
function formatParticipantLabel(template, count) {
|
|
58
81
|
return template.replace("{count}", String(count));
|
|
59
82
|
}
|
|
60
83
|
|
|
61
|
-
// src/participant/
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
84
|
+
// src/participant/ParticipantChannelBadges.tsx
|
|
85
|
+
import { Globe, Mail, MessageCircle, MessagesSquare, Smartphone } from "lucide-react";
|
|
86
|
+
|
|
87
|
+
// src/participant/participantChannels.ts
|
|
88
|
+
var PARTICIPANT_CHANNEL_ORDER = [
|
|
89
|
+
{ channel: "app", iconName: "Smartphone", labelKey: "channelApp" },
|
|
90
|
+
{ channel: "whatsapp", iconName: "MessageCircle", labelKey: "channelWhatsapp" },
|
|
91
|
+
{ channel: "email", iconName: "Mail", labelKey: "channelEmail" },
|
|
92
|
+
{ channel: "portal", iconName: "Globe", labelKey: "channelPortal" },
|
|
93
|
+
{ channel: "webchat", iconName: "MessagesSquare", labelKey: "channelWebchat" }
|
|
94
|
+
];
|
|
95
|
+
function resolveParticipantChannels(channels) {
|
|
96
|
+
if (channels === void 0 || channels.length === 0) return [];
|
|
97
|
+
const present = new Set(channels);
|
|
98
|
+
return PARTICIPANT_CHANNEL_ORDER.filter((descriptor) => present.has(descriptor.channel));
|
|
99
|
+
}
|
|
100
|
+
function resolveParticipantChannelLabel(descriptor, labels) {
|
|
101
|
+
return labels[descriptor.labelKey];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/participant/ParticipantChannelBadges.tsx
|
|
105
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
106
|
+
var ICONS = {
|
|
107
|
+
Smartphone,
|
|
108
|
+
MessageCircle,
|
|
109
|
+
Mail,
|
|
110
|
+
Globe,
|
|
111
|
+
MessagesSquare
|
|
112
|
+
};
|
|
113
|
+
function BadgeContent({ descriptor, labels, separator }) {
|
|
114
|
+
const Icon = ICONS[descriptor.iconName];
|
|
115
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
116
|
+
/* @__PURE__ */ jsx(Icon, { size: 14, "aria-hidden": true }),
|
|
117
|
+
/* @__PURE__ */ jsx("span", { className: "cv-p-sr-only", children: `${resolveParticipantChannelLabel(descriptor, labels)}${separator}` })
|
|
118
|
+
] });
|
|
119
|
+
}
|
|
120
|
+
function ParticipantChannelBadges({ channels, labels, variant = "list" }) {
|
|
121
|
+
const descriptors = resolveParticipantChannels(channels);
|
|
122
|
+
if (descriptors.length === 0) return null;
|
|
123
|
+
if (variant === "inline") {
|
|
124
|
+
return /* @__PURE__ */ jsxs("span", { className: "cv-p-channels", children: [
|
|
125
|
+
/* @__PURE__ */ jsx("span", { className: "cv-p-sr-only", children: `${labels.channelsGroup}: ` }),
|
|
126
|
+
descriptors.map((descriptor, index) => /* @__PURE__ */ jsx("span", { className: `cv-p-channel cv-p-channel--${descriptor.channel}`, children: /* @__PURE__ */ jsx(
|
|
127
|
+
BadgeContent,
|
|
128
|
+
{
|
|
129
|
+
descriptor,
|
|
130
|
+
labels,
|
|
131
|
+
separator: index < descriptors.length - 1 ? ", " : ""
|
|
132
|
+
}
|
|
133
|
+
) }, descriptor.channel))
|
|
134
|
+
] });
|
|
135
|
+
}
|
|
136
|
+
return /* @__PURE__ */ jsx("ul", { className: "cv-p-channels", "aria-label": labels.channelsGroup, children: descriptors.map((descriptor) => /* @__PURE__ */ jsx("li", { className: `cv-p-channel cv-p-channel--${descriptor.channel}`, children: /* @__PURE__ */ jsx(BadgeContent, { descriptor, labels, separator: "" }) }, descriptor.channel)) });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/participant/ParticipantInboxRow.tsx
|
|
140
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
141
|
+
function formatRowTime(iso, locale) {
|
|
142
|
+
const date = new Date(iso);
|
|
143
|
+
if (isSameDay(date, /* @__PURE__ */ new Date())) return formatTimestamp(iso);
|
|
144
|
+
return date.toLocaleDateString(locale, { day: "2-digit", month: "2-digit" });
|
|
145
|
+
}
|
|
146
|
+
function RowIcon({ props, kind }) {
|
|
147
|
+
const custom = props.renderSubjectIcon?.(props.conversation);
|
|
148
|
+
if (custom !== null && custom !== void 0 && custom !== false && custom !== "") {
|
|
149
|
+
return /* @__PURE__ */ jsx2("span", { className: "cv-p-row__icon cv-p-inbox__icon", "aria-hidden": "true", children: custom });
|
|
150
|
+
}
|
|
151
|
+
return /* @__PURE__ */ jsx2("span", { className: "cv-p-row__icon", "aria-hidden": "true", children: props.group?.icon ?? kind.slice(0, 2) });
|
|
152
|
+
}
|
|
153
|
+
function ParticipantInboxRow(props) {
|
|
154
|
+
const { conversation, group, labels, locale, onSelect } = props;
|
|
155
|
+
const kind = group?.label ?? conversation.subjectType;
|
|
156
|
+
const className = conversation.awaitingParticipant ? "cv-p-row cv-p-row--awaiting" : "cv-p-row";
|
|
157
|
+
const { subjectType, subjectId } = conversation;
|
|
158
|
+
return /* @__PURE__ */ jsxs2("button", { type: "button", className, onClick: () => onSelect({ subjectType, subjectId }), children: [
|
|
159
|
+
/* @__PURE__ */ jsx2(RowIcon, { props, kind }),
|
|
160
|
+
/* @__PURE__ */ jsxs2("span", { className: "cv-p-row__body", children: [
|
|
161
|
+
/* @__PURE__ */ jsx2("span", { className: "cv-p-row__kind", children: kind }),
|
|
162
|
+
/* @__PURE__ */ jsx2("span", { className: "cv-p-row__title", children: conversation.subjectLabel }),
|
|
163
|
+
/* @__PURE__ */ jsxs2("span", { className: "cv-p-row__tags", children: [
|
|
164
|
+
conversation.protocol ? /* @__PURE__ */ jsxs2("span", { className: "cv-p-protocol", children: [
|
|
165
|
+
/* @__PURE__ */ jsxs2("span", { className: "cv-p-sr-only", children: [
|
|
166
|
+
labels.protocolPrefix,
|
|
167
|
+
" "
|
|
168
|
+
] }),
|
|
169
|
+
conversation.protocol
|
|
170
|
+
] }) : null,
|
|
171
|
+
/* @__PURE__ */ jsx2(ParticipantChannelBadges, { channels: conversation.channels, labels, variant: "inline" })
|
|
172
|
+
] }),
|
|
173
|
+
conversation.lastMessagePreview ? /* @__PURE__ */ jsx2("span", { className: "cv-p-row__preview", children: conversation.lastMessagePreview }) : null
|
|
174
|
+
] }),
|
|
175
|
+
/* @__PURE__ */ jsxs2("span", { className: "cv-p-row__meta", children: [
|
|
176
|
+
conversation.lastMessageAt ? /* @__PURE__ */ jsx2("span", { children: formatRowTime(conversation.lastMessageAt, locale) }) : null,
|
|
177
|
+
conversation.unreadCount > 0 ? /* @__PURE__ */ jsxs2("span", { className: "cv-p-row__unread", children: [
|
|
178
|
+
/* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: conversation.unreadCount }),
|
|
179
|
+
/* @__PURE__ */ jsx2("span", { className: "cv-p-sr-only", children: formatParticipantLabel(labels.unreadCount, conversation.unreadCount) })
|
|
180
|
+
] }) : null
|
|
181
|
+
] })
|
|
182
|
+
] });
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// src/participant/ParticipantInboxSearchField.tsx
|
|
186
|
+
import { useId } from "react";
|
|
187
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
188
|
+
function ParticipantInboxSearchField({ search, labels }) {
|
|
189
|
+
const inputId = useId();
|
|
190
|
+
return /* @__PURE__ */ jsxs3("div", { className: "cv-p-search", children: [
|
|
191
|
+
/* @__PURE__ */ jsx3("label", { className: "cv-p-sr-only", htmlFor: inputId, children: labels.searchLabel }),
|
|
192
|
+
/* @__PURE__ */ jsx3(
|
|
193
|
+
"input",
|
|
194
|
+
{
|
|
195
|
+
id: inputId,
|
|
196
|
+
type: "search",
|
|
197
|
+
className: "cv-p-search__input",
|
|
198
|
+
value: search.value,
|
|
199
|
+
placeholder: labels.searchPlaceholder,
|
|
200
|
+
autoComplete: "off",
|
|
201
|
+
onChange: (event) => search.onChange(event.target.value)
|
|
202
|
+
}
|
|
203
|
+
)
|
|
204
|
+
] });
|
|
68
205
|
}
|
|
69
206
|
|
|
70
207
|
// src/participant/ParticipantLoadState.tsx
|
|
71
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
208
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
72
209
|
function ParticipantLoadError({ labels, onRetry }) {
|
|
73
|
-
return /* @__PURE__ */
|
|
74
|
-
/* @__PURE__ */
|
|
75
|
-
/* @__PURE__ */
|
|
210
|
+
return /* @__PURE__ */ jsxs4("div", { className: "cv-p-error", role: "alert", children: [
|
|
211
|
+
/* @__PURE__ */ jsx4("p", { className: "cv-p-error__message", children: labels.loadError }),
|
|
212
|
+
/* @__PURE__ */ jsx4("button", { type: "button", className: "cv-p-button", onClick: onRetry, children: labels.retry })
|
|
76
213
|
] });
|
|
77
214
|
}
|
|
78
215
|
function ParticipantLoading({ labels }) {
|
|
79
|
-
return /* @__PURE__ */
|
|
80
|
-
/* @__PURE__ */
|
|
81
|
-
/* @__PURE__ */
|
|
82
|
-
/* @__PURE__ */
|
|
216
|
+
return /* @__PURE__ */ jsxs4("div", { className: "cv-p-loading", children: [
|
|
217
|
+
/* @__PURE__ */ jsx4("span", { className: "cv-p-skeleton", "aria-hidden": "true" }),
|
|
218
|
+
/* @__PURE__ */ jsx4("span", { className: "cv-p-skeleton", "aria-hidden": "true" }),
|
|
219
|
+
/* @__PURE__ */ jsx4("span", { className: "cv-p-sr-only", children: labels.loading })
|
|
83
220
|
] });
|
|
84
221
|
}
|
|
85
222
|
|
|
86
223
|
// src/participant/ParticipantInbox.tsx
|
|
87
|
-
import { Fragment, jsx as
|
|
224
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
88
225
|
var ALL_FILTER = "all";
|
|
89
|
-
function
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return date.toLocaleDateString(locale, { day: "2-digit", month: "2-digit" });
|
|
226
|
+
function resolveNoResultsLabel({ view, hasMore, labels }) {
|
|
227
|
+
if (view.hasMatchesOutsideFilter) return labels.noResultsInFilter;
|
|
228
|
+
return hasMore ? labels.noResultsLoadedOnly : labels.noResults;
|
|
93
229
|
}
|
|
94
230
|
function sectionTitle(section, props) {
|
|
95
231
|
if (section.key === "awaiting") return props.labels.sectionAwaiting;
|
|
@@ -98,7 +234,7 @@ function sectionTitle(section, props) {
|
|
|
98
234
|
return props.subjectGroups.find((group) => group.subjectType === section.key)?.label ?? section.key;
|
|
99
235
|
}
|
|
100
236
|
function Filters({ filters, active, labels, onChange }) {
|
|
101
|
-
return /* @__PURE__ */
|
|
237
|
+
return /* @__PURE__ */ jsx5("div", { className: "cv-p-filters", role: "group", "aria-label": labels.filtersGroup, children: filters.map((filter) => /* @__PURE__ */ jsxs5(
|
|
102
238
|
"button",
|
|
103
239
|
{
|
|
104
240
|
type: "button",
|
|
@@ -107,79 +243,68 @@ function Filters({ filters, active, labels, onChange }) {
|
|
|
107
243
|
onClick: () => onChange(filter.subjectType),
|
|
108
244
|
children: [
|
|
109
245
|
filter.subjectType === ALL_FILTER ? labels.filterAll : filter.label,
|
|
110
|
-
filter.unreadCount > 0 ? /* @__PURE__ */
|
|
246
|
+
filter.unreadCount > 0 ? /* @__PURE__ */ jsx5("b", { className: "cv-p-chip__count", children: filter.unreadCount }) : null
|
|
111
247
|
]
|
|
112
248
|
},
|
|
113
249
|
filter.subjectType
|
|
114
250
|
)) });
|
|
115
251
|
}
|
|
116
|
-
function Row({ conversation, group, labels, locale, onSelect }) {
|
|
117
|
-
const kind = group?.label ?? conversation.subjectType;
|
|
118
|
-
const className = conversation.awaitingParticipant ? "cv-p-row cv-p-row--awaiting" : "cv-p-row";
|
|
119
|
-
const { subjectType, subjectId } = conversation;
|
|
120
|
-
return /* @__PURE__ */ jsxs2("button", { type: "button", className, onClick: () => onSelect({ subjectType, subjectId }), children: [
|
|
121
|
-
/* @__PURE__ */ jsx2("span", { className: "cv-p-row__icon", "aria-hidden": "true", children: group?.icon ?? kind.slice(0, 2) }),
|
|
122
|
-
/* @__PURE__ */ jsxs2("span", { className: "cv-p-row__body", children: [
|
|
123
|
-
/* @__PURE__ */ jsx2("span", { className: "cv-p-row__kind", children: kind }),
|
|
124
|
-
/* @__PURE__ */ jsx2("span", { className: "cv-p-row__title", children: conversation.subjectLabel }),
|
|
125
|
-
conversation.lastMessagePreview ? /* @__PURE__ */ jsx2("span", { className: "cv-p-row__preview", children: conversation.lastMessagePreview }) : null
|
|
126
|
-
] }),
|
|
127
|
-
/* @__PURE__ */ jsxs2("span", { className: "cv-p-row__meta", children: [
|
|
128
|
-
conversation.lastMessageAt ? /* @__PURE__ */ jsx2("span", { children: formatRowTime(conversation.lastMessageAt, locale) }) : null,
|
|
129
|
-
conversation.unreadCount > 0 ? /* @__PURE__ */ jsxs2("span", { className: "cv-p-row__unread", children: [
|
|
130
|
-
/* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: conversation.unreadCount }),
|
|
131
|
-
/* @__PURE__ */ jsx2("span", { className: "cv-p-sr-only", children: formatParticipantLabel(labels.unreadCount, conversation.unreadCount) })
|
|
132
|
-
] }) : null
|
|
133
|
-
] })
|
|
134
|
-
] });
|
|
135
|
-
}
|
|
136
252
|
function SectionHeading({ title, count }) {
|
|
137
|
-
return /* @__PURE__ */
|
|
138
|
-
/* @__PURE__ */
|
|
139
|
-
/* @__PURE__ */
|
|
253
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
254
|
+
/* @__PURE__ */ jsx5("span", { className: "cv-p-section__title", children: title }),
|
|
255
|
+
/* @__PURE__ */ jsx5("span", { className: "cv-p-section__count", children: count })
|
|
140
256
|
] });
|
|
141
257
|
}
|
|
142
|
-
function Section({
|
|
143
|
-
|
|
144
|
-
|
|
258
|
+
function Section({
|
|
259
|
+
section,
|
|
260
|
+
props
|
|
261
|
+
}) {
|
|
262
|
+
const rows = section.conversations.map((conversation) => /* @__PURE__ */ jsx5(
|
|
263
|
+
ParticipantInboxRow,
|
|
145
264
|
{
|
|
146
265
|
conversation,
|
|
147
266
|
group: props.subjectGroups.find((group) => group.subjectType === conversation.subjectType),
|
|
148
267
|
labels: props.labels,
|
|
149
268
|
locale: props.locale,
|
|
150
|
-
onSelect: props.onSelect
|
|
269
|
+
onSelect: props.onSelect,
|
|
270
|
+
renderSubjectIcon: props.renderSubjectIcon
|
|
151
271
|
},
|
|
152
272
|
`${conversation.subjectType}:${conversation.subjectId}`
|
|
153
273
|
));
|
|
154
|
-
const heading = /* @__PURE__ */
|
|
274
|
+
const heading = /* @__PURE__ */ jsx5(SectionHeading, { title: sectionTitle(section, props), count: section.conversations.length });
|
|
155
275
|
if (section.key === "closed") {
|
|
156
|
-
return /* @__PURE__ */
|
|
157
|
-
/* @__PURE__ */
|
|
276
|
+
return /* @__PURE__ */ jsxs5("details", { className: "cv-p-section cv-p-section--closed", children: [
|
|
277
|
+
/* @__PURE__ */ jsx5("summary", { className: "cv-p-section__heading", children: heading }),
|
|
158
278
|
rows
|
|
159
279
|
] });
|
|
160
280
|
}
|
|
161
281
|
const modifier = section.key === "awaiting" ? " cv-p-section--awaiting" : "";
|
|
162
|
-
return /* @__PURE__ */
|
|
163
|
-
/* @__PURE__ */
|
|
282
|
+
return /* @__PURE__ */ jsxs5("section", { className: `cv-p-section${modifier}`, children: [
|
|
283
|
+
/* @__PURE__ */ jsx5("h3", { className: "cv-p-section__heading", children: heading }),
|
|
164
284
|
rows
|
|
165
285
|
] });
|
|
166
286
|
}
|
|
167
287
|
function ParticipantInbox(props) {
|
|
168
288
|
const { view, labels, filter, onFilterChange } = props;
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
289
|
+
const isSearching = (props.search?.value.trim() ?? "") !== "";
|
|
290
|
+
const loadView = resolveLoadView({ status: props.status, hasItems: view.sections.length > 0 || isSearching });
|
|
291
|
+
const hasNoResults = isSearching && view.sections.length === 0 && props.status === "ready";
|
|
292
|
+
const noResultsLabel = resolveNoResultsLabel(props);
|
|
293
|
+
return /* @__PURE__ */ jsxs5("div", { className: "cv-p cv-p-inbox", "aria-busy": loadView.isLoading, children: [
|
|
294
|
+
/* @__PURE__ */ jsx5("h2", { className: "cv-p-inbox__title", children: labels.inboxTitle }),
|
|
295
|
+
view.showFilters ? /* @__PURE__ */ jsx5(Filters, { filters: view.filters, active: view.activeFilter, labels, onChange: onFilterChange }) : null,
|
|
296
|
+
props.search?.isVisible ? /* @__PURE__ */ jsx5(ParticipantInboxSearchField, { search: props.search, labels }) : null,
|
|
297
|
+
loadView.isLoading ? /* @__PURE__ */ jsx5(ParticipantLoading, { labels }) : null,
|
|
298
|
+
loadView.hasError ? /* @__PURE__ */ jsx5(ParticipantLoadError, { labels, onRetry: props.refresh }) : null,
|
|
299
|
+
loadView.isEmpty ? /* @__PURE__ */ jsx5("p", { className: "cv-p-empty", children: labels.emptyInbox }) : null,
|
|
300
|
+
hasNoResults ? /* @__PURE__ */ jsx5("p", { className: "cv-p-empty", children: noResultsLabel }) : null,
|
|
301
|
+
view.sections.map((section) => /* @__PURE__ */ jsx5(Section, { section, props }, section.key)),
|
|
302
|
+
props.hasMore ? /* @__PURE__ */ jsx5("button", { type: "button", className: "cv-p-button cv-p-inbox__more", onClick: props.loadMore, children: labels.loadMore }) : null
|
|
178
303
|
] });
|
|
179
304
|
}
|
|
180
305
|
|
|
181
306
|
// src/participant/ParticipantThreadScreen.tsx
|
|
182
|
-
import { useEffect as
|
|
307
|
+
import { useEffect as useEffect8, useMemo as useMemo3, useState as useState6 } from "react";
|
|
183
308
|
|
|
184
309
|
// src/participant/ParticipantComposer.tsx
|
|
185
310
|
import { useRef, useState } from "react";
|
|
@@ -217,18 +342,18 @@ function applyQuickReply(currentText, replyText) {
|
|
|
217
342
|
}
|
|
218
343
|
|
|
219
344
|
// src/participant/ParticipantComposer.tsx
|
|
220
|
-
import { Fragment as
|
|
345
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
221
346
|
function QuickReplyStrip({ quickReplies, labels, onPick }) {
|
|
222
|
-
return /* @__PURE__ */
|
|
347
|
+
return /* @__PURE__ */ jsx6("div", { className: "cv-p-quick", role: "group", "aria-label": labels.quickRepliesGroup, children: quickReplies.map((quickReply) => /* @__PURE__ */ jsx6("button", { type: "button", className: "cv-p-chip", onClick: () => onPick(quickReply.body), children: quickReply.title }, quickReply.id)) });
|
|
223
348
|
}
|
|
224
349
|
function FileList({ files, labels, onRemove }) {
|
|
225
350
|
if (files.length === 0) return null;
|
|
226
|
-
return /* @__PURE__ */
|
|
227
|
-
/* @__PURE__ */
|
|
228
|
-
/* @__PURE__ */
|
|
229
|
-
/* @__PURE__ */
|
|
230
|
-
/* @__PURE__ */
|
|
231
|
-
/* @__PURE__ */
|
|
351
|
+
return /* @__PURE__ */ jsx6("ul", { className: "cv-p-files", "aria-label": labels.attachmentsList, children: files.map((file, index) => /* @__PURE__ */ jsxs6("li", { className: "cv-p-files__item", children: [
|
|
352
|
+
/* @__PURE__ */ jsx6("span", { className: "cv-p-files__name", children: file.name }),
|
|
353
|
+
/* @__PURE__ */ jsx6("span", { className: "cv-p-files__size", children: formatFileSize(file.size) }),
|
|
354
|
+
/* @__PURE__ */ jsxs6("button", { type: "button", className: "cv-p-files__remove", "aria-label": `${labels.removeAttachment}: ${file.name}`, onClick: () => onRemove(file), children: [
|
|
355
|
+
/* @__PURE__ */ jsx6("span", { "aria-hidden": "true", children: "\xD7" }),
|
|
356
|
+
/* @__PURE__ */ jsx6("span", { className: "cv-p-sr-only", children: labels.removeAttachment })
|
|
232
357
|
] })
|
|
233
358
|
] }, `${file.name}-${file.size}-${index}`)) });
|
|
234
359
|
}
|
|
@@ -237,8 +362,8 @@ function rejectionText(rejection, labels) {
|
|
|
237
362
|
}
|
|
238
363
|
function AttachControl({ labels, disabled, acceptedTypes, onChosen }) {
|
|
239
364
|
const fileInputRef = useRef(null);
|
|
240
|
-
return /* @__PURE__ */
|
|
241
|
-
/* @__PURE__ */
|
|
365
|
+
return /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
366
|
+
/* @__PURE__ */ jsx6(
|
|
242
367
|
"input",
|
|
243
368
|
{
|
|
244
369
|
ref: fileInputRef,
|
|
@@ -250,9 +375,9 @@ function AttachControl({ labels, disabled, acceptedTypes, onChosen }) {
|
|
|
250
375
|
onChange: onChosen
|
|
251
376
|
}
|
|
252
377
|
),
|
|
253
|
-
/* @__PURE__ */
|
|
254
|
-
/* @__PURE__ */
|
|
255
|
-
/* @__PURE__ */
|
|
378
|
+
/* @__PURE__ */ jsxs6("button", { type: "button", className: "cv-p-button", disabled, onClick: () => fileInputRef.current?.click(), children: [
|
|
379
|
+
/* @__PURE__ */ jsx6("span", { "aria-hidden": "true", children: "\uFF0B" }),
|
|
380
|
+
/* @__PURE__ */ jsx6("span", { className: "cv-p-sr-only", children: labels.attach })
|
|
256
381
|
] })
|
|
257
382
|
] });
|
|
258
383
|
}
|
|
@@ -281,13 +406,13 @@ function ParticipantComposer(props) {
|
|
|
281
406
|
event.preventDefault();
|
|
282
407
|
if (canSend) onSend();
|
|
283
408
|
}
|
|
284
|
-
return /* @__PURE__ */
|
|
285
|
-
props.quickReplies && props.quickReplies.length > 0 ? /* @__PURE__ */
|
|
286
|
-
/* @__PURE__ */
|
|
287
|
-
rejection ? /* @__PURE__ */
|
|
288
|
-
/* @__PURE__ */
|
|
289
|
-
channelCapabilityFor(channel).attachments.accepted ? /* @__PURE__ */
|
|
290
|
-
/* @__PURE__ */
|
|
409
|
+
return /* @__PURE__ */ jsxs6("form", { className: "cv-p-composer", onSubmit: handleSubmit, children: [
|
|
410
|
+
props.quickReplies && props.quickReplies.length > 0 ? /* @__PURE__ */ jsx6(QuickReplyStrip, { quickReplies: props.quickReplies, labels, onPick: (body) => onChange(applyQuickReply(value, body)) }) : null,
|
|
411
|
+
/* @__PURE__ */ jsx6(FileList, { files, labels, onRemove: handleRemoveFile }),
|
|
412
|
+
rejection ? /* @__PURE__ */ jsx6("p", { className: "cv-p-composer__error", role: "alert", children: rejectionText(rejection, labels) }) : null,
|
|
413
|
+
/* @__PURE__ */ jsxs6("div", { className: "cv-p-composer__row", children: [
|
|
414
|
+
channelCapabilityFor(channel).attachments.accepted ? /* @__PURE__ */ jsx6(AttachControl, { labels, disabled, acceptedTypes: props.acceptedTypes, onChosen: handleFilesChosen }) : null,
|
|
415
|
+
/* @__PURE__ */ jsx6(
|
|
291
416
|
"textarea",
|
|
292
417
|
{
|
|
293
418
|
className: "cv-p-composer__input",
|
|
@@ -300,9 +425,9 @@ function ParticipantComposer(props) {
|
|
|
300
425
|
onChange: (event) => onChange(event.target.value)
|
|
301
426
|
}
|
|
302
427
|
),
|
|
303
|
-
/* @__PURE__ */
|
|
304
|
-
/* @__PURE__ */
|
|
305
|
-
/* @__PURE__ */
|
|
428
|
+
/* @__PURE__ */ jsxs6("button", { type: "submit", className: "cv-p-button cv-p-button--primary", disabled: !canSend, children: [
|
|
429
|
+
/* @__PURE__ */ jsx6("span", { "aria-hidden": "true", children: "\u27A4" }),
|
|
430
|
+
/* @__PURE__ */ jsx6("span", { className: "cv-p-sr-only", children: labels.send })
|
|
306
431
|
] })
|
|
307
432
|
] })
|
|
308
433
|
] });
|
|
@@ -338,7 +463,7 @@ function isSafeAttachmentUrl(url) {
|
|
|
338
463
|
}
|
|
339
464
|
|
|
340
465
|
// src/participant/ParticipantAttachmentItem.tsx
|
|
341
|
-
import { jsx as
|
|
466
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
342
467
|
function useAttachmentUrl(attachment, resolveAttachmentUrl) {
|
|
343
468
|
const [url, setUrl] = useState2(void 0);
|
|
344
469
|
const disposition = attachment.kind === "document" ? "attachment" : "inline";
|
|
@@ -361,18 +486,18 @@ function useAttachmentUrl(attachment, resolveAttachmentUrl) {
|
|
|
361
486
|
function ParticipantAttachmentItem({ attachment, resolveAttachmentUrl, labels }) {
|
|
362
487
|
const url = useAttachmentUrl(attachment, resolveAttachmentUrl);
|
|
363
488
|
if (attachment.kind === "image") {
|
|
364
|
-
return /* @__PURE__ */
|
|
365
|
-
url ? /* @__PURE__ */
|
|
366
|
-
/* @__PURE__ */
|
|
489
|
+
return /* @__PURE__ */ jsxs7("figure", { className: "cv-p-attachment cv-p-attachment--image", children: [
|
|
490
|
+
url ? /* @__PURE__ */ jsx7("img", { className: "cv-p-attachment__image", src: url, alt: attachment.filename }) : null,
|
|
491
|
+
/* @__PURE__ */ jsx7("figcaption", { className: "cv-p-attachment__name", children: attachment.filename })
|
|
367
492
|
] });
|
|
368
493
|
}
|
|
369
494
|
if (attachment.kind === "audio") {
|
|
370
|
-
return /* @__PURE__ */
|
|
371
|
-
/* @__PURE__ */
|
|
372
|
-
/* @__PURE__ */
|
|
495
|
+
return /* @__PURE__ */ jsxs7("div", { className: "cv-p-attachment cv-p-attachment--audio", children: [
|
|
496
|
+
/* @__PURE__ */ jsx7("span", { className: "cv-p-attachment__name", children: attachment.filename }),
|
|
497
|
+
/* @__PURE__ */ jsx7("audio", { className: "cv-p-attachment__audio", controls: true, preload: "none", src: url })
|
|
373
498
|
] });
|
|
374
499
|
}
|
|
375
|
-
return /* @__PURE__ */
|
|
500
|
+
return /* @__PURE__ */ jsxs7(
|
|
376
501
|
"a",
|
|
377
502
|
{
|
|
378
503
|
className: "cv-p-attachment cv-p-attachment--document",
|
|
@@ -380,8 +505,8 @@ function ParticipantAttachmentItem({ attachment, resolveAttachmentUrl, labels })
|
|
|
380
505
|
download: attachment.filename,
|
|
381
506
|
"aria-label": `${labels.downloadAttachment}: ${attachment.filename}`,
|
|
382
507
|
children: [
|
|
383
|
-
/* @__PURE__ */
|
|
384
|
-
/* @__PURE__ */
|
|
508
|
+
/* @__PURE__ */ jsx7("span", { className: "cv-p-attachment__name", children: attachment.filename }),
|
|
509
|
+
/* @__PURE__ */ jsx7("span", { className: "cv-p-attachment__size", children: formatFileSize(attachment.sizeBytes) })
|
|
385
510
|
]
|
|
386
511
|
}
|
|
387
512
|
);
|
|
@@ -425,7 +550,7 @@ function resolveOwnMessageStatus(params) {
|
|
|
425
550
|
}
|
|
426
551
|
|
|
427
552
|
// src/participant/ParticipantMessageBubble.tsx
|
|
428
|
-
import { jsx as
|
|
553
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
429
554
|
function describeItem(item) {
|
|
430
555
|
if (item.kind === "server") {
|
|
431
556
|
const { message } = item;
|
|
@@ -463,22 +588,22 @@ function OwnStatus({ status, labels, onRetry }) {
|
|
|
463
588
|
const ticksStatus = status === "sending" ? "queued" : status;
|
|
464
589
|
const isVisibleText = status === "sending" || status === "queued" || status === "failed";
|
|
465
590
|
if (status === "failed" && onRetry) {
|
|
466
|
-
return /* @__PURE__ */
|
|
467
|
-
/* @__PURE__ */
|
|
468
|
-
/* @__PURE__ */
|
|
591
|
+
return /* @__PURE__ */ jsxs8("button", { type: "button", className: "cv-p-bubble__retry", onClick: onRetry, children: [
|
|
592
|
+
/* @__PURE__ */ jsx8(StatusTicks, { status: "failed", appearance: "stylesheet" }),
|
|
593
|
+
/* @__PURE__ */ jsx8("span", { children: labels.statusFailed })
|
|
469
594
|
] });
|
|
470
595
|
}
|
|
471
596
|
const text = status === "failed" ? labels.statusFailedShort : statusText(status, labels);
|
|
472
|
-
return /* @__PURE__ */
|
|
473
|
-
/* @__PURE__ */
|
|
474
|
-
/* @__PURE__ */
|
|
597
|
+
return /* @__PURE__ */ jsxs8("span", { className: "cv-p-bubble__status", children: [
|
|
598
|
+
/* @__PURE__ */ jsx8(StatusTicks, { status: ticksStatus, appearance: "stylesheet" }),
|
|
599
|
+
/* @__PURE__ */ jsx8("span", { className: isVisibleText ? "cv-p-bubble__status-text" : "cv-p-sr-only", children: text })
|
|
475
600
|
] });
|
|
476
601
|
}
|
|
477
602
|
function FailedActions({ labels, onDiscard, onEdit }) {
|
|
478
603
|
if (!onDiscard && !onEdit) return null;
|
|
479
|
-
return /* @__PURE__ */
|
|
480
|
-
onEdit ? /* @__PURE__ */
|
|
481
|
-
onDiscard ? /* @__PURE__ */
|
|
604
|
+
return /* @__PURE__ */ jsxs8("span", { className: "cv-p-bubble__actions", children: [
|
|
605
|
+
onEdit ? /* @__PURE__ */ jsx8("button", { type: "button", className: "cv-p-bubble__action", onClick: onEdit, children: labels.edit }) : null,
|
|
606
|
+
onDiscard ? /* @__PURE__ */ jsx8("button", { type: "button", className: "cv-p-bubble__action", onClick: onDiscard, children: labels.discard }) : null
|
|
482
607
|
] });
|
|
483
608
|
}
|
|
484
609
|
function toTextPayload(text, createdAt, isMine) {
|
|
@@ -503,10 +628,10 @@ function ParticipantMessageBubble({
|
|
|
503
628
|
const content = describeItem(item);
|
|
504
629
|
const { isMine } = content;
|
|
505
630
|
const ownStatus = isMine ? resolveOwnMessageStatus({ displayState: content.displayState, serverStatus: content.serverStatus, confirmsRead }) : void 0;
|
|
506
|
-
return /* @__PURE__ */
|
|
507
|
-
isMine ? /* @__PURE__ */
|
|
508
|
-
content.text ? /* @__PURE__ */
|
|
509
|
-
content.attachments.map((attachment) => /* @__PURE__ */
|
|
631
|
+
return /* @__PURE__ */ jsxs8("div", { className: isMine ? "cv-p-bubble cv-p-bubble--mine" : "cv-p-bubble", children: [
|
|
632
|
+
isMine ? /* @__PURE__ */ jsx8("span", { className: "cv-p-sr-only", children: labels.me }) : content.authorName ? /* @__PURE__ */ jsx8("span", { className: "cv-p-bubble__author", children: content.authorName }) : null,
|
|
633
|
+
content.text ? /* @__PURE__ */ jsx8(MessageText, { message: toTextPayload(content.text, content.createdAt, isMine), copyOnClick: false, appearance: "stylesheet" }) : null,
|
|
634
|
+
content.attachments.map((attachment) => /* @__PURE__ */ jsx8(
|
|
510
635
|
ParticipantAttachmentItem,
|
|
511
636
|
{
|
|
512
637
|
attachment,
|
|
@@ -515,17 +640,90 @@ function ParticipantMessageBubble({
|
|
|
515
640
|
},
|
|
516
641
|
attachment.id
|
|
517
642
|
)),
|
|
518
|
-
content.pendingFilenames.map((filename, index) => /* @__PURE__ */
|
|
519
|
-
/* @__PURE__ */
|
|
520
|
-
/* @__PURE__ */
|
|
521
|
-
ownStatus ? /* @__PURE__ */
|
|
643
|
+
content.pendingFilenames.map((filename, index) => /* @__PURE__ */ jsx8("span", { className: "cv-p-attachment cv-p-attachment--pending", children: filename }, `${filename}-${index}`)),
|
|
644
|
+
/* @__PURE__ */ jsxs8("span", { className: "cv-p-bubble__meta", children: [
|
|
645
|
+
/* @__PURE__ */ jsx8("time", { className: "cv-p-bubble__time", dateTime: content.createdAt, children: formatTimestamp(content.createdAt) }),
|
|
646
|
+
ownStatus ? /* @__PURE__ */ jsx8(OwnStatus, { status: ownStatus, labels, onRetry }) : null
|
|
522
647
|
] }),
|
|
523
|
-
ownStatus === "failed" ? /* @__PURE__ */
|
|
648
|
+
ownStatus === "failed" ? /* @__PURE__ */ jsx8(FailedActions, { labels, onDiscard, onEdit }) : null
|
|
524
649
|
] });
|
|
525
650
|
}
|
|
526
651
|
|
|
652
|
+
// src/participant/ParticipantProtocolBadge.tsx
|
|
653
|
+
import { useEffect as useEffect2, useReducer } from "react";
|
|
654
|
+
|
|
655
|
+
// src/participant/participantProtocolCopy.ts
|
|
656
|
+
async function copyProtocolToClipboard(protocol, clipboard) {
|
|
657
|
+
if (clipboard === void 0) return false;
|
|
658
|
+
try {
|
|
659
|
+
await clipboard.writeText(protocol);
|
|
660
|
+
return true;
|
|
661
|
+
} catch {
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
var INITIAL_PROTOCOL_COPY_STATE = { copyCount: 0, isCopied: false };
|
|
666
|
+
function protocolCopyReducer(state, action) {
|
|
667
|
+
if (action.type === "copied") return { copyCount: state.copyCount + 1, isCopied: true };
|
|
668
|
+
return { ...state, isCopied: false };
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// src/participant/ParticipantProtocolBadge.tsx
|
|
672
|
+
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
673
|
+
var COPIED_ANNOUNCEMENT_MS = 3e3;
|
|
674
|
+
function ParticipantProtocolBadgeView({
|
|
675
|
+
protocol,
|
|
676
|
+
labels,
|
|
677
|
+
copyState,
|
|
678
|
+
onCopy
|
|
679
|
+
}) {
|
|
680
|
+
const { isCopied, copyCount } = copyState;
|
|
681
|
+
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
682
|
+
/* @__PURE__ */ jsxs9("div", { className: "cv-p-protocol cv-p-protocol--header", children: [
|
|
683
|
+
/* @__PURE__ */ jsxs9("span", { className: "cv-p-protocol__code", children: [
|
|
684
|
+
/* @__PURE__ */ jsxs9("span", { className: "cv-p-sr-only", children: [
|
|
685
|
+
labels.protocolPrefix,
|
|
686
|
+
" "
|
|
687
|
+
] }),
|
|
688
|
+
protocol
|
|
689
|
+
] }),
|
|
690
|
+
/* @__PURE__ */ jsxs9("button", { type: "button", className: "cv-p-protocol__copy", onClick: onCopy, children: [
|
|
691
|
+
/* @__PURE__ */ jsx9("span", { "aria-hidden": "true", children: isCopied ? labels.protocolCopied : labels.copyProtocol }),
|
|
692
|
+
/* @__PURE__ */ jsxs9("span", { className: "cv-p-sr-only", children: [
|
|
693
|
+
labels.copyProtocol,
|
|
694
|
+
" ",
|
|
695
|
+
protocol
|
|
696
|
+
] })
|
|
697
|
+
] })
|
|
698
|
+
] }),
|
|
699
|
+
/* @__PURE__ */ jsx9("div", { className: "cv-p-sr-only", role: "status", "aria-live": "polite", children: isCopied ? /* @__PURE__ */ jsx9("span", { children: labels.protocolCopied }, copyCount) : null })
|
|
700
|
+
] });
|
|
701
|
+
}
|
|
702
|
+
function ParticipantProtocolBadge({ protocol, labels }) {
|
|
703
|
+
const [copyState, dispatch] = useReducer(protocolCopyReducer, INITIAL_PROTOCOL_COPY_STATE);
|
|
704
|
+
const { isCopied, copyCount } = copyState;
|
|
705
|
+
useEffect2(() => {
|
|
706
|
+
if (!isCopied) return void 0;
|
|
707
|
+
const timer = setTimeout(() => dispatch({ type: "expired" }), COPIED_ANNOUNCEMENT_MS);
|
|
708
|
+
return () => clearTimeout(timer);
|
|
709
|
+
}, [isCopied, copyCount]);
|
|
710
|
+
async function handleCopy() {
|
|
711
|
+
const clipboard = typeof navigator === "undefined" ? void 0 : navigator.clipboard;
|
|
712
|
+
if (await copyProtocolToClipboard(protocol, clipboard)) dispatch({ type: "copied" });
|
|
713
|
+
}
|
|
714
|
+
return /* @__PURE__ */ jsx9(
|
|
715
|
+
ParticipantProtocolBadgeView,
|
|
716
|
+
{
|
|
717
|
+
protocol,
|
|
718
|
+
labels,
|
|
719
|
+
copyState,
|
|
720
|
+
onCopy: () => void handleCopy()
|
|
721
|
+
}
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
|
|
527
725
|
// src/participant/ParticipantThread.tsx
|
|
528
|
-
import { jsx as
|
|
726
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
529
727
|
function createdAtOf2(item) {
|
|
530
728
|
return item.kind === "server" ? item.message.createdAt : item.pending.createdAt;
|
|
531
729
|
}
|
|
@@ -539,21 +737,25 @@ function resolveActions(item, pendingActions) {
|
|
|
539
737
|
function Header({ props }) {
|
|
540
738
|
const { conversation, labels, onBack, onOpenSubject } = props;
|
|
541
739
|
const { subjectType, subjectId } = conversation;
|
|
542
|
-
return /* @__PURE__ */
|
|
543
|
-
onBack ? /* @__PURE__ */
|
|
544
|
-
/* @__PURE__ */
|
|
545
|
-
/* @__PURE__ */
|
|
740
|
+
return /* @__PURE__ */ jsxs10("header", { className: "cv-p-thread__header", children: [
|
|
741
|
+
onBack ? /* @__PURE__ */ jsxs10("button", { type: "button", className: "cv-p-button cv-p-thread__back", onClick: onBack, children: [
|
|
742
|
+
/* @__PURE__ */ jsx10("span", { "aria-hidden": "true", children: "\u2039" }),
|
|
743
|
+
/* @__PURE__ */ jsx10("span", { className: "cv-p-sr-only", children: labels.back })
|
|
546
744
|
] }) : null,
|
|
547
|
-
/* @__PURE__ */
|
|
548
|
-
"
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
745
|
+
/* @__PURE__ */ jsxs10("div", { className: "cv-p-thread__heading", children: [
|
|
746
|
+
/* @__PURE__ */ jsx10("h2", { className: "cv-p-thread__title", children: onOpenSubject ? /* @__PURE__ */ jsx10(
|
|
747
|
+
"button",
|
|
748
|
+
{
|
|
749
|
+
type: "button",
|
|
750
|
+
className: "cv-p-thread__title-button",
|
|
751
|
+
"aria-label": `${labels.openSubject}: ${conversation.subjectLabel}`,
|
|
752
|
+
onClick: () => onOpenSubject({ subjectType, subjectId }),
|
|
753
|
+
children: conversation.subjectLabel
|
|
754
|
+
}
|
|
755
|
+
) : conversation.subjectLabel }),
|
|
756
|
+
conversation.protocol ? /* @__PURE__ */ jsx10(ParticipantProtocolBadge, { protocol: conversation.protocol, labels }) : null,
|
|
757
|
+
/* @__PURE__ */ jsx10(ParticipantChannelBadges, { channels: conversation.channels, labels })
|
|
758
|
+
] })
|
|
557
759
|
] });
|
|
558
760
|
}
|
|
559
761
|
function Timeline({ props }) {
|
|
@@ -565,12 +767,12 @@ function Timeline({ props }) {
|
|
|
565
767
|
const day = new Date(createdAtOf2(item));
|
|
566
768
|
if (previousDay === void 0 || !isSameDay(previousDay, day)) {
|
|
567
769
|
nodes.push(
|
|
568
|
-
/* @__PURE__ */
|
|
770
|
+
/* @__PURE__ */ jsx10("div", { className: "cv-p-day", role: "separator", children: day.toLocaleDateString(locale, { weekday: "short", day: "2-digit", month: "2-digit" }) }, `day:${keyOf(item)}`)
|
|
569
771
|
);
|
|
570
772
|
}
|
|
571
773
|
previousDay = day;
|
|
572
774
|
nodes.push(
|
|
573
|
-
/* @__PURE__ */
|
|
775
|
+
/* @__PURE__ */ jsx10(
|
|
574
776
|
ParticipantMessageBubble,
|
|
575
777
|
{
|
|
576
778
|
item,
|
|
@@ -583,14 +785,14 @@ function Timeline({ props }) {
|
|
|
583
785
|
)
|
|
584
786
|
);
|
|
585
787
|
}
|
|
586
|
-
return /* @__PURE__ */
|
|
788
|
+
return /* @__PURE__ */ jsx10("div", { className: "cv-p-thread__messages", children: nodes });
|
|
587
789
|
}
|
|
588
790
|
function Footer({ props }) {
|
|
589
791
|
const { conversation, labels, draft } = props;
|
|
590
792
|
if (conversation.status === "closed") {
|
|
591
|
-
return /* @__PURE__ */
|
|
793
|
+
return /* @__PURE__ */ jsx10("p", { className: "cv-p-thread__closed", children: labels.closedNotice });
|
|
592
794
|
}
|
|
593
|
-
return /* @__PURE__ */
|
|
795
|
+
return /* @__PURE__ */ jsx10(
|
|
594
796
|
ParticipantComposer,
|
|
595
797
|
{
|
|
596
798
|
value: draft.value,
|
|
@@ -611,17 +813,17 @@ function ParticipantThread(props) {
|
|
|
611
813
|
const { conversation, labels, hasMore, onLoadOlder, renderSubjectCard } = props;
|
|
612
814
|
const subjectCard = renderSubjectCard?.(conversation);
|
|
613
815
|
const loadView = resolveLoadView({ status: props.status, hasItems: props.items.length > 0 });
|
|
614
|
-
return /* @__PURE__ */
|
|
615
|
-
/* @__PURE__ */
|
|
616
|
-
subjectCard ? /* @__PURE__ */
|
|
617
|
-
/* @__PURE__ */
|
|
618
|
-
loadView.isLoading ? /* @__PURE__ */
|
|
619
|
-
loadView.hasError ? /* @__PURE__ */
|
|
620
|
-
hasMore && onLoadOlder ? /* @__PURE__ */
|
|
621
|
-
/* @__PURE__ */
|
|
816
|
+
return /* @__PURE__ */ jsxs10("div", { className: "cv-p cv-p-thread", "aria-busy": loadView.isLoading, children: [
|
|
817
|
+
/* @__PURE__ */ jsx10(Header, { props }),
|
|
818
|
+
subjectCard ? /* @__PURE__ */ jsx10("div", { className: "cv-p-thread__subject-card", children: subjectCard }) : null,
|
|
819
|
+
/* @__PURE__ */ jsxs10("div", { className: "cv-p-thread__scroll", ref: props.scroll.ref, onScroll: props.scroll.onScroll, children: [
|
|
820
|
+
loadView.isLoading ? /* @__PURE__ */ jsx10(ParticipantLoading, { labels }) : null,
|
|
821
|
+
loadView.hasError ? /* @__PURE__ */ jsx10(ParticipantLoadError, { labels, onRetry: props.refresh }) : null,
|
|
822
|
+
hasMore && onLoadOlder ? /* @__PURE__ */ jsx10("button", { type: "button", className: "cv-p-thread__older", onClick: onLoadOlder, children: labels.loadOlder }) : null,
|
|
823
|
+
/* @__PURE__ */ jsx10(Timeline, { props })
|
|
622
824
|
] }),
|
|
623
|
-
/* @__PURE__ */
|
|
624
|
-
/* @__PURE__ */
|
|
825
|
+
/* @__PURE__ */ jsx10("div", { className: "cv-p-thread__live", role: "status", "aria-live": "polite", children: props.newMessagesCount > 0 ? labels.newMessages : "" }),
|
|
826
|
+
/* @__PURE__ */ jsx10(Footer, { props })
|
|
625
827
|
] });
|
|
626
828
|
}
|
|
627
829
|
|
|
@@ -775,7 +977,7 @@ function participantSendStatesReducer(states, { subject, action }) {
|
|
|
775
977
|
}
|
|
776
978
|
|
|
777
979
|
// src/participant/useParticipantThread.ts
|
|
778
|
-
import { useCallback as useCallback2, useEffect as
|
|
980
|
+
import { useCallback as useCallback2, useEffect as useEffect6, useMemo, useReducer as useReducer2, useRef as useRef4 } from "react";
|
|
779
981
|
|
|
780
982
|
// src/participant/participantThreadState.ts
|
|
781
983
|
var INITIAL_PARTICIPANT_THREAD_STATE = {
|
|
@@ -811,7 +1013,7 @@ function participantThreadReducer(state, action) {
|
|
|
811
1013
|
}
|
|
812
1014
|
|
|
813
1015
|
// src/participant/useParticipantMarkRead.ts
|
|
814
|
-
import { useEffect as
|
|
1016
|
+
import { useEffect as useEffect4 } from "react";
|
|
815
1017
|
|
|
816
1018
|
// src/participant/shouldMarkRead.ts
|
|
817
1019
|
function shouldMarkParticipantRead(params) {
|
|
@@ -823,12 +1025,12 @@ function shouldMarkParticipantRead(params) {
|
|
|
823
1025
|
}
|
|
824
1026
|
|
|
825
1027
|
// src/participant/useDocumentVisibility.ts
|
|
826
|
-
import { useEffect as
|
|
1028
|
+
import { useEffect as useEffect3, useState as useState4 } from "react";
|
|
827
1029
|
function useDocumentVisibility() {
|
|
828
1030
|
const [visibilityState, setVisibilityState] = useState4(
|
|
829
1031
|
() => typeof document === "undefined" ? "visible" : document.visibilityState
|
|
830
1032
|
);
|
|
831
|
-
|
|
1033
|
+
useEffect3(() => {
|
|
832
1034
|
function handleVisibilityChange() {
|
|
833
1035
|
setVisibilityState(document.visibilityState);
|
|
834
1036
|
}
|
|
@@ -843,18 +1045,18 @@ function useDocumentVisibility() {
|
|
|
843
1045
|
function useParticipantMarkRead(params) {
|
|
844
1046
|
const { apiRef, subject, unreadCount, messageCount, onMarkedRead } = params;
|
|
845
1047
|
const visibilityState = useDocumentVisibility();
|
|
846
|
-
|
|
1048
|
+
useEffect4(() => {
|
|
847
1049
|
if (!shouldMarkParticipantRead({ selected: subject, subject, visibilityState, unreadCount })) return;
|
|
848
1050
|
void apiRef.current.markRead(subject).then(() => onMarkedRead?.(subject), () => void 0);
|
|
849
1051
|
}, [apiRef, subject, visibilityState, unreadCount, messageCount, onMarkedRead]);
|
|
850
1052
|
}
|
|
851
1053
|
|
|
852
1054
|
// src/participant/useParticipantRevalidation.ts
|
|
853
|
-
import { useEffect as
|
|
1055
|
+
import { useEffect as useEffect5, useRef as useRef2 } from "react";
|
|
854
1056
|
function useParticipantRevalidation(api, onRevalidate) {
|
|
855
1057
|
const handlerRef = useRef2(onRevalidate);
|
|
856
1058
|
handlerRef.current = onRevalidate;
|
|
857
|
-
|
|
1059
|
+
useEffect5(() => {
|
|
858
1060
|
function handleFocus() {
|
|
859
1061
|
handlerRef.current();
|
|
860
1062
|
}
|
|
@@ -948,7 +1150,7 @@ function useParticipantThread(params) {
|
|
|
948
1150
|
const { api, subject, channel, unreadCount = 0, onMarkedRead, sendEntries, dispatchSend, hostPending = [] } = params;
|
|
949
1151
|
const { subjectType, subjectId } = subject;
|
|
950
1152
|
const stableSubject = useMemo(() => ({ subjectType, subjectId }), [subjectType, subjectId]);
|
|
951
|
-
const [state, dispatch] =
|
|
1153
|
+
const [state, dispatch] = useReducer2(participantThreadReducer, INITIAL_PARTICIPANT_THREAD_STATE);
|
|
952
1154
|
const apiRef = useRef4(api);
|
|
953
1155
|
apiRef.current = api;
|
|
954
1156
|
const activeSubjectKey = useRef4("");
|
|
@@ -980,7 +1182,7 @@ function useParticipantThread(params) {
|
|
|
980
1182
|
}, [stableSubject, subjectType, subjectId, oldestMessageId]);
|
|
981
1183
|
const handleSentMessage = useCallback2((message) => dispatch({ type: "sendConfirmed", message }), []);
|
|
982
1184
|
const sending = useParticipantSend({ apiRef, subject: stableSubject, entries: sendEntries, dispatchSend, onSentMessage: handleSentMessage });
|
|
983
|
-
|
|
1185
|
+
useEffect6(() => {
|
|
984
1186
|
activeSubjectKey.current = `${subjectType}:${subjectId}`;
|
|
985
1187
|
dispatch({ type: "reset" });
|
|
986
1188
|
void refresh();
|
|
@@ -988,7 +1190,7 @@ function useParticipantThread(params) {
|
|
|
988
1190
|
useParticipantRevalidation(api, (event) => {
|
|
989
1191
|
if (isForSubject(event, stableSubject)) void refresh();
|
|
990
1192
|
});
|
|
991
|
-
|
|
1193
|
+
useEffect6(() => {
|
|
992
1194
|
if (sendEntries.length === 0) return;
|
|
993
1195
|
dispatchSend({ type: "reflected", knownClientMessageIds: collectKnownClientMessageIds({ messages: state.messages, hostPending }) });
|
|
994
1196
|
}, [sendEntries, state.messages, hostPending, dispatchSend]);
|
|
@@ -1029,7 +1231,7 @@ function useParticipantConversationView(params) {
|
|
|
1029
1231
|
}
|
|
1030
1232
|
|
|
1031
1233
|
// src/participant/useParticipantThreadScroll.ts
|
|
1032
|
-
import { useEffect as
|
|
1234
|
+
import { useEffect as useEffect7, useRef as useRef6 } from "react";
|
|
1033
1235
|
|
|
1034
1236
|
// src/participant/participantNewMessages.ts
|
|
1035
1237
|
function collectServerMessageIds(items) {
|
|
@@ -1131,19 +1333,19 @@ function keyOf2(item) {
|
|
|
1131
1333
|
function useParticipantThreadScroll(items) {
|
|
1132
1334
|
const { scroll, isNearBottom } = useStickToBottom({ firstKey: keyOf2(items[0]), lastKey: keyOf2(items[items.length - 1]) });
|
|
1133
1335
|
const seenIds = useRef6(/* @__PURE__ */ new Set());
|
|
1134
|
-
|
|
1336
|
+
useEffect7(() => {
|
|
1135
1337
|
if (isNearBottom) seenIds.current = collectServerMessageIds(items);
|
|
1136
1338
|
}, [isNearBottom, items]);
|
|
1137
1339
|
return { scroll, newMessagesCount: isNearBottom ? 0 : countNewIncomingMessages(seenIds.current, items) };
|
|
1138
1340
|
}
|
|
1139
1341
|
|
|
1140
1342
|
// src/participant/ParticipantThreadScreen.tsx
|
|
1141
|
-
import { jsx as
|
|
1343
|
+
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1142
1344
|
function useOpenedConversation(api, subject, isNeeded) {
|
|
1143
1345
|
const [opened, setOpened] = useState6({ status: "idle" });
|
|
1144
1346
|
const { subjectType, subjectId } = subject;
|
|
1145
1347
|
const canOpen = api.openConversation !== void 0;
|
|
1146
|
-
|
|
1348
|
+
useEffect8(() => {
|
|
1147
1349
|
if (!isNeeded || !canOpen) return;
|
|
1148
1350
|
let isCurrent = true;
|
|
1149
1351
|
setOpened({ status: "loading" });
|
|
@@ -1158,12 +1360,12 @@ function useOpenedConversation(api, subject, isNeeded) {
|
|
|
1158
1360
|
return opened;
|
|
1159
1361
|
}
|
|
1160
1362
|
function NotFound({ labels, onBack }) {
|
|
1161
|
-
return /* @__PURE__ */
|
|
1162
|
-
/* @__PURE__ */
|
|
1163
|
-
/* @__PURE__ */
|
|
1164
|
-
/* @__PURE__ */
|
|
1363
|
+
return /* @__PURE__ */ jsxs11("div", { className: "cv-p cv-p-thread", children: [
|
|
1364
|
+
/* @__PURE__ */ jsx11("header", { className: "cv-p-thread__header", children: onBack ? /* @__PURE__ */ jsxs11("button", { type: "button", className: "cv-p-button cv-p-thread__back", onClick: onBack, children: [
|
|
1365
|
+
/* @__PURE__ */ jsx11("span", { "aria-hidden": "true", children: "\u2039" }),
|
|
1366
|
+
/* @__PURE__ */ jsx11("span", { className: "cv-p-sr-only", children: labels.back })
|
|
1165
1367
|
] }) : null }),
|
|
1166
|
-
/* @__PURE__ */
|
|
1368
|
+
/* @__PURE__ */ jsx11("p", { className: "cv-p-empty", children: labels.notFound })
|
|
1167
1369
|
] });
|
|
1168
1370
|
}
|
|
1169
1371
|
function ParticipantThreadScreen(props) {
|
|
@@ -1173,11 +1375,11 @@ function ParticipantThreadScreen(props) {
|
|
|
1173
1375
|
);
|
|
1174
1376
|
const opened = useOpenedConversation(api, selected, listed === void 0);
|
|
1175
1377
|
const conversation = listed ?? (opened.status === "found" ? opened.conversation : void 0);
|
|
1176
|
-
if (conversation) return /* @__PURE__ */
|
|
1378
|
+
if (conversation) return /* @__PURE__ */ jsx11(LoadedThread, { ...props, conversation });
|
|
1177
1379
|
const isResolving = opened.status === "loading" || api.openConversation !== void 0 && opened.status === "idle";
|
|
1178
1380
|
const isListLoading = inbox.status === "idle" || inbox.status === "loading";
|
|
1179
|
-
if (isResolving || api.openConversation === void 0 && isListLoading) return /* @__PURE__ */
|
|
1180
|
-
return /* @__PURE__ */
|
|
1381
|
+
if (isResolving || api.openConversation === void 0 && isListLoading) return /* @__PURE__ */ jsx11("div", { className: "cv-p cv-p-thread", "aria-busy": "true" });
|
|
1382
|
+
return /* @__PURE__ */ jsx11(NotFound, { labels, onBack: props.onBack });
|
|
1181
1383
|
}
|
|
1182
1384
|
function LoadedThread(props) {
|
|
1183
1385
|
const { api, selected, conversation, draftsRef, inbox } = props;
|
|
@@ -1199,7 +1401,7 @@ function LoadedThread(props) {
|
|
|
1199
1401
|
restoreFromEntry(entry);
|
|
1200
1402
|
dispatchSend({ type: "discarded", clientMessageId });
|
|
1201
1403
|
}
|
|
1202
|
-
return /* @__PURE__ */
|
|
1404
|
+
return /* @__PURE__ */ jsx11(
|
|
1203
1405
|
ParticipantThread,
|
|
1204
1406
|
{
|
|
1205
1407
|
conversation,
|
|
@@ -1231,6 +1433,39 @@ function LoadedThread(props) {
|
|
|
1231
1433
|
);
|
|
1232
1434
|
}
|
|
1233
1435
|
|
|
1436
|
+
// src/participant/participantProtocol.ts
|
|
1437
|
+
var PROTOCOL_SEARCH_CONVERSATION_THRESHOLD = 8;
|
|
1438
|
+
function normalizeProtocolQuery(text) {
|
|
1439
|
+
return text.replace(/[-\s]/g, "").toUpperCase();
|
|
1440
|
+
}
|
|
1441
|
+
function matchesProtocolQuery(protocol, query) {
|
|
1442
|
+
const normalizedQuery = normalizeProtocolQuery(query);
|
|
1443
|
+
if (normalizedQuery === "") return true;
|
|
1444
|
+
if (protocol === void 0) return false;
|
|
1445
|
+
return normalizeProtocolQuery(protocol).includes(normalizedQuery);
|
|
1446
|
+
}
|
|
1447
|
+
function foldText(text) {
|
|
1448
|
+
return text.normalize("NFD").replace(/\p{M}/gu, "").toLowerCase();
|
|
1449
|
+
}
|
|
1450
|
+
function matchesTitle(subjectLabel, query) {
|
|
1451
|
+
return foldText(subjectLabel).includes(foldText(query));
|
|
1452
|
+
}
|
|
1453
|
+
function filterConversationsBySearch(conversations, query) {
|
|
1454
|
+
const trimmedQuery = query.trim();
|
|
1455
|
+
if (trimmedQuery === "") return conversations;
|
|
1456
|
+
const hasProtocolTerm = normalizeProtocolQuery(trimmedQuery) !== "";
|
|
1457
|
+
return conversations.filter(
|
|
1458
|
+
(conversation) => matchesTitle(conversation.subjectLabel, trimmedQuery) || hasProtocolTerm && matchesProtocolQuery(conversation.protocol, trimmedQuery)
|
|
1459
|
+
);
|
|
1460
|
+
}
|
|
1461
|
+
function isInboxSearchVisible({ conversations, searchQuery }) {
|
|
1462
|
+
return searchQuery !== "" || shouldShowInboxSearch(conversations);
|
|
1463
|
+
}
|
|
1464
|
+
function shouldShowInboxSearch(conversations) {
|
|
1465
|
+
if (conversations.length > PROTOCOL_SEARCH_CONVERSATION_THRESHOLD) return true;
|
|
1466
|
+
return conversations.some((conversation) => conversation.protocol !== void 0);
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1234
1469
|
// src/participant/participantGrouping.ts
|
|
1235
1470
|
var ALL_FILTER2 = "all";
|
|
1236
1471
|
var SECTION_AWAITING = "awaiting";
|
|
@@ -1270,22 +1505,35 @@ function buildFilters(params) {
|
|
|
1270
1505
|
};
|
|
1271
1506
|
return { filters: [all, ...groupFilters], showFilters: groupFilters.length >= 2 };
|
|
1272
1507
|
}
|
|
1508
|
+
function resolveActiveFilter(params) {
|
|
1509
|
+
const { filter, conversations } = params;
|
|
1510
|
+
if (filter === void 0 || filter === ALL_FILTER2) return ALL_FILTER2;
|
|
1511
|
+
return conversations.some((conversation) => conversation.subjectType === filter) ? filter : ALL_FILTER2;
|
|
1512
|
+
}
|
|
1273
1513
|
function groupParticipantConversations(params) {
|
|
1274
|
-
const {
|
|
1275
|
-
const
|
|
1276
|
-
const
|
|
1514
|
+
const { subjectGroups } = params;
|
|
1515
|
+
const filter = resolveActiveFilter(params);
|
|
1516
|
+
const isFiltered = filter !== ALL_FILTER2;
|
|
1517
|
+
const searched = filterConversationsBySearch(params.conversations, params.searchQuery ?? "");
|
|
1518
|
+
const visible = isFiltered ? searched.filter((conversation) => conversation.subjectType === filter) : searched;
|
|
1277
1519
|
const knownTypes = new Set(subjectGroups.map((group) => group.subjectType));
|
|
1278
1520
|
const buckets = /* @__PURE__ */ new Map();
|
|
1279
1521
|
for (const conversation of visible) {
|
|
1280
1522
|
const key = resolveSectionKey(conversation, knownTypes);
|
|
1281
1523
|
buckets.set(key, [...buckets.get(key) ?? [], conversation]);
|
|
1282
1524
|
}
|
|
1283
|
-
const orderedKeys = [
|
|
1525
|
+
const orderedKeys = [
|
|
1526
|
+
SECTION_AWAITING,
|
|
1527
|
+
...subjectGroups.map((group) => group.subjectType),
|
|
1528
|
+
SECTION_OTHER,
|
|
1529
|
+
SECTION_CLOSED
|
|
1530
|
+
];
|
|
1284
1531
|
const sections = orderedKeys.flatMap((key) => {
|
|
1285
1532
|
const bucket = buckets.get(key);
|
|
1286
1533
|
return bucket === void 0 ? [] : [buildSection(key, bucket)];
|
|
1287
1534
|
});
|
|
1288
|
-
|
|
1535
|
+
const hasMatchesOutsideFilter = isFiltered && visible.length === 0 && searched.length > 0;
|
|
1536
|
+
return { sections, hasMatchesOutsideFilter, activeFilter: filter, ...buildFilters(params) };
|
|
1289
1537
|
}
|
|
1290
1538
|
|
|
1291
1539
|
// src/participant/participantTheme.ts
|
|
@@ -1306,23 +1554,27 @@ function buildParticipantThemeStyle(theme) {
|
|
|
1306
1554
|
}
|
|
1307
1555
|
|
|
1308
1556
|
// src/participant/ParticipantConversationsScreen.tsx
|
|
1309
|
-
import { jsx as
|
|
1557
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1310
1558
|
var ALL_FILTER3 = "all";
|
|
1311
1559
|
function ParticipantConversationsScreen(props) {
|
|
1312
1560
|
const { selected, inbox, subjectGroups, classNames } = props;
|
|
1313
1561
|
const [filter, setFilter] = useState7(ALL_FILTER3);
|
|
1562
|
+
const [searchQuery, setSearchQuery] = useState7("");
|
|
1314
1563
|
const draftsRef = useRef7(/* @__PURE__ */ new Map());
|
|
1315
|
-
const [sendStates, dispatchSendStates] =
|
|
1316
|
-
const labels = useMemo4(
|
|
1317
|
-
() => ({ ...DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS, ...props.labels }),
|
|
1318
|
-
[props.labels]
|
|
1319
|
-
);
|
|
1564
|
+
const [sendStates, dispatchSendStates] = useReducer3(participantSendStatesReducer, /* @__PURE__ */ new Map());
|
|
1565
|
+
const labels = useMemo4(() => ({ ...DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS, ...props.labels }), [props.labels]);
|
|
1320
1566
|
const view = useMemo4(
|
|
1321
|
-
() => groupParticipantConversations({
|
|
1322
|
-
|
|
1567
|
+
() => groupParticipantConversations({
|
|
1568
|
+
conversations: inbox.conversations,
|
|
1569
|
+
subjectGroups,
|
|
1570
|
+
filter,
|
|
1571
|
+
searchQuery
|
|
1572
|
+
}),
|
|
1573
|
+
[inbox.conversations, subjectGroups, filter, searchQuery]
|
|
1323
1574
|
);
|
|
1575
|
+
const isSearchVisible = isInboxSearchVisible({ conversations: inbox.conversations, searchQuery });
|
|
1324
1576
|
const rootClassName = ["cv-p-root", props.className, classNames?.root].filter(Boolean).join(" ");
|
|
1325
|
-
return /* @__PURE__ */
|
|
1577
|
+
return /* @__PURE__ */ jsx12("div", { className: rootClassName, style: buildParticipantThemeStyle(props.theme), children: selected === void 0 ? /* @__PURE__ */ jsx12("div", { className: ["cv-p-root__screen", classNames?.inbox].filter(Boolean).join(" "), children: /* @__PURE__ */ jsx12(
|
|
1326
1578
|
ParticipantInbox,
|
|
1327
1579
|
{
|
|
1328
1580
|
view,
|
|
@@ -1335,9 +1587,11 @@ function ParticipantConversationsScreen(props) {
|
|
|
1335
1587
|
refresh: () => void inbox.refresh(),
|
|
1336
1588
|
hasMore: inbox.hasMore,
|
|
1337
1589
|
loadMore: () => void inbox.loadMore(),
|
|
1338
|
-
locale: props.locale
|
|
1590
|
+
locale: props.locale,
|
|
1591
|
+
renderSubjectIcon: props.renderSubjectIcon,
|
|
1592
|
+
search: { value: searchQuery, onChange: setSearchQuery, isVisible: isSearchVisible }
|
|
1339
1593
|
}
|
|
1340
|
-
) }) : /* @__PURE__ */
|
|
1594
|
+
) }) : /* @__PURE__ */ jsx12("div", { className: ["cv-p-root__screen", classNames?.thread].filter(Boolean).join(" "), children: /* @__PURE__ */ jsx12(
|
|
1341
1595
|
ParticipantThreadScreen,
|
|
1342
1596
|
{
|
|
1343
1597
|
...props,
|
|
@@ -1352,7 +1606,7 @@ function ParticipantConversationsScreen(props) {
|
|
|
1352
1606
|
}
|
|
1353
1607
|
|
|
1354
1608
|
// src/participant/useParticipantInbox.ts
|
|
1355
|
-
import { useCallback as useCallback5, useEffect as
|
|
1609
|
+
import { useCallback as useCallback5, useEffect as useEffect9, useReducer as useReducer4 } from "react";
|
|
1356
1610
|
|
|
1357
1611
|
// src/participant/participantInboxState.ts
|
|
1358
1612
|
var INITIAL_PARTICIPANT_INBOX_STATE = { status: "idle", conversations: [] };
|
|
@@ -1402,7 +1656,7 @@ function describeError2(error) {
|
|
|
1402
1656
|
return error instanceof Error ? error.message : "unknown error";
|
|
1403
1657
|
}
|
|
1404
1658
|
function useParticipantInbox(api) {
|
|
1405
|
-
const [state, dispatch] =
|
|
1659
|
+
const [state, dispatch] = useReducer4(participantInboxReducer, INITIAL_PARTICIPANT_INBOX_STATE);
|
|
1406
1660
|
const refresh = useCallback5(async () => {
|
|
1407
1661
|
dispatch({ type: "started" });
|
|
1408
1662
|
try {
|
|
@@ -1425,7 +1679,7 @@ function useParticipantInbox(api) {
|
|
|
1425
1679
|
const markSubjectRead = useCallback5((subject) => {
|
|
1426
1680
|
dispatch({ type: "markedRead", subject });
|
|
1427
1681
|
}, []);
|
|
1428
|
-
|
|
1682
|
+
useEffect9(() => {
|
|
1429
1683
|
void refresh();
|
|
1430
1684
|
}, [refresh]);
|
|
1431
1685
|
useParticipantRevalidation(api, () => {
|
|
@@ -1435,11 +1689,17 @@ function useParticipantInbox(api) {
|
|
|
1435
1689
|
}
|
|
1436
1690
|
|
|
1437
1691
|
// src/participant/ParticipantConversations.tsx
|
|
1438
|
-
import { jsx as
|
|
1692
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1439
1693
|
function ParticipantConversations(props) {
|
|
1440
1694
|
const inbox = useParticipantInbox(props.api);
|
|
1441
1695
|
const { status, conversations, hasMore, refresh, loadMore, markSubjectRead } = inbox;
|
|
1442
|
-
return /* @__PURE__ */
|
|
1696
|
+
return /* @__PURE__ */ jsx13(
|
|
1697
|
+
ParticipantConversationsScreen,
|
|
1698
|
+
{
|
|
1699
|
+
...props,
|
|
1700
|
+
inbox: { status, conversations, hasMore, refresh, loadMore, markSubjectRead }
|
|
1701
|
+
}
|
|
1702
|
+
);
|
|
1443
1703
|
}
|
|
1444
1704
|
export {
|
|
1445
1705
|
DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS,
|