@realtimexsco/live-chat 1.3.2 → 1.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/README.md CHANGED
@@ -4,14 +4,15 @@
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@realtimexsco/live-chat.svg)](https://www.npmjs.com/package/@realtimexsco/live-chat)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/@realtimexsco/live-chat.svg)](https://www.npmjs.com/package/@realtimexsco/live-chat)
7
- [![license](https://img.shields.io/npm/l/@realtimexsco/live-chat.svg)](./LICENSE)
7
+ [![license](https://img.shields.io/npm/l/@realtimexsco/live-chat.svg)](https://bitbucket.org/software-co/realtimex-npm-package/src/1d8b3426735c2d080ded2ba67255bc43f5035f4b/LICENSE)
8
8
 
9
9
  | | |
10
10
  |---|---|
11
11
  | **Package** | [`@realtimexsco/live-chat`](https://www.npmjs.com/package/@realtimexsco/live-chat) |
12
12
  | **Styles** | `@realtimexsco/live-chat/styles.css` |
13
13
  | **Requires** | React 17+, Tailwind CSS **v4**, Zustand 4+ |
14
- | **License** | [MIT](./LICENSE) |
14
+ | **Docs** | [realtimex.softwareco.com](https://realtimex.softwareco.com/) |
15
+ | **License** | [MIT](https://bitbucket.org/software-co/realtimex-npm-package/src/1d8b3426735c2d080ded2ba67255bc43f5035f4b/LICENSE) |
15
16
 
16
17
  Socket.IO, REST client, Zustand store, Radix UI, emoji picker, and chat UI are **bundled**. Your app only installs peer dependencies.
17
18
 
@@ -58,16 +59,12 @@ DMs · groups · Socket.IO · reactions · replies · forward · edit/delete ·
58
59
 
59
60
  | Topic | Link |
60
61
  |-------|------|
61
- | Full setup guide (Tailwind, Vite, Next.js, config) | [docs/full-guide.md](./docs/full-guide.md) |
62
- | Customization (`components`, `classNames`, `features`) | [Customization](./docs/full-guide.md#customization--three-ways) |
63
- | ChatMain props & API | [Props reference](./docs/full-guide.md#chatmain-props-reference) |
64
- | Hooks & store | [Hooks & store](./docs/full-guide.md#hooks--store) |
65
- | Dev proxy (CORS) | [Dev proxy](./docs/full-guide.md#dev-proxy-cors) |
62
+ | Full setup & docs | [https://realtimex.softwareco.com/](https://realtimex.softwareco.com/) |
66
63
  | npm package | [npmjs.com/package/@realtimexsco/live-chat](https://www.npmjs.com/package/@realtimexsco/live-chat) |
67
- | License | [MIT License](./LICENSE) |
64
+ | License | [MIT](https://bitbucket.org/software-co/realtimex-npm-package/src/1d8b3426735c2d080ded2ba67255bc43f5035f4b/LICENSE) |
68
65
 
69
66
  ---
70
67
 
71
68
  ## License
72
69
 
73
- [MIT](./LICENSE) © RealtimeX
70
+ [MIT](https://bitbucket.org/software-co/realtimex-npm-package/src/1d8b3426735c2d080ded2ba67255bc43f5035f4b/LICENSE) © RealtimeX
package/dist/index.cjs CHANGED
@@ -860,6 +860,9 @@ var init_conversation_helpers = __esm({
860
860
  const mergedParticipants = conversation.participants !== void 0 ? mergeConversationParticipants(existing?.participants, conversation.participants) : existing?.participants ?? conversation.participants;
861
861
  const isGroup = isGroupConversation(conversation) || isGroupConversation(existing);
862
862
  const resolvedGroupImage = resolveGroupImage(conversation) || resolveGroupImage(existing);
863
+ const incomingGroupName = typeof conversation.groupName === "string" && conversation.groupName.trim() || typeof conversation.name === "string" && conversation.name.trim() || "";
864
+ const existingGroupName = typeof existing?.groupName === "string" && existing.groupName.trim() || typeof existing?.name === "string" && existing.name.trim() || "";
865
+ const resolvedGroupName = incomingGroupName || existingGroupName || void 0;
863
866
  return {
864
867
  ...existing,
865
868
  ...conversation,
@@ -867,7 +870,10 @@ var init_conversation_helpers = __esm({
867
870
  isGroup,
868
871
  isBlocked: resolvedBlocked,
869
872
  lastMessage: mergeLastMessage(existing?.lastMessage, conversation.lastMessage),
870
- ...isGroup && resolvedGroupImage ? { image: resolvedGroupImage, groupImage: resolvedGroupImage } : {}
873
+ ...isGroup ? {
874
+ ...resolvedGroupName ? { groupName: resolvedGroupName, name: resolvedGroupName } : {},
875
+ ...resolvedGroupImage ? { image: resolvedGroupImage, groupImage: resolvedGroupImage } : {}
876
+ } : {}
871
877
  };
872
878
  };
873
879
  resolveConversationLastMessage = (conversation, messagesByConversation) => {
@@ -2803,8 +2809,7 @@ var init_message_handlers = __esm({
2803
2809
  conversationType: lastDM.conversationType || "individual",
2804
2810
  isGroup: false,
2805
2811
  ...shouldIncludeParticipants ? { participants: participantSeed } : {},
2806
- groupName: lastDM.groupName,
2807
- name: lastDM.groupName,
2812
+ ...lastDM.groupName ? { groupName: lastDM.groupName, name: lastDM.groupName } : {},
2808
2813
  owner: existingConv?.owner ?? lastDM.owner
2809
2814
  },
2810
2815
  {
@@ -3147,8 +3152,10 @@ var init_group_handlers = __esm({
3147
3152
  _id: conversationId,
3148
3153
  conversationType: "group",
3149
3154
  isGroup: true,
3150
- groupName: lastDM.groupName,
3151
- name: lastDM.groupName,
3155
+ ...lastDM.groupName || lastDM.name ? {
3156
+ groupName: lastDM.groupName || lastDM.name,
3157
+ name: lastDM.groupName || lastDM.name
3158
+ } : {},
3152
3159
  participants: buildParticipantsFromMessagePayload(lastDM, loggedUserId)
3153
3160
  },
3154
3161
  {
@@ -3186,8 +3193,10 @@ var init_group_handlers = __esm({
3186
3193
  _id: conversationId,
3187
3194
  conversationType: "group",
3188
3195
  isGroup: true,
3189
- groupName: lastDM.groupName,
3190
- name: lastDM.groupName,
3196
+ ...lastDM.groupName || lastDM.name ? {
3197
+ groupName: lastDM.groupName || lastDM.name,
3198
+ name: lastDM.groupName || lastDM.name
3199
+ } : {},
3191
3200
  participants: buildParticipantsFromMessagePayload(lastDM, loggedUserId)
3192
3201
  },
3193
3202
  {
@@ -8858,7 +8867,7 @@ function MessageAttachmentsCaptionBar({
8858
8867
  onCancelEdit
8859
8868
  }) {
8860
8869
  if (isStandaloneMetaOnly) {
8861
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end pt-0.5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", children: [
8870
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end pt-1.5 pb-0.5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", children: [
8862
8871
  /* @__PURE__ */ jsxRuntime.jsx(
8863
8872
  MessageCornerBadges,
8864
8873
  {
@@ -10069,6 +10078,8 @@ function FileAttachmentRow({
10069
10078
  }
10070
10079
  window.open(fileUrl, "_blank", "noopener,noreferrer");
10071
10080
  };
10081
+ const onThemeBubble = inBubble && isSender;
10082
+ const onIncomingBubble = inBubble && !isSender;
10072
10083
  return /* @__PURE__ */ jsxRuntime.jsxs(
10073
10084
  "div",
10074
10085
  {
@@ -10076,8 +10087,11 @@ function FileAttachmentRow({
10076
10087
  "group w-full transition-opacity",
10077
10088
  !stacked && "flex min-w-[220px] items-center gap-2",
10078
10089
  stacked && "py-1.5",
10079
- stacked && showDivider && (inBubble && isSender ? "border-t border-white/15" : "border-t border-(--chat-border)/35"),
10080
- !stacked && !inBubble && "rounded-2xl border border-(--chat-border) bg-(--chat-surface) p-2 shadow-sm",
10090
+ stacked && showDivider && (onThemeBubble ? "border-t border-white/15" : "border-t border-(--chat-border)/35"),
10091
+ !stacked && "rounded-xl border p-2.5",
10092
+ !stacked && onThemeBubble && "border-white/20 bg-white/12 text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.08)] backdrop-blur-[2px]",
10093
+ !stacked && onIncomingBubble && "border-(--chat-border)/70 bg-(--chat-elevated) text-(--chat-text) shadow-sm [.dark_&]:bg-(--chat-surface)",
10094
+ !stacked && !inBubble && "border-(--chat-border) bg-(--chat-surface) shadow-sm",
10081
10095
  !fileUrl && "pointer-events-none opacity-60",
10082
10096
  isCaptionActive && "opacity-90"
10083
10097
  ),
@@ -10089,36 +10103,31 @@ function FileAttachmentRow({
10089
10103
  type: "button",
10090
10104
  onClick: handleFileOpen,
10091
10105
  disabled: !fileUrl || selectionMode,
10092
- className: "flex min-w-0 flex-1 items-center gap-2 text-left disabled:cursor-default",
10106
+ className: "flex min-w-0 flex-1 items-center gap-2.5 text-left disabled:cursor-default",
10093
10107
  children: [
10094
10108
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
10095
- "flex shrink-0 items-center justify-center rounded-lg text-white",
10096
- stacked ? "size-9" : "size-10 rounded-xl shadow-sm",
10109
+ "flex size-10 shrink-0 items-center justify-center rounded-lg text-white shadow-sm",
10097
10110
  getAttachmentIconBoxClass(rawName)
10098
- ), children: getAttachmentIcon(rawName, "file", "text-white", stacked ? 18 : 20) }),
10111
+ ), children: getAttachmentIcon(rawName, "file", "text-white", 18) }),
10099
10112
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
10100
10113
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
10101
- "block truncate text-xs font-medium leading-tight",
10102
- inBubble && isSender ? "text-white" : "text-(--chat-text)"
10114
+ "block truncate text-[12px] font-semibold leading-tight",
10115
+ onThemeBubble ? "text-white" : "text-(--chat-text)"
10103
10116
  ), children: displayName }),
10104
10117
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
10105
- "mt-0.5 block truncate text-[10px] leading-tight uppercase",
10106
- inBubble && isSender ? "text-white/60" : "text-(--chat-muted)"
10118
+ "mt-0.5 block truncate text-[10px] font-medium leading-tight uppercase tracking-wide",
10119
+ onThemeBubble ? "text-white/70" : "text-(--chat-muted)"
10107
10120
  ), children: subtitle })
10108
10121
  ] }),
10109
10122
  /* @__PURE__ */ jsxRuntime.jsx(
10110
10123
  "span",
10111
10124
  {
10112
10125
  className: cn(
10113
- "flex shrink-0 items-center justify-center transition-colors",
10114
- stacked ? "size-6 text-(--chat-muted) group-hover:text-(--chat-theme)" : cn(
10115
- "size-7 rounded-lg border",
10116
- inBubble && isSender ? "border-white/15 bg-white/10 text-white/80 group-hover:bg-white/15 group-hover:text-white" : "border-(--chat-border) bg-(--chat-elevated) text-(--chat-muted) group-hover:text-(--chat-theme)"
10117
- ),
10118
- stacked && inBubble && isSender && "text-white/70 group-hover:text-white"
10126
+ "flex size-8 shrink-0 items-center justify-center rounded-full transition-colors",
10127
+ onThemeBubble ? "text-white/80 group-hover:bg-white/10 group-hover:text-white" : "text-(--chat-muted) group-hover:bg-(--chat-hover) group-hover:text-(--chat-theme)"
10119
10128
  ),
10120
10129
  "aria-hidden": true,
10121
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: stacked ? 13 : 14 })
10130
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: 14 })
10122
10131
  }
10123
10132
  )
10124
10133
  ]
@@ -10129,13 +10138,13 @@ function FileAttachmentRow({
10129
10138
  {
10130
10139
  onClick: onEditCaption,
10131
10140
  label: `${attachmentCaption ? "Edit" : "Add"} caption for ${displayName}`,
10132
- className: inBubble && isSender ? "text-white/60 hover:text-white" : void 0
10141
+ className: onThemeBubble ? "text-white/60 hover:text-white" : void 0
10133
10142
  }
10134
10143
  )
10135
10144
  ] }),
10136
10145
  stacked && attachmentCaption ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn(
10137
- "mt-1 whitespace-pre-wrap break-words pl-11 pr-7 text-[11px] leading-snug",
10138
- inBubble && isSender ? "text-white/85" : "text-(--chat-text-secondary)"
10146
+ "mt-1 whitespace-pre-wrap break-words pl-12 pr-8 text-[11px] leading-snug",
10147
+ onThemeBubble ? "text-white/85" : "text-(--chat-text-secondary)"
10139
10148
  ), children: attachmentCaption }) : null
10140
10149
  ]
10141
10150
  }
@@ -10254,17 +10263,30 @@ function MessageAttachmentsNonImageSection({
10254
10263
  att.id
10255
10264
  );
10256
10265
  };
10257
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: nonImageGroups.map((group) => {
10266
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full flex-col gap-1.5", children: nonImageGroups.map((group) => {
10258
10267
  if (group.kind === "file-run") {
10259
10268
  if (group.items.length === 1) {
10260
10269
  return renderFileAttachmentFrame(group.items[0]);
10261
10270
  }
10262
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full min-w-[220px]", children: group.items.map(
10263
- (att2, index) => renderFileAttachmentFrame(att2, {
10264
- stacked: true,
10265
- showDivider: index > 0
10266
- })
10267
- ) }, `file-run-${group.items.map((item) => item.id).join("-")}`);
10271
+ return /* @__PURE__ */ jsxRuntime.jsx(
10272
+ "div",
10273
+ {
10274
+ className: cn(
10275
+ "w-full min-w-[220px]",
10276
+ isBubbleLayout && "rounded-xl border p-2",
10277
+ isBubbleLayout && isSender && "border-white/20 bg-white/12 shadow-[inset_0_1px_0_rgba(255,255,255,0.08)] backdrop-blur-[2px]",
10278
+ isBubbleLayout && !isSender && "border-(--chat-border)/70 bg-(--chat-elevated) shadow-sm [.dark_&]:bg-(--chat-surface)",
10279
+ !isBubbleLayout && "rounded-xl border border-(--chat-border) bg-(--chat-surface) p-2 shadow-sm"
10280
+ ),
10281
+ children: group.items.map(
10282
+ (att2, index) => renderFileAttachmentFrame(att2, {
10283
+ stacked: true,
10284
+ showDivider: index > 0
10285
+ })
10286
+ )
10287
+ },
10288
+ `file-run-${group.items.map((item) => item.id).join("-")}`
10289
+ );
10268
10290
  }
10269
10291
  const att = group.item;
10270
10292
  const type = resolveAttachmentType(att);
@@ -10354,11 +10376,12 @@ function MessageAttachmentsView({
10354
10376
  const isImageOnlyBubble = isBubbleLayout && nonImages.length === 0 && images.length > 0;
10355
10377
  const showImageMetaOverlay = isImageOnlyBubble && !hasMessageCaption && !anyImageHasCaption && !attachmentSelectionMode;
10356
10378
  const showCaptionBar = showBottomBar && (!isImageOnlyBubble || hasMessageCaption);
10357
- const bubbleSurface = !isBubbleLayout ? void 0 : isImageOnlyBubble && !hasMessageCaption && !anyImageHasCaption ? "media" : isSender ? "sent" : "received";
10379
+ const canShowSenderName = !!isGroup && !isSender && !!showSenderLabel && !!senderName;
10380
+ const showForwardedInHeader = isBubbleLayout && isForwarded;
10381
+ const bubbleSurface = !isBubbleLayout ? void 0 : isImageOnlyBubble && !hasMessageCaption && !anyImageHasCaption && !isForwarded && !canShowSenderName ? "media" : isSender ? "sent" : "received";
10358
10382
  const metaTimeClass = showImageMetaOverlay ? "text-white/90" : isSender ? "text-white/70" : "text-(--chat-muted)";
10359
10383
  const metaBorderClass = isSender ? "border-white/15" : "border-(--chat-border)/40";
10360
10384
  const metaBadgeVariant = showImageMetaOverlay || isBubbleLayout && isSender ? "on-dark" : "default";
10361
- const isForwardedImageOnly = isBubbleLayout && isForwarded && isImageOnlyBubble;
10362
10385
  return /* @__PURE__ */ jsxRuntime.jsxs(
10363
10386
  "div",
10364
10387
  {
@@ -10377,29 +10400,39 @@ function MessageAttachmentsView({
10377
10400
  isSender,
10378
10401
  surface: bubbleSurface,
10379
10402
  className: cn(
10380
- isImageOnlyBubble ? "p-0" : isForwarded ? "px-2 py-0.5" : "px-2.5 py-1"
10403
+ isImageOnlyBubble ? "overflow-hidden p-0" : isForwarded || canShowSenderName ? "px-2 py-1" : cn(
10404
+ "px-2.5",
10405
+ nonImages.length > 1 || images.length > 0 && nonImages.length > 0 ? "py-1.5" : "py-1"
10406
+ )
10381
10407
  )
10382
10408
  })
10383
10409
  ),
10384
10410
  children: [
10385
- !isSender && showSenderLabel && senderName && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-0.5 pb-1", children: /* @__PURE__ */ jsxRuntime.jsx(GroupSenderName, { name: senderName }) }),
10386
- isBubbleLayout && isForwarded && !isForwardedImageOnly && /* @__PURE__ */ jsxRuntime.jsx(MessageForwardedLabel, { isSender, className: "px-0 pt-0 pb-0" }),
10411
+ (canShowSenderName || showForwardedInHeader) && /* @__PURE__ */ jsxRuntime.jsxs(
10412
+ "div",
10413
+ {
10414
+ className: cn(
10415
+ "relative z-10 flex min-w-0 flex-col gap-0.5",
10416
+ isImageOnlyBubble ? "px-2.5 pt-1.5 pb-1" : "px-0.5 pb-0.5"
10417
+ ),
10418
+ children: [
10419
+ canShowSenderName ? /* @__PURE__ */ jsxRuntime.jsx(GroupSenderName, { name: senderName }) : null,
10420
+ showForwardedInHeader ? /* @__PURE__ */ jsxRuntime.jsx(
10421
+ MessageForwardedLabel,
10422
+ {
10423
+ isSender,
10424
+ className: "px-0 pt-0 pb-0"
10425
+ }
10426
+ ) : null
10427
+ ]
10428
+ }
10429
+ ),
10387
10430
  isBubbleLayout && replySnippet ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 pb-1", children: replySnippet }) : null,
10388
10431
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
10389
10432
  "flex w-full flex-col",
10390
- !isImageOnlyBubble && "gap-0",
10391
- isImageOnlyBubble && "relative overflow-hidden rounded-[inherit]"
10433
+ !isImageOnlyBubble && (images.length > 0 && nonImages.length > 0 ? "gap-1.5" : "gap-0"),
10434
+ isImageOnlyBubble && "relative overflow-hidden"
10392
10435
  ), children: [
10393
- isForwardedImageOnly && /* @__PURE__ */ jsxRuntime.jsx(
10394
- "div",
10395
- {
10396
- className: cn(
10397
- "pointer-events-none absolute inset-x-0 top-0 z-20 px-2 py-0.5",
10398
- isSender ? "bg-linear-to-b from-(--chat-theme)/95 via-(--chat-theme)/55 to-transparent" : "bg-linear-to-b from-(--chat-incoming-bubble)/95 via-(--chat-incoming-bubble)/55 to-transparent"
10399
- ),
10400
- children: /* @__PURE__ */ jsxRuntime.jsx(MessageForwardedLabel, { isSender, overlay: true, className: "px-0 pt-0 pb-0" })
10401
- }
10402
- ),
10403
10436
  /* @__PURE__ */ jsxRuntime.jsx(
10404
10437
  MessageAttachmentsImageSection,
10405
10438
  {
@@ -13837,6 +13870,7 @@ function MessageItemTextBubble({
13837
13870
  isSender,
13838
13871
  className: extra
13839
13872
  });
13873
+ const canShowSenderName = !!isGroup && !isSender && !!showSenderLabel && !!senderName;
13840
13874
  return /* @__PURE__ */ jsxRuntime.jsxs(
13841
13875
  "div",
13842
13876
  {
@@ -13844,15 +13878,17 @@ function MessageItemTextBubble({
13844
13878
  bubbleClasses(
13845
13879
  cn(
13846
13880
  "flex min-w-[72px] flex-col transition-all duration-200",
13847
- isForwarded ? "gap-0.5 px-2.5 py-1.5 text-[13px]" : "gap-1 px-3.5 py-2.5 text-[14px]"
13881
+ canShowSenderName ? "gap-0.5 px-2.5 py-1.5 text-[14px]" : isForwarded ? "gap-0.5 px-2.5 py-1.5 text-[13px]" : "gap-1 px-3.5 py-2.5 text-[14px]"
13848
13882
  )
13849
13883
  ),
13850
13884
  isPending && "opacity-70",
13851
13885
  isHighlighted && (isSender ? "ring-2 ring-amber-300/60" : "ring-2 ring-amber-200/60")
13852
13886
  ),
13853
13887
  children: [
13854
- isForwarded && /* @__PURE__ */ jsxRuntime.jsx(MessageForwardedLabel, { isSender, className: "px-0 pt-0 pb-0" }),
13855
- !isSender && showSenderLabel && senderName && /* @__PURE__ */ jsxRuntime.jsx(GroupSenderName, { name: senderName, className: "mb-0.5" }),
13888
+ (canShowSenderName || isForwarded) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
13889
+ canShowSenderName ? /* @__PURE__ */ jsxRuntime.jsx(GroupSenderName, { name: senderName }) : null,
13890
+ isForwarded ? /* @__PURE__ */ jsxRuntime.jsx(MessageForwardedLabel, { isSender, className: "px-0 pt-0 pb-0" }) : null
13891
+ ] }),
13856
13892
  /* @__PURE__ */ jsxRuntime.jsx(
13857
13893
  MessageReplySnippet_default,
13858
13894
  {