stream-chat-react 14.0.0-beta.4 → 14.0.0-beta.6

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.
Files changed (69) hide show
  1. package/dist/cjs/{WithAudioPlayback.236d404c.js → WithAudioPlayback.f9abf707.js} +94 -116
  2. package/dist/cjs/WithAudioPlayback.f9abf707.js.map +1 -0
  3. package/dist/cjs/emojis.js +1 -1
  4. package/dist/cjs/index.js +161 -188
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/css/index.css +219 -595
  7. package/dist/css/index.css.map +1 -1
  8. package/dist/es/{WithAudioPlayback.89700cb5.mjs → WithAudioPlayback.d90f1a99.mjs} +184 -206
  9. package/dist/es/WithAudioPlayback.d90f1a99.mjs.map +1 -0
  10. package/dist/es/emojis.mjs +1 -1
  11. package/dist/es/index.mjs +221 -248
  12. package/dist/es/index.mjs.map +1 -1
  13. package/dist/types/components/Avatar/Avatar.d.ts +1 -1
  14. package/dist/types/components/Avatar/Avatar.d.ts.map +1 -1
  15. package/dist/types/components/Avatar/AvatarStack.d.ts +2 -2
  16. package/dist/types/components/Avatar/AvatarStack.d.ts.map +1 -1
  17. package/dist/types/components/Avatar/ChannelAvatar.d.ts +2 -6
  18. package/dist/types/components/Avatar/ChannelAvatar.d.ts.map +1 -1
  19. package/dist/types/components/Avatar/GroupAvatar.d.ts +6 -7
  20. package/dist/types/components/Avatar/GroupAvatar.d.ts.map +1 -1
  21. package/dist/types/components/ChannelHeader/ChannelHeader.d.ts +1 -1
  22. package/dist/types/components/ChannelHeader/ChannelHeader.d.ts.map +1 -1
  23. package/dist/types/components/ChannelListItem/ChannelListItemUI.d.ts.map +1 -1
  24. package/dist/types/components/ChannelListItem/utils.d.ts.map +1 -1
  25. package/dist/types/components/Dialog/service/DialogPortal.d.ts.map +1 -1
  26. package/dist/types/components/Form/SwitchField.d.ts.map +1 -1
  27. package/dist/types/components/Icons/createIcon.d.ts +1 -1
  28. package/dist/types/components/Icons/createIcon.d.ts.map +1 -1
  29. package/dist/types/components/Icons/icons.d.ts +9 -41
  30. package/dist/types/components/Icons/icons.d.ts.map +1 -1
  31. package/dist/types/components/Icons/index.d.ts +0 -1
  32. package/dist/types/components/Icons/index.d.ts.map +1 -1
  33. package/dist/types/components/Message/Message.d.ts.map +1 -1
  34. package/dist/types/components/Message/hooks/useUserRole.d.ts.map +1 -1
  35. package/dist/types/components/Message/types.d.ts +1 -5
  36. package/dist/types/components/Message/types.d.ts.map +1 -1
  37. package/dist/types/components/MessageActions/MessageActions.defaults.d.ts.map +1 -1
  38. package/dist/types/components/MessageComposer/MessageComposerUI.d.ts.map +1 -1
  39. package/dist/types/components/MessageComposer/hooks/useSubmitHandler.d.ts.map +1 -1
  40. package/dist/types/components/MessageComposer/preEditSnapshot.d.ts +16 -0
  41. package/dist/types/components/MessageComposer/preEditSnapshot.d.ts.map +1 -0
  42. package/dist/types/components/MessageList/MessageList.d.ts +1 -1
  43. package/dist/types/components/MessageList/MessageList.d.ts.map +1 -1
  44. package/dist/types/components/MessageList/VirtualizedMessageList.d.ts +1 -1
  45. package/dist/types/components/MessageList/VirtualizedMessageList.d.ts.map +1 -1
  46. package/dist/types/components/MessageList/VirtualizedMessageListComponents.d.ts.map +1 -1
  47. package/dist/types/components/Reactions/MessageReactions.d.ts +4 -16
  48. package/dist/types/components/Reactions/MessageReactions.d.ts.map +1 -1
  49. package/dist/types/components/Reactions/MessageReactionsDetail.d.ts +4 -4
  50. package/dist/types/components/Reactions/MessageReactionsDetail.d.ts.map +1 -1
  51. package/dist/types/components/Reactions/hooks/useProcessReactions.d.ts +4 -2
  52. package/dist/types/components/Reactions/hooks/useProcessReactions.d.ts.map +1 -1
  53. package/dist/types/components/Reactions/types.d.ts +0 -1
  54. package/dist/types/components/Reactions/types.d.ts.map +1 -1
  55. package/dist/types/components/SummarizedMessagePreview/SummarizedMessagePreview.d.ts.map +1 -1
  56. package/dist/types/components/SummarizedMessagePreview/hooks/useLatestMessagePreview.d.ts.map +1 -1
  57. package/dist/types/components/Thread/ThreadHeader.d.ts +1 -1
  58. package/dist/types/components/Thread/ThreadHeader.d.ts.map +1 -1
  59. package/dist/types/components/TypingIndicator/TypingIndicator.d.ts.map +1 -1
  60. package/dist/types/context/ComponentContext.d.ts +2 -2
  61. package/dist/types/context/ComponentContext.d.ts.map +1 -1
  62. package/dist/types/context/MessageBounceContext.d.ts.map +1 -1
  63. package/dist/types/context/MessageContext.d.ts +1 -5
  64. package/dist/types/context/MessageContext.d.ts.map +1 -1
  65. package/package.json +1 -1
  66. package/dist/cjs/WithAudioPlayback.236d404c.js.map +0 -1
  67. package/dist/es/WithAudioPlayback.89700cb5.mjs.map +0 -1
  68. package/dist/types/components/Icons/IconGiphy.d.ts +0 -3
  69. package/dist/types/components/Icons/IconGiphy.d.ts.map +0 -1
package/dist/cjs/index.js CHANGED
@@ -5,7 +5,7 @@ const clsx = require("clsx");
5
5
  const nanoid = require("nanoid");
6
6
  const React = require("react");
7
7
  const audioProcessing = require("./audioProcessing.56e5db9d.js");
8
- const WithAudioPlayback = require("./WithAudioPlayback.236d404c.js");
8
+ const WithAudioPlayback = require("./WithAudioPlayback.f9abf707.js");
9
9
  const streamChat = require("stream-chat");
10
10
  const throttle = require("lodash.throttle");
11
11
  const linkify = require("linkifyjs");
