@anakin824/prdg-chat-ui 0.3.2 → 0.3.4

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/index.mjs CHANGED
@@ -178,10 +178,15 @@ function chatDebugWarn(debug, ...args) {
178
178
  }
179
179
 
180
180
  // src/chat/lib/queryKeys.ts
181
+ function normalizeConversationCacheId(conversationId) {
182
+ if (conversationId == null) return null;
183
+ const t = conversationId.trim();
184
+ return t ? t.toLowerCase() : null;
185
+ }
181
186
  var chatKeys = {
182
187
  all: ["chat"],
183
188
  conversations: () => [...chatKeys.all, "conversations"],
184
- messages: (conversationId) => [...chatKeys.all, "messages", conversationId],
189
+ messages: (conversationId) => [...chatKeys.all, "messages", normalizeConversationCacheId(conversationId)],
185
190
  members: (conversationId) => [...chatKeys.all, "members", conversationId],
186
191
  contacts: (q) => [...chatKeys.all, "contacts", q]
187
192
  };
@@ -248,7 +253,10 @@ function getMessagePageSummary(queryClient, conversationId) {
248
253
  function pushMessageToCache(queryClient, msg) {
249
254
  let result = "missing-cache";
250
255
  queryClient.setQueryData(chatKeys.messages(msg.conversation_id), (prev) => {
251
- if (!prev) return void 0;
256
+ if (!prev) {
257
+ result = "seeded";
258
+ return { items: [msg], next_cursor: "" };
259
+ }
252
260
  if (prev.items.some((m) => m.id === msg.id)) {
253
261
  result = "duplicate";
254
262
  return prev;
@@ -426,11 +434,12 @@ function ChatNatsBridge({ natsWsUrl, natsToken, onConnectedChange }) {
426
434
  const connRef = useRef(null);
427
435
  useEffect(() => {
428
436
  if (servers.length === 0) return;
437
+ const entityConvIds = entityKey ? entityKey.split(",").filter(Boolean) : [];
429
438
  chatDebugLog(debug, "ChatNatsBridge: starting subscriptions", {
430
439
  userId,
431
440
  natsTenantId,
432
441
  servers,
433
- entityConversationIds
442
+ entityConversationIds: entityConvIds
434
443
  });
435
444
  let cancelled = false;
436
445
  void (async () => {
@@ -523,7 +532,7 @@ function ChatNatsBridge({ natsWsUrl, natsToken, onConnectedChange }) {
523
532
  handleMsg(m.data, m.subject);
524
533
  }
525
534
  })();
526
- for (const convId of entityConversationIds) {
535
+ for (const convId of entityConvIds) {
527
536
  const subj = entityConversationSubject(natsTenantId, convId);
528
537
  chatDebugLog(debug, "ChatNatsBridge: subscribing entity conversation", {
529
538
  conversationId: convId,
@@ -540,7 +549,7 @@ function ChatNatsBridge({ natsWsUrl, natsToken, onConnectedChange }) {
540
549
  if (process.env.NODE_ENV === "development") {
541
550
  const subjectList = [
542
551
  inbox,
543
- ...entityConversationIds.map((id) => entityConversationSubject(natsTenantId, id))
552
+ ...entityConvIds.map((id) => entityConversationSubject(natsTenantId, id))
544
553
  ];
545
554
  console.info("[NATS] WebSocket connected \u2014 servers:", servers, "subjects:", subjectList);
546
555
  void (async () => {
@@ -571,7 +580,7 @@ function ChatNatsBridge({ natsWsUrl, natsToken, onConnectedChange }) {
571
580
  connRef.current = null;
572
581
  void c?.drain();
573
582
  };
574
- }, [servers, natsToken, natsTenantId, userId, entityKey, queryClient, entityConversationIds, debug]);
583
+ }, [servers, natsToken, natsTenantId, userId, entityKey, queryClient, debug]);
575
584
  return null;
576
585
  }
577
586
 
@@ -622,6 +631,28 @@ function buildThemeColorOverrideCss(themeOverride) {
622
631
  ${body}
623
632
  }`;
624
633
  }
634
+ function buildAppShellThemeCss(themeOverride) {
635
+ const p = themeOverride?.primary?.trim();
636
+ if (!p) return "";
637
+ const icon = themeOverride?.secondary?.trim() || p;
638
+ const body = `
639
+ --chat-app-accent: ${p};
640
+ --chat-app-tab-active: ${p};
641
+ --chat-app-icon: ${icon};
642
+ --chat-app-fab: ${p};
643
+ --chat-app-row-active-bg: color-mix(in srgb, ${p} 14%, transparent);
644
+ --chat-app-row-active-ring: color-mix(in srgb, ${p} 30%, transparent);
645
+ `;
646
+ return `
647
+ html:not(.dark) [data-chat-root]:not([data-chat-appearance="dark"]),
648
+ [data-chat-root][data-chat-appearance="light"] {
649
+ ${body}
650
+ }
651
+ html.dark [data-chat-root]:not([data-chat-appearance="light"]),
652
+ [data-chat-root][data-chat-appearance="dark"] {
653
+ ${body}
654
+ }`;
655
+ }
625
656
  function ChatProvider({
626
657
  apiUrl,
627
658
  token,
@@ -748,10 +779,11 @@ function ChatProvider({
748
779
  const styleTag = useMemo(() => {
749
780
  const t = mergedTheme;
750
781
  let css = `[data-chat-root] {
751
- --chat-radius: ${t.radius};
752
- --chat-font-family: ${t.fontFamily};
782
+ --chat-radius: ${t.radius ?? "12px"};
783
+ --chat-font-family: ${t.fontFamily ?? "system-ui, -apple-system, sans-serif"};
753
784
  }`;
754
785
  css += buildThemeColorOverrideCss(theme);
786
+ css += buildAppShellThemeCss(theme);
755
787
  return css;
756
788
  }, [mergedTheme, theme]);
757
789
  const [natsConnected, setNatsConnected] = useState(false);
@@ -1044,8 +1076,10 @@ function useChatPanelController({
1044
1076
  [onConversationChange]
1045
1077
  );
1046
1078
  const refreshFromServer = useCallback(() => {
1047
- void queryClient.invalidateQueries({ queryKey: chatKeys.conversations() });
1048
- if (selectedId) void queryClient.invalidateQueries({ queryKey: chatKeys.messages(selectedId) });
1079
+ void queryClient.refetchQueries({ queryKey: chatKeys.conversations() });
1080
+ if (selectedId) {
1081
+ void queryClient.refetchQueries({ queryKey: chatKeys.messages(selectedId) });
1082
+ }
1049
1083
  }, [queryClient, selectedId]);
1050
1084
  useEffect(() => {
1051
1085
  if (!peerUserId) return;
@@ -2163,7 +2197,7 @@ function initials2(name) {
2163
2197
  }
2164
2198
 
2165
2199
  // scss-module:./standalone-chat.module.css#scss-module
2166
- var standalone_chat_module_default = { "root": "standalone-chat__root", "shell": "standalone-chat__shell", "sidebar": "standalone-chat__sidebar", "sidebarHeader": "standalone-chat__sidebarHeader", "sidebarTitle": "standalone-chat__sidebarTitle", "iconSquare": "standalone-chat__iconSquare", "searchWrap": "standalone-chat__searchWrap", "searchInput": "standalone-chat__searchInput", "searchIcon": "standalone-chat__searchIcon", "tabs": "standalone-chat__tabs", "tab": "standalone-chat__tab", "tabActive": "standalone-chat__tabActive", "listScroll": "standalone-chat__listScroll", "sectionLabel": "standalone-chat__sectionLabel", "convRow": "standalone-chat__convRow", "convRowActive": "standalone-chat__convRowActive", "avatar": "standalone-chat__avatar", "avatarInitials": "standalone-chat__avatarInitials", "avatarDot": "standalone-chat__avatarDot", "convBody": "standalone-chat__convBody", "convTopLine": "standalone-chat__convTopLine", "convName": "standalone-chat__convName", "convPreview": "standalone-chat__convPreview", "convTime": "standalone-chat__convTime", "fab": "standalone-chat__fab", "sidebarFooter": "standalone-chat__sidebarFooter", "main": "standalone-chat__main", "mainHeader": "standalone-chat__mainHeader", "mainHeaderLeft": "standalone-chat__mainHeaderLeft", "mainAvatar": "standalone-chat__mainAvatar", "mainTitle": "standalone-chat__mainTitle", "mainStatus": "standalone-chat__mainStatus", "mainActions": "standalone-chat__mainActions", "actionBtn": "standalone-chat__actionBtn", "threadArea": "standalone-chat__threadArea", "emptyMain": "standalone-chat__emptyMain", "inputArea": "standalone-chat__inputArea", "callsEmpty": "standalone-chat__callsEmpty" };
2200
+ var standalone_chat_module_default = { "root": "standalone-chat__root", "shell": "standalone-chat__shell", "sidebar": "standalone-chat__sidebar", "sidebarHeader": "standalone-chat__sidebarHeader", "sidebarTitle": "standalone-chat__sidebarTitle", "iconSquare": "standalone-chat__iconSquare", "searchWrap": "standalone-chat__searchWrap", "searchInput": "standalone-chat__searchInput", "searchIcon": "standalone-chat__searchIcon", "tabs": "standalone-chat__tabs", "tab": "standalone-chat__tab", "tabActive": "standalone-chat__tabActive", "listScroll": "standalone-chat__listScroll", "sectionLabel": "standalone-chat__sectionLabel", "convRow": "standalone-chat__convRow", "convRowActive": "standalone-chat__convRowActive", "avatar": "standalone-chat__avatar", "avatarInitials": "standalone-chat__avatarInitials", "avatarDot": "standalone-chat__avatarDot", "convBody": "standalone-chat__convBody", "convTopLine": "standalone-chat__convTopLine", "convName": "standalone-chat__convName", "convPreview": "standalone-chat__convPreview", "convTime": "standalone-chat__convTime", "fab": "standalone-chat__fab", "sidebarFooter": "standalone-chat__sidebarFooter", "main": "standalone-chat__main", "mainHeader": "standalone-chat__mainHeader", "mainHeaderLeft": "standalone-chat__mainHeaderLeft", "mainTitle": "standalone-chat__mainTitle", "mainStatus": "standalone-chat__mainStatus", "mainActions": "standalone-chat__mainActions", "actionBtn": "standalone-chat__actionBtn", "threadArea": "standalone-chat__threadArea", "emptyMain": "standalone-chat__emptyMain", "inputArea": "standalone-chat__inputArea", "callsEmpty": "standalone-chat__callsEmpty" };
2167
2201
 
2168
2202
  // src/chat/components/ChatInboxSidebar.tsx
2169
2203
  function ChatInboxSidebar({
@@ -2198,7 +2232,7 @@ function ChatInboxSidebar({
2198
2232
  /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.convBody }, /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.convTopLine }, /* @__PURE__ */ React.createElement("span", { className: standalone_chat_module_default.convName }, name), /* @__PURE__ */ React.createElement("span", { className: standalone_chat_module_default.convTime }, timeStr)), preview ? /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.convPreview }, preview) : null)
2199
2233
  );
2200
2234
  };
2201
- return /* @__PURE__ */ React.createElement("aside", { className: standalone_chat_module_default.sidebar }, /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.sidebarHeader }, /* @__PURE__ */ React.createElement("h1", { className: standalone_chat_module_default.sidebarTitle }, "Messages"), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", gap: 8 } }, /* @__PURE__ */ React.createElement(
2235
+ return /* @__PURE__ */ React.createElement("aside", { className: standalone_chat_module_default.sidebar }, /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.sidebarHeader }, /* @__PURE__ */ React.createElement("h1", { className: standalone_chat_module_default.sidebarTitle }, "Messages"), /* @__PURE__ */ React.createElement(
2202
2236
  "button",
2203
2237
  {
2204
2238
  type: "button",
@@ -2208,7 +2242,7 @@ function ChatInboxSidebar({
2208
2242
  onClick: () => onRefresh()
2209
2243
  },
2210
2244
  "\u21BB"
2211
- ), /* @__PURE__ */ React.createElement("button", { type: "button", className: standalone_chat_module_default.iconSquare, "aria-label": "Settings", title: "Settings" }, "\u2699"))), /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.searchWrap }, /* @__PURE__ */ React.createElement(
2245
+ )), /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.searchWrap }, /* @__PURE__ */ React.createElement(
2212
2246
  "input",
2213
2247
  {
2214
2248
  type: "search",
@@ -2218,7 +2252,15 @@ function ChatInboxSidebar({
2218
2252
  onChange: (e) => setQ(e.target.value),
2219
2253
  "aria-label": "Search conversations"
2220
2254
  }
2221
- ), /* @__PURE__ */ React.createElement("span", { className: standalone_chat_module_default.searchIcon }, "\u2315")), /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.tabs, role: "tablist" }, tabDefs.map(([id, label]) => /* @__PURE__ */ React.createElement(
2255
+ ), /* @__PURE__ */ React.createElement("span", { className: standalone_chat_module_default.searchIcon, "aria-hidden": true }, /* @__PURE__ */ React.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", "aria-hidden": true }, /* @__PURE__ */ React.createElement("circle", { cx: "11", cy: "11", r: "7", stroke: "currentColor", strokeWidth: "2" }), /* @__PURE__ */ React.createElement(
2256
+ "path",
2257
+ {
2258
+ d: "M20 20l-3.5-3.5",
2259
+ stroke: "currentColor",
2260
+ strokeWidth: "2",
2261
+ strokeLinecap: "round"
2262
+ }
2263
+ )))), /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.tabs, role: "tablist" }, tabDefs.map(([id, label]) => /* @__PURE__ */ React.createElement(
2222
2264
  "button",
2223
2265
  {
2224
2266
  key: id,
@@ -2236,6 +2278,7 @@ function ChatInboxSidebar({
2236
2278
  function ChatMainColumn({
2237
2279
  selectedId,
2238
2280
  headerTitle,
2281
+ headerInitials,
2239
2282
  headerStatus,
2240
2283
  messages,
2241
2284
  loadMsg,
@@ -2251,7 +2294,7 @@ function ChatMainColumn({
2251
2294
  if (!selectedId) {
2252
2295
  return /* @__PURE__ */ React.createElement("main", { className: standalone_chat_module_default.main }, /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.emptyMain }, emptyMessage));
2253
2296
  }
2254
- return /* @__PURE__ */ React.createElement("main", { className: standalone_chat_module_default.main }, /* @__PURE__ */ React.createElement("header", { className: standalone_chat_module_default.mainHeader }, /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.mainHeaderLeft }, /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.mainAvatar, "aria-hidden": true }), /* @__PURE__ */ React.createElement("div", { style: { minWidth: 0 } }, /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.mainTitle }, headerTitle), headerStatus ? /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.mainStatus }, headerStatus) : null)), /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.mainActions }, callEnabled ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("button", { type: "button", className: standalone_chat_module_default.actionBtn, "aria-label": "Voice call", title: "Voice call" }, "\u{1F4DE}"), /* @__PURE__ */ React.createElement("button", { type: "button", className: standalone_chat_module_default.actionBtn, "aria-label": "Video call", title: "Video call" }, "\u{1F4F9}")) : null, /* @__PURE__ */ React.createElement("button", { type: "button", className: standalone_chat_module_default.actionBtn, "aria-label": "More", title: "More" }, "\u22EE"))), /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.threadArea }, loadMsg ? /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.emptyMain }, "Loading\u2026") : /* @__PURE__ */ React.createElement(
2297
+ return /* @__PURE__ */ React.createElement("main", { className: standalone_chat_module_default.main }, /* @__PURE__ */ React.createElement("header", { className: standalone_chat_module_default.mainHeader }, /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.mainHeaderLeft }, /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.avatar, "aria-hidden": true }, /* @__PURE__ */ React.createElement("span", { className: standalone_chat_module_default.avatarInitials }, headerInitials?.trim() || "?"), /* @__PURE__ */ React.createElement("span", { className: standalone_chat_module_default.avatarDot })), /* @__PURE__ */ React.createElement("div", { style: { minWidth: 0 } }, /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.mainTitle }, headerTitle), headerStatus ? /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.mainStatus }, headerStatus) : null)), callEnabled ? /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.mainActions }, /* @__PURE__ */ React.createElement("button", { type: "button", className: standalone_chat_module_default.actionBtn, "aria-label": "Voice call", title: "Voice call" }, "\u{1F4DE}"), /* @__PURE__ */ React.createElement("button", { type: "button", className: standalone_chat_module_default.actionBtn, "aria-label": "Video call", title: "Video call" }, "\u{1F4F9}")) : null), /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.threadArea }, loadMsg ? /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.emptyMain }, "Loading\u2026") : /* @__PURE__ */ React.createElement(
2255
2298
  MessageThread,
2256
2299
  {
2257
2300
  messages,
@@ -2314,6 +2357,7 @@ function StandaloneChatPage(props) {
2314
2357
  const otherMembers = membersForSelected.filter((m) => m.id !== config.userId);
2315
2358
  const headerTitle = selectedConv ? selectedConv.kind === "direct" ? selectedConv.peer_display_name ?? otherMembers[0]?.display_name ?? convLabel(selectedConv) : convLabel(selectedConv) : "";
2316
2359
  const headerStatus = typingNames.length > 0 ? `${typingNames.join(", ")} typing\u2026` : selectedId ? "online" : "";
2360
+ const headerInitials = headerTitle.trim() ? initials2(headerTitle) : "?";
2317
2361
  return /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.root }, /* @__PURE__ */ React.createElement("div", { className: standalone_chat_module_default.shell }, /* @__PURE__ */ React.createElement(
2318
2362
  ChatInboxSidebar,
2319
2363
  {
@@ -2336,6 +2380,7 @@ function StandaloneChatPage(props) {
2336
2380
  {
2337
2381
  selectedId: selectedId && selectedConv ? selectedId : null,
2338
2382
  headerTitle,
2383
+ headerInitials,
2339
2384
  headerStatus,
2340
2385
  messages,
2341
2386
  loadMsg,
@@ -2393,6 +2438,6 @@ function ChatConversationView({
2393
2438
  ), showTyping ? /* @__PURE__ */ React.createElement(TypingIndicator, { names: typingNames }) : null), /* @__PURE__ */ React.createElement("div", { className: inputAreaClassName }, /* @__PURE__ */ React.createElement(MessageInput, { conversationId })));
2394
2439
  }
2395
2440
 
2396
- export { ChatAPI, MessageInput as ChatComposer, ChatConversationView, ChatInboxSidebar, ChatMainColumn, ChatPanel, ChatProvider, ChatWidget, ConversationList, INITIAL_MESSAGE_PAGE_SIZE, MessageBubble, MessageInput, MessageThread, NewChatModal, StandaloneChatPage, TypingIndicator, chatKeys, convDisplayName, convLabel, formatConvTime, initials2 as initials, mergeMessagePages, useChat, useChatActions, useChatPanelController, useConversationMembers, useConversations, useMessages, usePresignedUrl, useUpload, useVoiceRecorder };
2441
+ export { ChatAPI, MessageInput as ChatComposer, ChatConversationView, ChatInboxSidebar, ChatMainColumn, ChatPanel, ChatProvider, ChatWidget, ConversationList, INITIAL_MESSAGE_PAGE_SIZE, MessageBubble, MessageInput, MessageThread, NewChatModal, StandaloneChatPage, TypingIndicator, chatKeys, convDisplayName, convLabel, formatConvTime, initials2 as initials, mergeMessagePages, normalizeConversationCacheId, useChat, useChatActions, useChatPanelController, useConversationMembers, useConversations, useMessages, usePresignedUrl, useUpload, useVoiceRecorder };
2397
2442
  //# sourceMappingURL=index.mjs.map
2398
2443
  //# sourceMappingURL=index.mjs.map