@@ -292,7 +292,8 @@ const DialogPortalDestination = () => {
292
292
  React.useEffect(() => {
293
293
  if (!destinationRoot || !dialogManager) return;
294
294
  const handleDocumentClick = (event) => {
295
- if (destinationRoot.contains(event.target)) return;
295
+ const target = event.target;
296
+ if (target !== destinationRoot && destinationRoot.contains(target)) return;
296
297
  setTimeout(() => {
297
298
  Object.values(dialogManager.state.getLatestValue().dialogsById).forEach(
298
299
  (dialog) => {
@@ -319,21 +320,6 @@ const DialogPortalDestination = () => {
319
320
  className: "str-chat__dialog-overlay",
320
321
  "data-str-chat__portal-id": dialogManager?.id,
321
322
  "data-testid": "str-chat__dialog-overlay",
322
- onClick: (event) => {
323
- if (!dialogManager) return;
324
- if (event.target !== event.currentTarget) return;
325
- Object.values(dialogManager.state.getLatestValue().dialogsById).forEach(
326
- (dialog) => {
327
- if (!dialog.isOpen) return;
328
- if (!shouldCloseOnOutsideClick({
329
- dialog,
330
- managerCloseOnClickOutside: dialogManager.closeOnClickOutside
331
- }))
332
- return;
333
- dialogManager.close(dialog.id);
334
- }
335
- );
336
- },
337
323
  ref: setDestinationRoot,
338
324
  style: {
339
325
  "--str-chat__dialog-overlay-height": openedDialogCount > 0 ? "100%" : "0"
@@ -491,6 +477,38 @@ const useMessageContext = (_componentName) => {
491
477
  }
492
478
  return contextValue;
493
479
  };
480
+ const snapshots = /* @__PURE__ */ new WeakMap();
481
+ const savePreEditSnapshot = (messageComposer) => {
482
+ if (snapshots.has(messageComposer)) return;
483
+ const composerState = messageComposer.state.getLatestValue();
484
+ const textState = messageComposer.textComposer.state.getLatestValue();
485
+ const attachmentState = messageComposer.attachmentManager.state.getLatestValue();
486
+ const linkPreviewState = messageComposer.linkPreviewsManager.state.getLatestValue();
487
+ const locationState = messageComposer.locationComposer.state.getLatestValue();
488
+ const pollState = messageComposer.pollComposer.state.getLatestValue();
489
+ const customDataState = messageComposer.customDataManager.state.getLatestValue();
490
+ snapshots.set(messageComposer, () => {
491
+ messageComposer.state.next(composerState);
492
+ messageComposer.textComposer.state.next(textState);
493
+ messageComposer.attachmentManager.state.next(attachmentState);
494
+ messageComposer.linkPreviewsManager.state.next(linkPreviewState);
495
+ messageComposer.locationComposer.state.next(locationState);
496
+ messageComposer.pollComposer.state.next(pollState);
497
+ messageComposer.customDataManager.state.next(customDataState);
498
+ });
499
+ };
500
+ const restorePreEditSnapshot = (messageComposer) => {
501
+ const restore = snapshots.get(messageComposer);
502
+ snapshots.delete(messageComposer);
503
+ if (restore) {
504
+ restore();
505
+ } else {
506
+ messageComposer.clear();
507
+ }
508
+ };
509
+ const discardPreEditSnapshot = (messageComposer) => {
510
+ snapshots.delete(messageComposer);
511
+ };
494
512
  const MessageBounceContext = React.createContext(
495
513
  void 0
496
514
  );
@@ -519,6 +537,7 @@ function MessageBounceProvider({ children }) {
519
537
  const handleEdit = React.useCallback(
520
538
  (e) => {
521
539
  e.preventDefault();
540
+ savePreEditSnapshot(messageComposer);
522
541
  messageComposer.initState({ composition: message });
523
542
  },
524
543
  [message, messageComposer]
@@ -727,47 +746,6 @@ const useNotifications = (options) => {
727
746
  const { notifications } = WithAudioPlayback.useStateStore(client.notifications.store, selector2);
728
747
  return notifications;
729
748
  };
730
- const IconGiphy = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsxs(
731
- WithAudioPlayback.BaseIcon,
732
- {
733
- ...props,
734
- className: clsx("str-chat__icon--giphy", className),
735
- viewBox: "0 0 16 16",
736
- children: [
737
- /* @__PURE__ */ jsxRuntime.jsx("rect", { fill: "black", height: "16", rx: "8", width: "16" }),
738
- /* @__PURE__ */ jsxRuntime.jsx(
739
- "path",
740
- {
741
- clipRule: "evenodd",
742
- d: "M5.27976 4.40015H10.7206V11.5999H5.2793L5.27976 4.40015Z",
743
- fill: "black",
744
- fillRule: "evenodd"
745
- }
746
- ),
747
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4.19189 4.1333H5.27969V11.8669H4.19189V4.1333Z", fill: "#04FF8E" }),
748
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10.7202 6.26685H11.808V11.8668H10.7202V6.26685Z", fill: "#8E2EFF" }),
749
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4.19189 11.5999H11.8079V12.6667H4.19189V11.5999Z", fill: "#00C5FF" }),
750
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4.19189 3.33325H8.54403V4.40005H4.19189V3.33325Z", fill: "#FFF152" }),
751
- /* @__PURE__ */ jsxRuntime.jsx(
752
- "path",
753
- {
754
- d: "M10.72 5.46638V4.40005H9.63174V3.33325H8.54395V6.53318H11.8078V5.46638",
755
- fill: "#FF5B5B"
756
- }
757
- ),
758
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10.7202 7.6V6.5332H11.808", fill: "#551C99" }),
759
- /* @__PURE__ */ jsxRuntime.jsx(
760
- "path",
761
- {
762
- clipRule: "evenodd",
763
- d: "M8.54432 3.33325V4.40005H7.45605",
764
- fill: "#999131",
765
- fillRule: "evenodd"
766
- }
767
- )
768
- ]
769
- }
770
- );
771
749
  const PlayButton = ({ className, isPlaying, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
772
750
  WithAudioPlayback.Button,
773
751
  {
@@ -8925,7 +8903,7 @@ const useUserRole = (message, onlySenderCanEdit, disableQuotedMessages) => {
8925
8903
  const isOwner = channel.state.membership.role === "owner";
8926
8904
  const isModerator = client.user?.role === "channel_moderator" || channel.state.membership.role === "channel_moderator" || channel.state.membership.role === "moderator" || channel.state.membership.is_moderator === true || channel.state.membership.channel_role === "channel_moderator";
8927
8905
  const isMyMessage = client.userID === message.user?.id;
8928
- const canEdit = !message.poll && (!onlySenderCanEdit && channelCapabilities["update-any-message"] || isMyMessage && channelCapabilities["update-own-message"]);
8906
+ const canEdit = !message.poll && message.command !== "giphy" && (!onlySenderCanEdit && channelCapabilities["update-any-message"] || isMyMessage && channelCapabilities["update-own-message"]);
8929
8907
  const canDelete = channelCapabilities["delete-any-message"] || isMyMessage && channelCapabilities["delete-own-message"];
8930
8908
  const canFlag = !isMyMessage && channelCapabilities["flag-message"];
8931
8909
  const canMute = !isMyMessage && channelCapabilities["mute-channel"];
@@ -9331,12 +9309,17 @@ const ErrorBadge = ({
9331
9309
  }) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { ...rest, className, size, variant: "error", children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamationMarkFill, {}) });
9332
9310
  function AvatarStack({
9333
9311
  badgeSize,
9312
+ capLimit = 3,
9334
9313
  component: Component = "div",
9335
9314
  displayInfo = [],
9336
- overflowCount,
9337
9315
  size
9338
9316
  }) {
9339
9317
  const { Avatar: Avatar$1 = Avatar } = WithAudioPlayback.useComponentContext(AvatarStack.name);
9318
+ const displayInfoToRender = React.useMemo(
9319
+ () => displayInfo.length > capLimit ? displayInfo.slice(0, capLimit) : displayInfo,
9320
+ [displayInfo, capLimit]
9321
+ );
9322
+ const overflowCount = displayInfo.length - displayInfoToRender.length;
9340
9323
  if (!displayInfo.length) {
9341
9324
  return null;
9342
9325
  }
@@ -9346,8 +9329,9 @@ function AvatarStack({
9346
9329
  className: clsx("str-chat__avatar-stack", {
9347
9330
  [`str-chat__avatar-stack--size-${size}`]: typeof size === "string"
9348
9331
  }),
9332
+ "data-testid": "avatar-stack",
9349
9333
  children: [
9350
- displayInfo.map((info, index) => /* @__PURE__ */ jsxRuntime.jsx(
9334
+ displayInfoToRender.map((info, index) => /* @__PURE__ */ jsxRuntime.jsx(
9351
9335
  Avatar$1,
9352
9336
  {
9353
9337
  imageUrl: info.imageUrl,
@@ -9360,6 +9344,7 @@ function AvatarStack({
9360
9344
  Badge,
9361
9345
  {
9362
9346
  className: "str-chat__avatar-stack__count-badge",
9347
+ "data-testid": "avatar-stack-count-badge",
9363
9348
  size: badgeSize ?? size,
9364
9349
  variant: "counter",
9365
9350
  children: [
@@ -9375,34 +9360,36 @@ function AvatarStack({
9375
9360
  const ChannelAvatar = ({
9376
9361
  displayMembers,
9377
9362
  imageUrl,
9378
- overflowCount,
9379
9363
  size,
9380
9364
  userName,
9381
9365
  ...sharedProps
9382
9366
  }) => {
9383
- if ((displayMembers?.length ?? 0) >= 2) {
9384
- return /* @__PURE__ */ jsxRuntime.jsx(
9385
- GroupAvatar,
9367
+ const displayInfo = React.useMemo(() => {
9368
+ if (displayMembers && displayMembers.length > 0) {
9369
+ return displayMembers;
9370
+ }
9371
+ return [
9386
9372
  {
9387
- displayMembers,
9388
- overflowCount,
9389
- size,
9390
- ...sharedProps
9373
+ imageUrl,
9374
+ userName
9391
9375
  }
9392
- );
9393
- }
9394
- return /* @__PURE__ */ jsxRuntime.jsx(Avatar, { imageUrl, size, userName, ...sharedProps });
9376
+ ];
9377
+ }, [displayMembers, imageUrl, userName]);
9378
+ return /* @__PURE__ */ jsxRuntime.jsx(GroupAvatar, { displayMembers: displayInfo, size, ...sharedProps });
9395
9379
  };
9396
9380
  const GroupAvatar = ({
9397
9381
  badgeSize,
9398
9382
  className,
9399
9383
  displayMembers = [],
9400
9384
  isOnline,
9401
- overflowCount,
9402
9385
  size,
9403
9386
  ...rest
9404
9387
  }) => {
9405
- const displayCountBadge = typeof overflowCount === "number" && overflowCount > 0;
9388
+ const displayMembersToRender = React.useMemo(
9389
+ () => displayMembers.length > 4 ? displayMembers.slice(0, 2) : displayMembers,
9390
+ [displayMembers]
9391
+ );
9392
+ const overflowCount = displayMembers.length - displayMembersToRender.length;
9406
9393
  if (displayMembers.length < 2) {
9407
9394
  const firstUser = displayMembers[0];
9408
9395
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -9440,19 +9427,20 @@ const GroupAvatar = ({
9440
9427
  role: "button",
9441
9428
  ...rest,
9442
9429
  children: [
9443
- displayMembers.slice(0, displayCountBadge ? 2 : 4).map(({ imageUrl, userName }, index) => /* @__PURE__ */ jsxRuntime.jsx(
9430
+ displayMembersToRender.map(({ id, imageUrl, userName }, index) => /* @__PURE__ */ jsxRuntime.jsx(
9444
9431
  Avatar,
9445
9432
  {
9446
9433
  imageUrl,
9447
9434
  size: avatarSize,
9448
9435
  userName
9449
9436
  },
9450
- `${userName}-${imageUrl}-${index}`
9437
+ id || `${userName}-${imageUrl}-${index}`
9451
9438
  )),
9452
- displayCountBadge && /* @__PURE__ */ jsxRuntime.jsxs(
9439
+ typeof overflowCount === "number" && overflowCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
9453
9440
  Badge,
9454
9441
  {
9455
9442
  className: "str-chat__avatar-group__count-badge",
9443
+ "data-testid": "group-avatar-count-badge",
9456
9444
  size: badgeSize,
9457
9445
  variant: "counter",
9458
9446
  children: [
@@ -11194,6 +11182,7 @@ const useSubmitHandler = (props) => {
11194
11182
  if (messageComposer.editedMessage && localMessage.type !== "error") {
11195
11183
  try {
11196
11184
  await editMessage(localMessage, sendOptions);
11185
+ discardPreEditSnapshot(messageComposer);
11197
11186
  messageComposer.clear();
11198
11187
  } catch (err) {
11199
11188
  client.notifications.addError({
@@ -12049,7 +12038,7 @@ const RemoveAttachmentPreviewButton = ({
12049
12038
  "data-testid": "preview-item-delete-button",
12050
12039
  disabled: uploadState === "uploading",
12051
12040
  ...props,
12052
- children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconCrossSmall, {})
12041
+ children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconXmarkSmall, {})
12053
12042
  }
12054
12043
  );
12055
12044
  };
@@ -13584,15 +13573,7 @@ const SwitchField = ({
13584
13573
  ref: inputRef
13585
13574
  }
13586
13575
  ),
13587
- title ? /* @__PURE__ */ jsxRuntime.jsx(
13588
- SwitchFieldLabel,
13589
- {
13590
- description,
13591
- htmlFor: id,
13592
- onClick: () => inputRef.current?.click(),
13593
- title
13594
- }
13595
- ) : children,
13576
+ title ? /* @__PURE__ */ jsxRuntime.jsx(SwitchFieldLabel, { description, htmlFor: id, title }) : children,
13596
13577
  /* @__PURE__ */ jsxRuntime.jsx(
13597
13578
  Switch,
13598
13579
  {
@@ -14651,7 +14632,7 @@ const PollVoteTimestamp = ({ timestamp }) => {
14651
14632
  const PollVoteAuthor = ({ vote }) => {
14652
14633
  const { t } = WithAudioPlayback.useTranslationContext();
14653
14634
  const { client } = WithAudioPlayback.useChatContext();
14654
- const displayName = client.user?.id && client.user.id === vote.user?.id ? t("You") : vote.user?.name || t("Anonymous");
14635
+ const displayName = client.user?.id && client.user.id === vote.user?.id ? t("You") : vote.user?.name || vote.user?.id || t("Anonymous");
14655
14636
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__poll-vote__author", children: [
14656
14637
  vote.user && /* @__PURE__ */ jsxRuntime.jsx(
14657
14638
  Avatar,
@@ -15725,7 +15706,7 @@ const useAttachmentSelectorContext = () => React.useContext(AttachmentSelectorCo
15725
15706
  const icons = {
15726
15707
  ban: WithAudioPlayback.IconUserRemove,
15727
15708
  flag: WithAudioPlayback.IconFlag,
15728
- giphy: IconGiphy,
15709
+ giphy: WithAudioPlayback.IconGiphy,
15729
15710
  mute: WithAudioPlayback.IconMute,
15730
15711
  unban: WithAudioPlayback.IconUserAdd,
15731
15712
  unmute: WithAudioPlayback.IconAudio
@@ -16273,7 +16254,7 @@ const FileAttachmentPreview = ({
16273
16254
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: hasSizeLimitError ? t("File too large") : uploadState === "blocked" ? t("Upload blocked") : t("Upload failed") })
16274
16255
  ] }),
16275
16256
  hasRetriableError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-file__retriable-error", children: [
16276
- /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamationTriangle, {}),
16257
+ /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamationTriangleFill, {}),
16277
16258
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("Upload error") }),
16278
16259
  /* @__PURE__ */ jsxRuntime.jsx(
16279
16260
  "button",
@@ -16493,7 +16474,7 @@ const ProgressBar = ({ className, progress, seek }) => {
16493
16474
  {
16494
16475
  className: "str-chat__message-attachment-audio-widget--progress-indicator",
16495
16476
  ref: setProgressIndicator,
16496
- style: { left: `${indicatorLeft}px` }
16477
+ style: { insetInlineStart: `${indicatorLeft}px` }
16497
16478
  }
16498
16479
  )
16499
16480
  }
@@ -16729,7 +16710,7 @@ const WaveProgressBar = ({
16729
16710
  "data-testid": "wave-progress-bar-progress-indicator",
16730
16711
  ref: setProgressIndicator,
16731
16712
  style: {
16732
- left: `${indicatorLeft}px`
16713
+ insetInlineStart: `${indicatorLeft}px`
16733
16714
  }
16734
16715
  }
16735
16716
  )
@@ -16828,7 +16809,7 @@ const AudioAttachmentPreview = ({
16828
16809
  /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamationMark, {}),
16829
16810
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: hasSizeLimitError ? t("File too large") : uploadState === "blocked" ? t("Upload blocked") : t("Upload failed") })
16830
16811
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-file__retriable-error", children: [
16831
- /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamationTriangle, {}),
16812
+ /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamationTriangleFill, {}),
16832
16813
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("Upload error") }),
16833
16814
  /* @__PURE__ */ jsxRuntime.jsx(
16834
16815
  "button",
@@ -16871,7 +16852,7 @@ const MediaAttachmentPreview = ({
16871
16852
  removeAttachments
16872
16853
  }) => {
16873
16854
  const { t } = WithAudioPlayback.useTranslationContext();
16874
- const { BaseImage: BaseImage$1 = BaseImage, LoadingIndicator: LoadingIndicator2 = LoadingIndicatorIcon } = WithAudioPlayback.useComponentContext();
16855
+ const { BaseImage: BaseImage$1 = BaseImage, LoadingIndicator: LoadingIndicator$1 = LoadingIndicator } = WithAudioPlayback.useComponentContext();
16875
16856
  const [thumbnailPreviewError, setThumbnailPreviewError] = React.useState(false);
16876
16857
  const { id, uploadPermissionCheck, uploadState } = attachment.localMetadata ?? {};
16877
16858
  const isUploading = uploadState === "uploading";
@@ -16922,7 +16903,7 @@ const MediaAttachmentPreview = ({
16922
16903
  }
16923
16904
  ),
16924
16905
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx("str-chat__attachment-preview-media__overlay"), children: [
16925
- isUploading && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator2, {}),
16906
+ isUploading && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator$1, { "data-testid": "loading-indicator" }),
16926
16907
  streamChat.isVideoAttachment(attachment) && !hasUploadError && uploadState !== "uploading" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-media__video-indicator", children: [
16927
16908
  /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconVideoFill, {}),
16928
16909
  attachment.duration && /* @__PURE__ */ jsxRuntime.jsx("div", { children: attachment.duration })
@@ -17473,7 +17454,7 @@ const CommandChip = ({ command }) => {
17473
17454
  const { textareaRef } = WithAudioPlayback.useMessageComposerContext();
17474
17455
  if (!command) return null;
17475
17456
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__command-chip", children: [
17476
- /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconThunder, {}),
17457
+ /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconBolt, {}),
17477
17458
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: command.name }),
17478
17459
  /* @__PURE__ */ jsxRuntime.jsx(
17479
17460
  "button",
@@ -18778,7 +18759,7 @@ const MessageComposerPreviews = () => {
18778
18759
  {
18779
18760
  message: editedMessage,
18780
18761
  onCancel: () => {
18781
- messageComposer.clear();
18762
+ restorePreEditSnapshot(messageComposer);
18782
18763
  }
18783
18764
  }
18784
18765
  ) }) : /* @__PURE__ */ jsxRuntime.jsx(QuotedMessagePreview$1, {}),
@@ -19014,8 +18995,7 @@ const getGroupChannelDisplayInfo = (channel) => {
19014
18995
  memberList.push({ imageUrl: user.image, userName: user.name });
19015
18996
  }
19016
18997
  return {
19017
- members: memberList,
19018
- overflowCount: memberList.length > 4 ? memberList.length - 2 : void 0
18998
+ members: memberList
19019
18999
  };
19020
19000
  };
19021
19001
  function computeChannelDisplayName(channel, directMessageLabel) {
@@ -19221,7 +19201,7 @@ const useChat = ({
19221
19201
  };
19222
19202
  React.useEffect(() => {
19223
19203
  if (!client) return;
19224
- const version = "14.0.0-beta.4";
19204
+ const version = "14.0.0-beta.6";
19225
19205
  const userAgent = client.getUserAgent();
19226
19206
  if (!userAgent.includes("stream-chat-react")) {
19227
19207
  client.setUserAgent(`stream-chat-react-${version}-${userAgent}`);
@@ -19355,7 +19335,7 @@ const ThreadHeaderSubtitle = ({
19355
19335
  ) });
19356
19336
  };
19357
19337
  const ThreadHeader = (props) => {
19358
- const { closeThread, MenuIcon = WithAudioPlayback.IconLayoutAlignLeft, overrideTitle, thread } = props;
19338
+ const { closeThread, MenuIcon = WithAudioPlayback.IconSidebar, overrideTitle, thread } = props;
19359
19339
  const { t } = WithAudioPlayback.useTranslationContext();
19360
19340
  const { channel } = WithAudioPlayback.useChannelStateContext();
19361
19341
  const { activeChatView } = WithAudioPlayback.useChatViewContext();
@@ -19365,7 +19345,7 @@ const ThreadHeader = (props) => {
19365
19345
  const replyCount = threadInstance ? replyCountThreadInstance : thread ? thread.reply_count ?? 0 : 0;
19366
19346
  const threadDisplayName = overrideTitle ?? channelDisplayTitle ?? displayNameFromParentMessage(thread) ?? void 0;
19367
19347
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__thread-header", children: [
19368
- activeChatView === "threads" && /* @__PURE__ */ jsxRuntime.jsx(ToggleSidebarButton, { canCollapse: !!threadInstance, mode: "expand", children: /* @__PURE__ */ jsxRuntime.jsx(MenuIcon, {}) }),
19348
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__thread-header__start", children: activeChatView === "threads" && /* @__PURE__ */ jsxRuntime.jsx(ToggleSidebarButton, { canCollapse: !!threadInstance, mode: "expand", children: /* @__PURE__ */ jsxRuntime.jsx(MenuIcon, {}) }) }),
19369
19349
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__thread-header-details", children: [
19370
19350
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__thread-header-title", children: t("Thread") }),
19371
19351
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -19377,7 +19357,7 @@ const ThreadHeader = (props) => {
19377
19357
  }
19378
19358
  )
19379
19359
  ] }),
19380
- !threadInstance && /* @__PURE__ */ jsxRuntime.jsx(
19360
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__thread-header__end", children: !threadInstance && /* @__PURE__ */ jsxRuntime.jsx(
19381
19361
  WithAudioPlayback.Button,
19382
19362
  {
19383
19363
  appearance: "ghost",
@@ -19390,7 +19370,7 @@ const ThreadHeader = (props) => {
19390
19370
  variant: "secondary",
19391
19371
  children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconXmark, {})
19392
19372
  }
19393
- )
19373
+ ) })
19394
19374
  ] });
19395
19375
  };
19396
19376
  const threadStateSelector = ({ replyCount }) => ({
@@ -19980,6 +19960,7 @@ const DefaultMessageActionComponents = {
19980
19960
  className: msgActionsBoxButtonClassName,
19981
19961
  Icon: WithAudioPlayback.IconEdit,
19982
19962
  onClick: () => {
19963
+ savePreEditSnapshot(messageComposer);
19983
19964
  messageComposer.initState({ composition: message });
19984
19965
  closeMenu();
19985
19966
  },
@@ -20355,9 +20336,9 @@ function MessageReactionsDetail({
20355
20336
  handleFetchReactions,
20356
20337
  onSelectedReactionTypeChange,
20357
20338
  reactionDetailsSort: propReactionDetailsSort,
20339
+ reactionGroups,
20358
20340
  reactions,
20359
20341
  selectedReactionType,
20360
- sortReactionDetails: propSortReactionDetails,
20361
20342
  totalReactionCount
20362
20343
  }) {
20363
20344
  const { client } = WithAudioPlayback.useChatContext();
@@ -20369,10 +20350,8 @@ function MessageReactionsDetail({
20369
20350
  const { t } = WithAudioPlayback.useTranslationContext();
20370
20351
  const {
20371
20352
  handleReaction: contextHandleReaction,
20372
- reactionDetailsSort: contextReactionDetailsSort,
20373
- sortReactionDetails: contextSortReactionDetails
20353
+ reactionDetailsSort: contextReactionDetailsSort
20374
20354
  } = useMessageContext(MessageReactionsDetail.name);
20375
- const legacySortReactionDetails = propSortReactionDetails ?? contextSortReactionDetails;
20376
20355
  const reactionDetailsSort = propReactionDetailsSort ?? contextReactionDetailsSort ?? defaultReactionDetailsSort;
20377
20356
  const {
20378
20357
  isLoading: areReactionsLoading,
@@ -20384,10 +20363,6 @@ function MessageReactionsDetail({
20384
20363
  shouldFetch: true,
20385
20364
  sort: reactionDetailsSort
20386
20365
  });
20387
- const reactionDetailsWithLegacyFallback = React.useMemo(
20388
- () => legacySortReactionDetails ? [...reactionDetails].sort(legacySortReactionDetails) : reactionDetails,
20389
- [legacySortReactionDetails, reactionDetails]
20390
- );
20391
20366
  return /* @__PURE__ */ jsxRuntime.jsxs(
20392
20367
  "div",
20393
20368
  {
@@ -20432,7 +20407,7 @@ function MessageReactionsDetail({
20432
20407
  "data-testid": "all-reacting-users",
20433
20408
  children: [
20434
20409
  areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator2, {}),
20435
- !areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: reactionDetailsWithLegacyFallback.map(({ type, user }) => {
20410
+ !areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: reactionDetails.map(({ type, user }) => {
20436
20411
  const belongsToCurrentUser = client.user?.id === user?.id;
20437
20412
  const EmojiComponent = Array.isArray(reactionOptions) ? void 0 : reactionOptions.quick[type]?.Component ?? reactionOptions.extended?.[type]?.Component;
20438
20413
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -20465,8 +20440,13 @@ function MessageReactionsDetail({
20465
20440
  className: "str-chat__message-reactions-detail__user-list-item-button",
20466
20441
  "data-testid": "remove-reaction-button",
20467
20442
  onClick: async (e) => {
20443
+ const reactionCountBeforeRemoval = reactionGroups?.[type]?.count ?? 0;
20468
20444
  await contextHandleReaction(type, e);
20469
- refetch();
20445
+ if (reactionCountBeforeRemoval <= 1) {
20446
+ onSelectedReactionTypeChange?.(null);
20447
+ } else {
20448
+ refetch();
20449
+ }
20470
20450
  },
20471
20451
  children: t("Tap to remove")
20472
20452
  }
@@ -20495,17 +20475,15 @@ const useProcessReactions = (params) => {
20495
20475
  const {
20496
20476
  own_reactions: propOwnReactions,
20497
20477
  reaction_groups: propReactionGroups,
20498
- reactionOptions: propReactionOptions,
20499
20478
  reactions: propReactions,
20500
20479
  sortReactions: propSortReactions
20501
20480
  } = params;
20502
20481
  const { message, sortReactions: contextSortReactions } = useMessageContext();
20503
- const { reactionOptions: contextReactionOptions = defaultReactionOptions } = WithAudioPlayback.useComponentContext();
20504
- const reactionOptions = propReactionOptions ?? contextReactionOptions;
20482
+ const { reactionOptions = defaultReactionOptions } = WithAudioPlayback.useComponentContext();
20505
20483
  const sortReactions = propSortReactions ?? contextSortReactions ?? defaultReactionsSort;
20506
- const latestReactions = propReactions || message.latest_reactions;
20507
- const ownReactions = propOwnReactions || message?.own_reactions;
20508
- const reactionGroups = propReactionGroups || message?.reaction_groups;
20484
+ const latestReactions = propReactions ?? message.latest_reactions;
20485
+ const ownReactions = propOwnReactions ?? message?.own_reactions;
20486
+ const reactionGroups = propReactionGroups ?? message?.reaction_groups ?? void 0;
20509
20487
  const isOwnReaction = React.useCallback(
20510
20488
  (reactionType) => ownReactions?.some((reaction) => reaction.type === reactionType) ?? false,
20511
20489
  [ownReactions]
@@ -20589,6 +20567,7 @@ const useProcessReactions = (params) => {
20589
20567
  return {
20590
20568
  existingReactions,
20591
20569
  hasReactions,
20570
+ reactionGroups,
20592
20571
  totalReactionCount,
20593
20572
  uniqueReactionTypeCount
20594
20573
  };
@@ -20605,16 +20584,22 @@ const FragmentOrButton = ({
20605
20584
  };
20606
20585
  const UnMemoizedMessageReactions = (props) => {
20607
20586
  const {
20587
+ capLimit: { clustered: capLimitClustered = 5, segmented: capLimitSegmented = 4 } = {},
20608
20588
  flipHorizontalPosition = false,
20609
20589
  handleFetchReactions,
20610
20590
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
20611
20591
  reactionDetailsSort,
20612
- sortReactionDetails,
20613
20592
  verticalPosition = "top",
20614
20593
  visualStyle = "clustered",
20615
20594
  ...rest
20616
20595
  } = props;
20617
- const { existingReactions, hasReactions, totalReactionCount, uniqueReactionTypeCount } = useProcessReactions(rest);
20596
+ const {
20597
+ existingReactions,
20598
+ hasReactions,
20599
+ reactionGroups,
20600
+ totalReactionCount,
20601
+ uniqueReactionTypeCount
20602
+ } = useProcessReactions(rest);
20618
20603
  const [selectedReactionType, setSelectedReactionType] = React.useState(
20619
20604
  null
20620
20605
  );
@@ -20633,16 +20618,27 @@ const UnMemoizedMessageReactions = (props) => {
20633
20618
  dialog.open();
20634
20619
  };
20635
20620
  const cappedExistingReactions = React.useMemo(() => {
20636
- if (visualStyle !== "segmented" || verticalPosition !== "top") return null;
20637
- const sliced = existingReactions.slice(0, 4);
20621
+ if (visualStyle === "segmented" && verticalPosition !== "top") return null;
20622
+ const capLimit = visualStyle === "segmented" ? capLimitSegmented : capLimitClustered;
20623
+ const sliced = existingReactions.slice(0, capLimit);
20638
20624
  return {
20625
+ /**
20626
+ * Accumulated reaction count of capped reaction types, first four in case of
20627
+ * segmented(top) and first five in case of clustered(top/bottom) variations.
20628
+ */
20639
20629
  reactionCountToDisplay: sliced.reduce(
20640
20630
  (accumulatedCount, { reactionCount }) => accumulatedCount + reactionCount,
20641
20631
  0
20642
20632
  ),
20643
20633
  reactionsToDisplay: sliced
20644
20634
  };
20645
- }, [existingReactions, verticalPosition, visualStyle]);
20635
+ }, [
20636
+ capLimitClustered,
20637
+ capLimitSegmented,
20638
+ existingReactions,
20639
+ verticalPosition,
20640
+ visualStyle
20641
+ ]);
20646
20642
  if (!hasReactions) return null;
20647
20643
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
20648
20644
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -20663,7 +20659,7 @@ const UnMemoizedMessageReactions = (props) => {
20663
20659
  "aria-pressed": isDialogOpen,
20664
20660
  buttonIf: visualStyle === "clustered",
20665
20661
  className: "str-chat__message-reactions__list-button",
20666
- onClick: () => handleReactionButtonClick(existingReactions[0]?.reactionType ?? null),
20662
+ onClick: () => handleReactionButtonClick(null),
20667
20663
  children: [
20668
20664
  /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "str-chat__message-reactions__list", children: [
20669
20665
  (cappedExistingReactions?.reactionsToDisplay ?? existingReactions).map(
@@ -20694,7 +20690,7 @@ const UnMemoizedMessageReactions = (props) => {
20694
20690
  reactionType
20695
20691
  )
20696
20692
  ),
20697
- uniqueReactionTypeCount > 4 && cappedExistingReactions && /* @__PURE__ */ jsxRuntime.jsx("li", { className: "str-chat__message-reactions__list-item str-chat__message-reactions__list-item--more", children: /* @__PURE__ */ jsxRuntime.jsx(
20693
+ uniqueReactionTypeCount > 4 && cappedExistingReactions && visualStyle === "segmented" && /* @__PURE__ */ jsxRuntime.jsx("li", { className: "str-chat__message-reactions__list-item str-chat__message-reactions__list-item--more", children: /* @__PURE__ */ jsxRuntime.jsx(
20698
20694
  "button",
20699
20695
  {
20700
20696
  className: "str-chat__message-reactions__list-item-button",
@@ -20727,9 +20723,9 @@ const UnMemoizedMessageReactions = (props) => {
20727
20723
  {
20728
20724
  handleFetchReactions,
20729
20725
  onSelectedReactionTypeChange: setSelectedReactionType,
20726
+ reactionGroups,
20730
20727
  reactions: existingReactions,
20731
20728
  selectedReactionType,
20732
- sortReactionDetails,
20733
20729
  totalReactionCount
20734
20730
  }
20735
20731
  )
@@ -21210,7 +21206,6 @@ const Message = (props) => {
21210
21206
  pinPermissions,
21211
21207
  reactionDetailsSort,
21212
21208
  retrySendMessage: propRetrySendMessage,
21213
- sortReactionDetails,
21214
21209
  sortReactions
21215
21210
  } = props;
21216
21211
  const { client } = WithAudioPlayback.useChatContext("Message");
@@ -21304,7 +21299,6 @@ const Message = (props) => {
21304
21299
  readBy: props.readBy,
21305
21300
  renderText: props.renderText,
21306
21301
  returnAllReadData: props.returnAllReadData,
21307
- sortReactionDetails,
21308
21302
  sortReactions,
21309
21303
  threadList: props.threadList,
21310
21304
  unsafeHTML: props.unsafeHTML,
@@ -22350,7 +22344,6 @@ const InfiniteScroll = (props) => {
22350
22344
  children
22351
22345
  ] });
22352
22346
  };
22353
- const MAX_AVATARS = 3;
22354
22347
  const UnMemoizedTypingIndicator = (props) => {
22355
22348
  const { isMessageListScrolledToBottom = true, scrollToBottom, threadList } = props;
22356
22349
  const { channelConfig, thread } = WithAudioPlayback.useChannelStateContext("TypingIndicator");
@@ -22367,11 +22360,16 @@ const UnMemoizedTypingIndicator = (props) => {
22367
22360
  const typingUsers = threadList ? typingInThread : typingInChannel;
22368
22361
  const { displayUsers } = useDebouncedTypingActive(typingUsers);
22369
22362
  const showIndicator = displayUsers.length > 0;
22370
- const displayInfo = displayUsers.slice(0, MAX_AVATARS).map(({ user }) => ({
22371
- id: user?.id,
22372
- imageUrl: user?.image,
22373
- userName: user?.name ?? ""
22374
- }));
22363
+ const displayInfo = React.useMemo(
22364
+ () => displayUsers.map(
22365
+ ({ user }) => ({
22366
+ id: user?.id,
22367
+ imageUrl: user?.image,
22368
+ userName: user?.name
22369
+ })
22370
+ ),
22371
+ [displayUsers]
22372
+ );
22375
22373
  React.useEffect(() => {
22376
22374
  if (showIndicator && isMessageListScrolledToBottom) scrollToBottom();
22377
22375
  }, [scrollToBottom, isMessageListScrolledToBottom, showIndicator]);
@@ -22381,7 +22379,6 @@ const UnMemoizedTypingIndicator = (props) => {
22381
22379
  if (!showIndicator || !isMessageListScrolledToBottom) {
22382
22380
  return null;
22383
22381
  }
22384
- const overflowCount = displayUsers.length > MAX_AVATARS ? displayUsers.length - MAX_AVATARS : 0;
22385
22382
  return /* @__PURE__ */ jsxRuntime.jsxs(
22386
22383
  "div",
22387
22384
  {
@@ -22394,15 +22391,7 @@ const UnMemoizedTypingIndicator = (props) => {
22394
22391
  ),
22395
22392
  "data-testid": "typing-indicator",
22396
22393
  children: [
22397
- displayInfo.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
22398
- AvatarStack,
22399
- {
22400
- badgeSize: "md",
22401
- displayInfo,
22402
- overflowCount: overflowCount > 0 ? overflowCount : void 0,
22403
- size: "md"
22404
- }
22405
- ),
22394
+ displayInfo.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(AvatarStack, { badgeSize: "md", displayInfo, size: "md" }),
22406
22395
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__typing-indicator__bubble", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__typing-indicator__dots", children: /* @__PURE__ */ jsxRuntime.jsx(TypingIndicatorDots, {}) }) })
22407
22396
  ]
22408
22397
  }
@@ -22933,7 +22922,6 @@ const MessageListWithContext = (props) => {
22933
22922
  returnAllReadData = false,
22934
22923
  reviewProcessedMessage,
22935
22924
  showUnreadNotificationAlways,
22936
- sortReactionDetails,
22937
22925
  sortReactions,
22938
22926
  suppressAutoscroll,
22939
22927
  threadList = false,
@@ -23051,7 +23039,6 @@ const MessageListWithContext = (props) => {
23051
23039
  renderText: props.renderText,
23052
23040
  retrySendMessage: props.retrySendMessage,
23053
23041
  showAvatar: props.showAvatar,
23054
- sortReactionDetails,
23055
23042
  sortReactions,
23056
23043
  unsafeHTML
23057
23044
  },
@@ -23346,7 +23333,6 @@ const messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
23346
23333
  renderText: renderText2,
23347
23334
  returnAllReadData,
23348
23335
  showAvatar,
23349
- sortReactionDetails,
23350
23336
  sortReactions,
23351
23337
  threadList,
23352
23338
  unreadMessageCount = 0,
@@ -23396,7 +23382,6 @@ const messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
23396
23382
  renderText: renderText2,
23397
23383
  returnAllReadData,
23398
23384
  showAvatar,
23399
- sortReactionDetails,
23400
23385
  sortReactions,
23401
23386
  threadList
23402
23387
  }
@@ -23481,7 +23466,6 @@ const VirtualizedMessageListWithContext = (props) => {
23481
23466
  shouldGroupByUser = false,
23482
23467
  showAvatar,
23483
23468
  showUnreadNotificationAlways,
23484
- sortReactionDetails,
23485
23469
  sortReactions,
23486
23470
  stickToBottomScrollBehavior = "smooth",
23487
23471
  suppressAutoscroll,
@@ -23750,7 +23734,6 @@ const VirtualizedMessageListWithContext = (props) => {
23750
23734
  returnAllReadData,
23751
23735
  shouldGroupByUser,
23752
23736
  showAvatar,
23753
- sortReactionDetails,
23754
23737
  sortReactions,
23755
23738
  threadList,
23756
23739
  unreadMessageCount: channelUnreadUiState?.unread_messages,
@@ -25089,7 +25072,7 @@ const LoadMorePaginator = React.memo(
25089
25072
  UnMemoizedLoadMorePaginator
25090
25073
  );
25091
25074
  const ChannelListHeader = ({
25092
- ToggleButtonIcon = WithAudioPlayback.IconLayoutAlignLeft
25075
+ ToggleButtonIcon = WithAudioPlayback.IconSidebar
25093
25076
  }) => {
25094
25077
  const { t } = WithAudioPlayback.useTranslationContext();
25095
25078
  const { channel, navOpen } = WithAudioPlayback.useChatContext();
@@ -25261,11 +25244,11 @@ const UnMemoizedChannelList = (props) => {
25261
25244
  }
25262
25245
  );
25263
25246
  const showChannelList = !searchIsActive;
25264
- return /* @__PURE__ */ jsxRuntime.jsx(DialogManagerProvider, { id: `channel-list-dialog-manager-${stableId}`, children: /* @__PURE__ */ jsxRuntime.jsx(
25247
+ return /* @__PURE__ */ jsxRuntime.jsx(
25265
25248
  WithAudioPlayback.ChannelListContextProvider,
25266
25249
  {
25267
25250
  value: { channels, hasNextPage, loadNextPage, setChannels },
25268
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className, ref: channelListRef, children: [
25251
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, ref: channelListRef, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogManagerProvider, { id: `channel-list-dialog-manager-${stableId}`, children: [
25269
25252
  /* @__PURE__ */ jsxRuntime.jsx(ChannelListHeader, {}),
25270
25253
  showChannelSearch && /* @__PURE__ */ jsxRuntime.jsx(Search$12, {}),
25271
25254
  showChannelList && /* @__PURE__ */ jsxRuntime.jsx(
@@ -25287,9 +25270,9 @@ const UnMemoizedChannelList = (props) => {
25287
25270
  }
25288
25271
  ),
25289
25272
  /* @__PURE__ */ jsxRuntime.jsx(NotificationList$1, { panel: "channel-list" })
25290
- ] })
25273
+ ] }) })
25291
25274
  }
25292
- ) });
25275
+ );
25293
25276
  };
25294
25277
  const ChannelList = React.memo(
25295
25278
  UnMemoizedChannelList
@@ -26016,11 +25999,13 @@ function ChannelListItemTimestamp({ lastMessage }) {
26016
25999
  function getAttachmentContentType(attachment) {
26017
26000
  if (!attachment) return "text";
26018
26001
  if (attachment.type === "giphy") return "giphy";
26019
- if (attachment.type === "image") return "image";
26002
+ if (attachment.type === "image") {
26003
+ if (attachment.og_scrape_url || attachment.title_link) return "link";
26004
+ return "image";
26005
+ }
26020
26006
  if (attachment.type === "video") return "video";
26021
26007
  if (attachment.type === "voiceRecording") return "voice";
26022
26008
  if (attachment.type === "file") return "file";
26023
- if (attachment.og_scrape_url || attachment.title_link) return "link";
26024
26009
  return "file";
26025
26010
  }
26026
26011
  function getAttachmentFallbackText(type, count, t) {
@@ -26100,13 +26085,13 @@ const useLatestMessagePreview = ({
26100
26085
  } else {
26101
26086
  contentType = "file";
26102
26087
  }
26103
- let text2 = contentType === "giphy" ? "Giphy" : (
26088
+ let text2 = contentType === "giphy" ? `GIPHY ${firstAttachment.title ?? ""}`.trim() : (
26104
26089
  // prioritize message text content if available
26105
26090
  textContent || // then fallback text of the single attachment if only one attachment is present and it's not a voice recording (fallback text is generic for voice recordings, so not useful in the preview)
26106
26091
  (attachments.length === 1 && contentType !== "voice" ? firstAttachment.fallback || firstAttachment.title : "") || // then generic fallback text based on attachment type and count
26107
26092
  getAttachmentFallbackText(contentType, attachments.length, t)
26108
26093
  );
26109
- if (contentType !== "giphy" && attachments.length === 1 && typeof firstAttachment.duration === "number") {
26094
+ if (attachments.length === 1 && typeof firstAttachment.duration === "number") {
26110
26095
  const minutes = Math.floor(firstAttachment.duration / 60);
26111
26096
  const seconds = Math.ceil(firstAttachment.duration) % 60;
26112
26097
  const durationString = `${minutes}:${seconds.toString().padStart(2, "0")}`;
@@ -26147,7 +26132,7 @@ const contentTypeIconMap = {
26147
26132
  deleted: WithAudioPlayback.IconNoSign,
26148
26133
  error: WithAudioPlayback.IconExclamationCircleFill,
26149
26134
  file: WithAudioPlayback.IconFile,
26150
- giphy: WithAudioPlayback.IconFile,
26135
+ giphy: WithAudioPlayback.IconGiphy,
26151
26136
  image: WithAudioPlayback.IconCamera,
26152
26137
  link: WithAudioPlayback.IconLink,
26153
26138
  location: WithAudioPlayback.IconLocation,
@@ -26249,7 +26234,6 @@ const UnMemoizedChannelListItemUI = (props) => {
26249
26234
  {
26250
26235
  displayMembers: groupChannelDisplayInfo?.members,
26251
26236
  imageUrl: displayImage,
26252
- overflowCount: groupChannelDisplayInfo?.overflowCount,
26253
26237
  size: "xl",
26254
26238
  userName: avatarName
26255
26239
  }
@@ -26795,7 +26779,7 @@ const ThreadListLoadingIndicator = () => {
26795
26779
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__thread-list-loading-indicator", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator$1, {}) });
26796
26780
  };
26797
26781
  const ThreadListHeader = ({
26798
- ToggleButtonIcon = WithAudioPlayback.IconLayoutAlignLeft
26782
+ ToggleButtonIcon = WithAudioPlayback.IconSidebar
26799
26783
  }) => {
26800
26784
  const { t } = WithAudioPlayback.useTranslationContext();
26801
26785
  const { navOpen } = WithAudioPlayback.useChatContext();
@@ -26928,10 +26912,9 @@ const ThreadList = ({ virtuosoProps }) => {
26928
26912
  const IconsBySeverity = {
26929
26913
  error: WithAudioPlayback.IconExclamationMark,
26930
26914
  info: null,
26931
- // IconInfo,
26932
26915
  loading: WithAudioPlayback.IconRefresh,
26933
26916
  success: WithAudioPlayback.IconCheckmark,
26934
- warning: WithAudioPlayback.IconExclamationTriangle
26917
+ warning: WithAudioPlayback.IconExclamationTriangleFill
26935
26918
  };
26936
26919
  const DefaultNotificationIcon = ({ notification }) => {
26937
26920
  if (!notification.severity) return null;
@@ -27769,7 +27752,7 @@ const Giphy = ({ attachment }) => {
27769
27752
  ] });
27770
27753
  };
27771
27754
  const GiphyBadge = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__giphy-badge", children: [
27772
- /* @__PURE__ */ jsxRuntime.jsx(IconGiphy, {}),
27755
+ /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconGiphy, {}),
27773
27756
  "Giphy"
27774
27757
  ] });
27775
27758
  const Geolocation = ({
@@ -27871,7 +27854,7 @@ const UnsupportedAttachment = ({ attachment }) => {
27871
27854
  const VisibilityDisclaimer = () => {
27872
27855
  const { t } = WithAudioPlayback.useTranslationContext();
27873
27856
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__visibility-disclaimer", children: [
27874
- /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconEyeOpen, {}),
27857
+ /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconEyeFill, {}),
27875
27858
  t("Only visible to you")
27876
27859
  ] });
27877
27860
  };
@@ -28304,7 +28287,7 @@ const ChannelHeader = (props) => {
28304
28287
  const {
28305
28288
  Avatar: Avatar2 = ChannelAvatar,
28306
28289
  image: overrideImage,
28307
- MenuIcon = WithAudioPlayback.IconLayoutAlignLeft,
28290
+ MenuIcon = WithAudioPlayback.IconSidebar,
28308
28291
  title: overrideTitle
28309
28292
  } = props;
28310
28293
  const { channel } = WithAudioPlayback.useChannelStateContext();
@@ -28321,22 +28304,21 @@ const ChannelHeader = (props) => {
28321
28304
  "str-chat__channel-header--sidebar-collapsed": !navOpen
28322
28305
  }),
28323
28306
  children: [
28324
- /* @__PURE__ */ jsxRuntime.jsx(ToggleSidebarButton, { mode: "expand", children: /* @__PURE__ */ jsxRuntime.jsx(MenuIcon, {}) }),
28307
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__channel-header__start", children: /* @__PURE__ */ jsxRuntime.jsx(ToggleSidebarButton, { mode: "expand", children: /* @__PURE__ */ jsxRuntime.jsx(MenuIcon, {}) }) }),
28325
28308
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__channel-header__data", children: [
28326
28309
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__channel-header__data__title", children: displayTitle }),
28327
28310
  /* @__PURE__ */ jsxRuntime.jsx(ChannelHeaderSubtitle, {})
28328
28311
  ] }),
28329
- /* @__PURE__ */ jsxRuntime.jsx(
28312
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__channel-header__end", children: /* @__PURE__ */ jsxRuntime.jsx(
28330
28313
  Avatar2,
28331
28314
  {
28332
28315
  className: "str-chat__avatar--channel-header",
28333
28316
  displayMembers: groupChannelDisplayInfo?.members,
28334
28317
  imageUrl: displayImage,
28335
- overflowCount: groupChannelDisplayInfo?.overflowCount,
28336
28318
  size: "lg",
28337
28319
  userName: displayTitle
28338
28320
  }
28339
- )
28321
+ ) })
28340
28322
  ]
28341
28323
  }
28342
28324
  );
@@ -28379,15 +28361,13 @@ exports.IconArchive = WithAudioPlayback.IconArchive;
28379
28361
  exports.IconArrowDown = WithAudioPlayback.IconArrowDown;
28380
28362
  exports.IconArrowDownCircle = WithAudioPlayback.IconArrowDownCircle;
28381
28363
  exports.IconArrowLeft = WithAudioPlayback.IconArrowLeft;
28382
- exports.IconArrowRight = WithAudioPlayback.IconArrowRight;
28383
28364
  exports.IconArrowUp = WithAudioPlayback.IconArrowUp;
28384
28365
  exports.IconArrowUpRight = WithAudioPlayback.IconArrowUpRight;
28385
28366
  exports.IconAttachment = WithAudioPlayback.IconAttachment;
28386
28367
  exports.IconAudio = WithAudioPlayback.IconAudio;
28387
28368
  exports.IconBell = WithAudioPlayback.IconBell;
28388
28369
  exports.IconBellOff = WithAudioPlayback.IconBellOff;
28389
- exports.IconBubble3ChatMessage = WithAudioPlayback.IconBubble3ChatMessage;
28390
- exports.IconBubbleText6SolidChatMessage = WithAudioPlayback.IconBubbleText6SolidChatMessage;
28370
+ exports.IconBolt = WithAudioPlayback.IconBolt;
28391
28371
  exports.IconCamera = WithAudioPlayback.IconCamera;
28392
28372
  exports.IconCheckmark = WithAudioPlayback.IconCheckmark;
28393
28373
  exports.IconCheckmark1Small = WithAudioPlayback.IconCheckmark1Small;
@@ -28398,31 +28378,26 @@ exports.IconChevronRight = WithAudioPlayback.IconChevronRight;
28398
28378
  exports.IconClock = WithAudioPlayback.IconClock;
28399
28379
  exports.IconCommand = WithAudioPlayback.IconCommand;
28400
28380
  exports.IconCopy = WithAudioPlayback.IconCopy;
28401
- exports.IconCrossSmall = WithAudioPlayback.IconCrossSmall;
28402
28381
  exports.IconDelete = WithAudioPlayback.IconDelete;
28403
28382
  exports.IconEdit = WithAudioPlayback.IconEdit;
28404
28383
  exports.IconEmoji = WithAudioPlayback.IconEmoji;
28405
28384
  exports.IconExclamationCircleFill = WithAudioPlayback.IconExclamationCircleFill;
28406
28385
  exports.IconExclamationMark = WithAudioPlayback.IconExclamationMark;
28407
28386
  exports.IconExclamationMarkFill = WithAudioPlayback.IconExclamationMarkFill;
28408
- exports.IconExclamationTriangle = WithAudioPlayback.IconExclamationTriangle;
28409
- exports.IconEyeOpen = WithAudioPlayback.IconEyeOpen;
28387
+ exports.IconExclamationTriangleFill = WithAudioPlayback.IconExclamationTriangleFill;
28388
+ exports.IconEyeFill = WithAudioPlayback.IconEyeFill;
28410
28389
  exports.IconFile = WithAudioPlayback.IconFile;
28411
28390
  exports.IconFlag = WithAudioPlayback.IconFlag;
28391
+ exports.IconGiphy = WithAudioPlayback.IconGiphy;
28412
28392
  exports.IconImage = WithAudioPlayback.IconImage;
28413
- exports.IconInfo = WithAudioPlayback.IconInfo;
28414
- exports.IconLayoutAlignLeft = WithAudioPlayback.IconLayoutAlignLeft;
28415
28393
  exports.IconLeave = WithAudioPlayback.IconLeave;
28416
- exports.IconLightBulbSimple = WithAudioPlayback.IconLightBulbSimple;
28417
28394
  exports.IconLink = WithAudioPlayback.IconLink;
28418
28395
  exports.IconLoading = WithAudioPlayback.IconLoading;
28419
28396
  exports.IconLocation = WithAudioPlayback.IconLocation;
28420
28397
  exports.IconMessageBubble = WithAudioPlayback.IconMessageBubble;
28421
28398
  exports.IconMessageBubbleFill = WithAudioPlayback.IconMessageBubbleFill;
28422
28399
  exports.IconMessageBubbles = WithAudioPlayback.IconMessageBubbles;
28423
- exports.IconMinus = WithAudioPlayback.IconMinus;
28424
28400
  exports.IconMinusCircle = WithAudioPlayback.IconMinusCircle;
28425
- exports.IconMinusSmall = WithAudioPlayback.IconMinusSmall;
28426
28401
  exports.IconMore = WithAudioPlayback.IconMore;
28427
28402
  exports.IconMute = WithAudioPlayback.IconMute;
28428
28403
  exports.IconNoSign = WithAudioPlayback.IconNoSign;
@@ -28441,10 +28416,9 @@ exports.IconRetry = WithAudioPlayback.IconRetry;
28441
28416
  exports.IconSave = WithAudioPlayback.IconSave;
28442
28417
  exports.IconSearch = WithAudioPlayback.IconSearch;
28443
28418
  exports.IconSend = WithAudioPlayback.IconSend;
28444
- exports.IconSettingsGear2 = WithAudioPlayback.IconSettingsGear2;
28419
+ exports.IconSidebar = WithAudioPlayback.IconSidebar;
28445
28420
  exports.IconThread = WithAudioPlayback.IconThread;
28446
28421
  exports.IconThreadFill = WithAudioPlayback.IconThreadFill;
28447
- exports.IconThunder = WithAudioPlayback.IconThunder;
28448
28422
  exports.IconTranslate = WithAudioPlayback.IconTranslate;
28449
28423
  exports.IconTrophy = WithAudioPlayback.IconTrophy;
28450
28424
  exports.IconUnpin = WithAudioPlayback.IconUnpin;
@@ -28457,9 +28431,9 @@ exports.IconUserRemove = WithAudioPlayback.IconUserRemove;
28457
28431
  exports.IconVideo = WithAudioPlayback.IconVideo;
28458
28432
  exports.IconVideoFill = WithAudioPlayback.IconVideoFill;
28459
28433
  exports.IconVoice = WithAudioPlayback.IconVoice;
28460
- exports.IconVoiceFill = WithAudioPlayback.IconVoiceFill;
28461
28434
  exports.IconXCircle = WithAudioPlayback.IconXCircle;
28462
28435
  exports.IconXmark = WithAudioPlayback.IconXmark;
28436
+ exports.IconXmarkSmall = WithAudioPlayback.IconXmarkSmall;
28463
28437
  exports.LoadingChannel = WithAudioPlayback.LoadingChannel;
28464
28438
  exports.LoadingErrorIndicator = WithAudioPlayback.LoadingErrorIndicator;
28465
28439
  exports.MESSAGE_ACTIONS = WithAudioPlayback.MESSAGE_ACTIONS;
@@ -28625,7 +28599,6 @@ exports.GiphyPreviewMessage = GiphyPreviewMessage;
28625
28599
  exports.GlobalModal = GlobalModal;
28626
28600
  exports.GroupAvatar = GroupAvatar;
28627
28601
  exports.Header = Header$1;
28628
- exports.IconGiphy = IconGiphy;
28629
28602
  exports.ImageComponent = ImageComponent;
28630
28603
  exports.ImageContainer = ImageContainer;
28631
28604
  exports.ImagePlaceholder = ImagePlaceholder;