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

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 (54) hide show
  1. package/dist/cjs/{WithAudioPlayback.236d404c.js → WithAudioPlayback.0c10cb67.js} +58 -90
  2. package/dist/cjs/WithAudioPlayback.0c10cb67.js.map +1 -0
  3. package/dist/cjs/emojis.js +1 -1
  4. package/dist/cjs/index.js +109 -138
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/css/index.css +72 -53
  7. package/dist/css/index.css.map +1 -1
  8. package/dist/es/{WithAudioPlayback.89700cb5.mjs → WithAudioPlayback.e7821fd4.mjs} +149 -181
  9. package/dist/es/WithAudioPlayback.e7821fd4.mjs.map +1 -0
  10. package/dist/es/emojis.mjs +1 -1
  11. package/dist/es/index.mjs +169 -198
  12. package/dist/es/index.mjs.map +1 -1
  13. package/dist/types/components/ChannelHeader/ChannelHeader.d.ts +1 -1
  14. package/dist/types/components/ChannelHeader/ChannelHeader.d.ts.map +1 -1
  15. package/dist/types/components/Dialog/service/DialogPortal.d.ts.map +1 -1
  16. package/dist/types/components/Form/SwitchField.d.ts.map +1 -1
  17. package/dist/types/components/Icons/icons.d.ts +6 -38
  18. package/dist/types/components/Icons/icons.d.ts.map +1 -1
  19. package/dist/types/components/Icons/index.d.ts +0 -1
  20. package/dist/types/components/Icons/index.d.ts.map +1 -1
  21. package/dist/types/components/Message/Message.d.ts.map +1 -1
  22. package/dist/types/components/Message/hooks/useUserRole.d.ts.map +1 -1
  23. package/dist/types/components/Message/types.d.ts +1 -5
  24. package/dist/types/components/Message/types.d.ts.map +1 -1
  25. package/dist/types/components/MessageActions/MessageActions.defaults.d.ts.map +1 -1
  26. package/dist/types/components/MessageComposer/MessageComposerUI.d.ts.map +1 -1
  27. package/dist/types/components/MessageComposer/hooks/useSubmitHandler.d.ts.map +1 -1
  28. package/dist/types/components/MessageComposer/preEditSnapshot.d.ts +16 -0
  29. package/dist/types/components/MessageComposer/preEditSnapshot.d.ts.map +1 -0
  30. package/dist/types/components/MessageList/MessageList.d.ts +1 -1
  31. package/dist/types/components/MessageList/MessageList.d.ts.map +1 -1
  32. package/dist/types/components/MessageList/VirtualizedMessageList.d.ts +1 -1
  33. package/dist/types/components/MessageList/VirtualizedMessageList.d.ts.map +1 -1
  34. package/dist/types/components/MessageList/VirtualizedMessageListComponents.d.ts.map +1 -1
  35. package/dist/types/components/Reactions/MessageReactions.d.ts +4 -16
  36. package/dist/types/components/Reactions/MessageReactions.d.ts.map +1 -1
  37. package/dist/types/components/Reactions/MessageReactionsDetail.d.ts +4 -4
  38. package/dist/types/components/Reactions/MessageReactionsDetail.d.ts.map +1 -1
  39. package/dist/types/components/Reactions/hooks/useProcessReactions.d.ts +4 -2
  40. package/dist/types/components/Reactions/hooks/useProcessReactions.d.ts.map +1 -1
  41. package/dist/types/components/Reactions/types.d.ts +0 -1
  42. package/dist/types/components/Reactions/types.d.ts.map +1 -1
  43. package/dist/types/components/SummarizedMessagePreview/SummarizedMessagePreview.d.ts.map +1 -1
  44. package/dist/types/components/SummarizedMessagePreview/hooks/useLatestMessagePreview.d.ts.map +1 -1
  45. package/dist/types/components/Thread/ThreadHeader.d.ts +1 -1
  46. package/dist/types/components/Thread/ThreadHeader.d.ts.map +1 -1
  47. package/dist/types/context/MessageBounceContext.d.ts.map +1 -1
  48. package/dist/types/context/MessageContext.d.ts +1 -5
  49. package/dist/types/context/MessageContext.d.ts.map +1 -1
  50. package/package.json +1 -1
  51. package/dist/cjs/WithAudioPlayback.236d404c.js.map +0 -1
  52. package/dist/es/WithAudioPlayback.89700cb5.mjs.map +0 -1
  53. package/dist/types/components/Icons/IconGiphy.d.ts +0 -3
  54. 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.0c10cb67.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"];
@@ -11194,6 +11172,7 @@ const useSubmitHandler = (props) => {
11194
11172
  if (messageComposer.editedMessage && localMessage.type !== "error") {
11195
11173
  try {
11196
11174
  await editMessage(localMessage, sendOptions);
11175
+ discardPreEditSnapshot(messageComposer);
11197
11176
  messageComposer.clear();
11198
11177
  } catch (err) {
11199
11178
  client.notifications.addError({
@@ -13584,15 +13563,7 @@ const SwitchField = ({
13584
13563
  ref: inputRef
13585
13564
  }
13586
13565
  ),
13587
- title ? /* @__PURE__ */ jsxRuntime.jsx(
13588
- SwitchFieldLabel,
13589
- {
13590
- description,
13591
- htmlFor: id,
13592
- onClick: () => inputRef.current?.click(),
13593
- title
13594
- }
13595
- ) : children,
13566
+ title ? /* @__PURE__ */ jsxRuntime.jsx(SwitchFieldLabel, { description, htmlFor: id, title }) : children,
13596
13567
  /* @__PURE__ */ jsxRuntime.jsx(
13597
13568
  Switch,
13598
13569
  {
@@ -14651,7 +14622,7 @@ const PollVoteTimestamp = ({ timestamp }) => {
14651
14622
  const PollVoteAuthor = ({ vote }) => {
14652
14623
  const { t } = WithAudioPlayback.useTranslationContext();
14653
14624
  const { client } = WithAudioPlayback.useChatContext();
14654
- const displayName = client.user?.id && client.user.id === vote.user?.id ? t("You") : vote.user?.name || t("Anonymous");
14625
+ const displayName = client.user?.id && client.user.id === vote.user?.id ? t("You") : vote.user?.name || vote.user?.id || t("Anonymous");
14655
14626
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__poll-vote__author", children: [
14656
14627
  vote.user && /* @__PURE__ */ jsxRuntime.jsx(
14657
14628
  Avatar,
@@ -15725,7 +15696,7 @@ const useAttachmentSelectorContext = () => React.useContext(AttachmentSelectorCo
15725
15696
  const icons = {
15726
15697
  ban: WithAudioPlayback.IconUserRemove,
15727
15698
  flag: WithAudioPlayback.IconFlag,
15728
- giphy: IconGiphy,
15699
+ giphy: WithAudioPlayback.IconGiphy,
15729
15700
  mute: WithAudioPlayback.IconMute,
15730
15701
  unban: WithAudioPlayback.IconUserAdd,
15731
15702
  unmute: WithAudioPlayback.IconAudio
@@ -17473,7 +17444,7 @@ const CommandChip = ({ command }) => {
17473
17444
  const { textareaRef } = WithAudioPlayback.useMessageComposerContext();
17474
17445
  if (!command) return null;
17475
17446
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__command-chip", children: [
17476
- /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconThunder, {}),
17447
+ /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconBolt, {}),
17477
17448
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: command.name }),
17478
17449
  /* @__PURE__ */ jsxRuntime.jsx(
17479
17450
  "button",
@@ -18778,7 +18749,7 @@ const MessageComposerPreviews = () => {
18778
18749
  {
18779
18750
  message: editedMessage,
18780
18751
  onCancel: () => {
18781
- messageComposer.clear();
18752
+ restorePreEditSnapshot(messageComposer);
18782
18753
  }
18783
18754
  }
18784
18755
  ) }) : /* @__PURE__ */ jsxRuntime.jsx(QuotedMessagePreview$1, {}),
@@ -19221,7 +19192,7 @@ const useChat = ({
19221
19192
  };
19222
19193
  React.useEffect(() => {
19223
19194
  if (!client) return;
19224
- const version = "14.0.0-beta.4";
19195
+ const version = "14.0.0-beta.5";
19225
19196
  const userAgent = client.getUserAgent();
19226
19197
  if (!userAgent.includes("stream-chat-react")) {
19227
19198
  client.setUserAgent(`stream-chat-react-${version}-${userAgent}`);
@@ -19355,7 +19326,7 @@ const ThreadHeaderSubtitle = ({
19355
19326
  ) });
19356
19327
  };
19357
19328
  const ThreadHeader = (props) => {
19358
- const { closeThread, MenuIcon = WithAudioPlayback.IconLayoutAlignLeft, overrideTitle, thread } = props;
19329
+ const { closeThread, MenuIcon = WithAudioPlayback.IconSidebar, overrideTitle, thread } = props;
19359
19330
  const { t } = WithAudioPlayback.useTranslationContext();
19360
19331
  const { channel } = WithAudioPlayback.useChannelStateContext();
19361
19332
  const { activeChatView } = WithAudioPlayback.useChatViewContext();
@@ -19365,7 +19336,7 @@ const ThreadHeader = (props) => {
19365
19336
  const replyCount = threadInstance ? replyCountThreadInstance : thread ? thread.reply_count ?? 0 : 0;
19366
19337
  const threadDisplayName = overrideTitle ?? channelDisplayTitle ?? displayNameFromParentMessage(thread) ?? void 0;
19367
19338
  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, {}) }),
19339
+ /* @__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
19340
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__thread-header-details", children: [
19370
19341
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__thread-header-title", children: t("Thread") }),
19371
19342
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -19377,7 +19348,7 @@ const ThreadHeader = (props) => {
19377
19348
  }
19378
19349
  )
19379
19350
  ] }),
19380
- !threadInstance && /* @__PURE__ */ jsxRuntime.jsx(
19351
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__thread-header__end", children: !threadInstance && /* @__PURE__ */ jsxRuntime.jsx(
19381
19352
  WithAudioPlayback.Button,
19382
19353
  {
19383
19354
  appearance: "ghost",
@@ -19390,7 +19361,7 @@ const ThreadHeader = (props) => {
19390
19361
  variant: "secondary",
19391
19362
  children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconXmark, {})
19392
19363
  }
19393
- )
19364
+ ) })
19394
19365
  ] });
19395
19366
  };
19396
19367
  const threadStateSelector = ({ replyCount }) => ({
@@ -19980,6 +19951,7 @@ const DefaultMessageActionComponents = {
19980
19951
  className: msgActionsBoxButtonClassName,
19981
19952
  Icon: WithAudioPlayback.IconEdit,
19982
19953
  onClick: () => {
19954
+ savePreEditSnapshot(messageComposer);
19983
19955
  messageComposer.initState({ composition: message });
19984
19956
  closeMenu();
19985
19957
  },
@@ -20355,9 +20327,9 @@ function MessageReactionsDetail({
20355
20327
  handleFetchReactions,
20356
20328
  onSelectedReactionTypeChange,
20357
20329
  reactionDetailsSort: propReactionDetailsSort,
20330
+ reactionGroups,
20358
20331
  reactions,
20359
20332
  selectedReactionType,
20360
- sortReactionDetails: propSortReactionDetails,
20361
20333
  totalReactionCount
20362
20334
  }) {
20363
20335
  const { client } = WithAudioPlayback.useChatContext();
@@ -20369,10 +20341,8 @@ function MessageReactionsDetail({
20369
20341
  const { t } = WithAudioPlayback.useTranslationContext();
20370
20342
  const {
20371
20343
  handleReaction: contextHandleReaction,
20372
- reactionDetailsSort: contextReactionDetailsSort,
20373
- sortReactionDetails: contextSortReactionDetails
20344
+ reactionDetailsSort: contextReactionDetailsSort
20374
20345
  } = useMessageContext(MessageReactionsDetail.name);
20375
- const legacySortReactionDetails = propSortReactionDetails ?? contextSortReactionDetails;
20376
20346
  const reactionDetailsSort = propReactionDetailsSort ?? contextReactionDetailsSort ?? defaultReactionDetailsSort;
20377
20347
  const {
20378
20348
  isLoading: areReactionsLoading,
@@ -20384,10 +20354,6 @@ function MessageReactionsDetail({
20384
20354
  shouldFetch: true,
20385
20355
  sort: reactionDetailsSort
20386
20356
  });
20387
- const reactionDetailsWithLegacyFallback = React.useMemo(
20388
- () => legacySortReactionDetails ? [...reactionDetails].sort(legacySortReactionDetails) : reactionDetails,
20389
- [legacySortReactionDetails, reactionDetails]
20390
- );
20391
20357
  return /* @__PURE__ */ jsxRuntime.jsxs(
20392
20358
  "div",
20393
20359
  {
@@ -20432,7 +20398,7 @@ function MessageReactionsDetail({
20432
20398
  "data-testid": "all-reacting-users",
20433
20399
  children: [
20434
20400
  areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator2, {}),
20435
- !areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: reactionDetailsWithLegacyFallback.map(({ type, user }) => {
20401
+ !areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: reactionDetails.map(({ type, user }) => {
20436
20402
  const belongsToCurrentUser = client.user?.id === user?.id;
20437
20403
  const EmojiComponent = Array.isArray(reactionOptions) ? void 0 : reactionOptions.quick[type]?.Component ?? reactionOptions.extended?.[type]?.Component;
20438
20404
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -20465,8 +20431,13 @@ function MessageReactionsDetail({
20465
20431
  className: "str-chat__message-reactions-detail__user-list-item-button",
20466
20432
  "data-testid": "remove-reaction-button",
20467
20433
  onClick: async (e) => {
20434
+ const reactionCountBeforeRemoval = reactionGroups?.[type]?.count ?? 0;
20468
20435
  await contextHandleReaction(type, e);
20469
- refetch();
20436
+ if (reactionCountBeforeRemoval <= 1) {
20437
+ onSelectedReactionTypeChange?.(null);
20438
+ } else {
20439
+ refetch();
20440
+ }
20470
20441
  },
20471
20442
  children: t("Tap to remove")
20472
20443
  }
@@ -20495,17 +20466,15 @@ const useProcessReactions = (params) => {
20495
20466
  const {
20496
20467
  own_reactions: propOwnReactions,
20497
20468
  reaction_groups: propReactionGroups,
20498
- reactionOptions: propReactionOptions,
20499
20469
  reactions: propReactions,
20500
20470
  sortReactions: propSortReactions
20501
20471
  } = params;
20502
20472
  const { message, sortReactions: contextSortReactions } = useMessageContext();
20503
- const { reactionOptions: contextReactionOptions = defaultReactionOptions } = WithAudioPlayback.useComponentContext();
20504
- const reactionOptions = propReactionOptions ?? contextReactionOptions;
20473
+ const { reactionOptions = defaultReactionOptions } = WithAudioPlayback.useComponentContext();
20505
20474
  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;
20475
+ const latestReactions = propReactions ?? message.latest_reactions;
20476
+ const ownReactions = propOwnReactions ?? message?.own_reactions;
20477
+ const reactionGroups = propReactionGroups ?? message?.reaction_groups ?? void 0;
20509
20478
  const isOwnReaction = React.useCallback(
20510
20479
  (reactionType) => ownReactions?.some((reaction) => reaction.type === reactionType) ?? false,
20511
20480
  [ownReactions]
@@ -20589,6 +20558,7 @@ const useProcessReactions = (params) => {
20589
20558
  return {
20590
20559
  existingReactions,
20591
20560
  hasReactions,
20561
+ reactionGroups,
20592
20562
  totalReactionCount,
20593
20563
  uniqueReactionTypeCount
20594
20564
  };
@@ -20605,16 +20575,22 @@ const FragmentOrButton = ({
20605
20575
  };
20606
20576
  const UnMemoizedMessageReactions = (props) => {
20607
20577
  const {
20578
+ capLimit: { clustered: capLimitClustered = 5, segmented: capLimitSegmented = 4 } = {},
20608
20579
  flipHorizontalPosition = false,
20609
20580
  handleFetchReactions,
20610
20581
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
20611
20582
  reactionDetailsSort,
20612
- sortReactionDetails,
20613
20583
  verticalPosition = "top",
20614
20584
  visualStyle = "clustered",
20615
20585
  ...rest
20616
20586
  } = props;
20617
- const { existingReactions, hasReactions, totalReactionCount, uniqueReactionTypeCount } = useProcessReactions(rest);
20587
+ const {
20588
+ existingReactions,
20589
+ hasReactions,
20590
+ reactionGroups,
20591
+ totalReactionCount,
20592
+ uniqueReactionTypeCount
20593
+ } = useProcessReactions(rest);
20618
20594
  const [selectedReactionType, setSelectedReactionType] = React.useState(
20619
20595
  null
20620
20596
  );
@@ -20633,16 +20609,27 @@ const UnMemoizedMessageReactions = (props) => {
20633
20609
  dialog.open();
20634
20610
  };
20635
20611
  const cappedExistingReactions = React.useMemo(() => {
20636
- if (visualStyle !== "segmented" || verticalPosition !== "top") return null;
20637
- const sliced = existingReactions.slice(0, 4);
20612
+ if (visualStyle === "segmented" && verticalPosition !== "top") return null;
20613
+ const capLimit = visualStyle === "segmented" ? capLimitSegmented : capLimitClustered;
20614
+ const sliced = existingReactions.slice(0, capLimit);
20638
20615
  return {
20616
+ /**
20617
+ * Accumulated reaction count of capped reaction types, first four in case of
20618
+ * segmented(top) and first five in case of clustered(top/bottom) variations.
20619
+ */
20639
20620
  reactionCountToDisplay: sliced.reduce(
20640
20621
  (accumulatedCount, { reactionCount }) => accumulatedCount + reactionCount,
20641
20622
  0
20642
20623
  ),
20643
20624
  reactionsToDisplay: sliced
20644
20625
  };
20645
- }, [existingReactions, verticalPosition, visualStyle]);
20626
+ }, [
20627
+ capLimitClustered,
20628
+ capLimitSegmented,
20629
+ existingReactions,
20630
+ verticalPosition,
20631
+ visualStyle
20632
+ ]);
20646
20633
  if (!hasReactions) return null;
20647
20634
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
20648
20635
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -20663,7 +20650,7 @@ const UnMemoizedMessageReactions = (props) => {
20663
20650
  "aria-pressed": isDialogOpen,
20664
20651
  buttonIf: visualStyle === "clustered",
20665
20652
  className: "str-chat__message-reactions__list-button",
20666
- onClick: () => handleReactionButtonClick(existingReactions[0]?.reactionType ?? null),
20653
+ onClick: () => handleReactionButtonClick(null),
20667
20654
  children: [
20668
20655
  /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "str-chat__message-reactions__list", children: [
20669
20656
  (cappedExistingReactions?.reactionsToDisplay ?? existingReactions).map(
@@ -20694,7 +20681,7 @@ const UnMemoizedMessageReactions = (props) => {
20694
20681
  reactionType
20695
20682
  )
20696
20683
  ),
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(
20684
+ 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
20685
  "button",
20699
20686
  {
20700
20687
  className: "str-chat__message-reactions__list-item-button",
@@ -20727,9 +20714,9 @@ const UnMemoizedMessageReactions = (props) => {
20727
20714
  {
20728
20715
  handleFetchReactions,
20729
20716
  onSelectedReactionTypeChange: setSelectedReactionType,
20717
+ reactionGroups,
20730
20718
  reactions: existingReactions,
20731
20719
  selectedReactionType,
20732
- sortReactionDetails,
20733
20720
  totalReactionCount
20734
20721
  }
20735
20722
  )
@@ -21210,7 +21197,6 @@ const Message = (props) => {
21210
21197
  pinPermissions,
21211
21198
  reactionDetailsSort,
21212
21199
  retrySendMessage: propRetrySendMessage,
21213
- sortReactionDetails,
21214
21200
  sortReactions
21215
21201
  } = props;
21216
21202
  const { client } = WithAudioPlayback.useChatContext("Message");
@@ -21304,7 +21290,6 @@ const Message = (props) => {
21304
21290
  readBy: props.readBy,
21305
21291
  renderText: props.renderText,
21306
21292
  returnAllReadData: props.returnAllReadData,
21307
- sortReactionDetails,
21308
21293
  sortReactions,
21309
21294
  threadList: props.threadList,
21310
21295
  unsafeHTML: props.unsafeHTML,
@@ -22933,7 +22918,6 @@ const MessageListWithContext = (props) => {
22933
22918
  returnAllReadData = false,
22934
22919
  reviewProcessedMessage,
22935
22920
  showUnreadNotificationAlways,
22936
- sortReactionDetails,
22937
22921
  sortReactions,
22938
22922
  suppressAutoscroll,
22939
22923
  threadList = false,
@@ -23051,7 +23035,6 @@ const MessageListWithContext = (props) => {
23051
23035
  renderText: props.renderText,
23052
23036
  retrySendMessage: props.retrySendMessage,
23053
23037
  showAvatar: props.showAvatar,
23054
- sortReactionDetails,
23055
23038
  sortReactions,
23056
23039
  unsafeHTML
23057
23040
  },
@@ -23346,7 +23329,6 @@ const messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
23346
23329
  renderText: renderText2,
23347
23330
  returnAllReadData,
23348
23331
  showAvatar,
23349
- sortReactionDetails,
23350
23332
  sortReactions,
23351
23333
  threadList,
23352
23334
  unreadMessageCount = 0,
@@ -23396,7 +23378,6 @@ const messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
23396
23378
  renderText: renderText2,
23397
23379
  returnAllReadData,
23398
23380
  showAvatar,
23399
- sortReactionDetails,
23400
23381
  sortReactions,
23401
23382
  threadList
23402
23383
  }
@@ -23481,7 +23462,6 @@ const VirtualizedMessageListWithContext = (props) => {
23481
23462
  shouldGroupByUser = false,
23482
23463
  showAvatar,
23483
23464
  showUnreadNotificationAlways,
23484
- sortReactionDetails,
23485
23465
  sortReactions,
23486
23466
  stickToBottomScrollBehavior = "smooth",
23487
23467
  suppressAutoscroll,
@@ -23750,7 +23730,6 @@ const VirtualizedMessageListWithContext = (props) => {
23750
23730
  returnAllReadData,
23751
23731
  shouldGroupByUser,
23752
23732
  showAvatar,
23753
- sortReactionDetails,
23754
23733
  sortReactions,
23755
23734
  threadList,
23756
23735
  unreadMessageCount: channelUnreadUiState?.unread_messages,
@@ -25089,7 +25068,7 @@ const LoadMorePaginator = React.memo(
25089
25068
  UnMemoizedLoadMorePaginator
25090
25069
  );
25091
25070
  const ChannelListHeader = ({
25092
- ToggleButtonIcon = WithAudioPlayback.IconLayoutAlignLeft
25071
+ ToggleButtonIcon = WithAudioPlayback.IconSidebar
25093
25072
  }) => {
25094
25073
  const { t } = WithAudioPlayback.useTranslationContext();
25095
25074
  const { channel, navOpen } = WithAudioPlayback.useChatContext();
@@ -25261,11 +25240,11 @@ const UnMemoizedChannelList = (props) => {
25261
25240
  }
25262
25241
  );
25263
25242
  const showChannelList = !searchIsActive;
25264
- return /* @__PURE__ */ jsxRuntime.jsx(DialogManagerProvider, { id: `channel-list-dialog-manager-${stableId}`, children: /* @__PURE__ */ jsxRuntime.jsx(
25243
+ return /* @__PURE__ */ jsxRuntime.jsx(
25265
25244
  WithAudioPlayback.ChannelListContextProvider,
25266
25245
  {
25267
25246
  value: { channels, hasNextPage, loadNextPage, setChannels },
25268
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className, ref: channelListRef, children: [
25247
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, ref: channelListRef, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogManagerProvider, { id: `channel-list-dialog-manager-${stableId}`, children: [
25269
25248
  /* @__PURE__ */ jsxRuntime.jsx(ChannelListHeader, {}),
25270
25249
  showChannelSearch && /* @__PURE__ */ jsxRuntime.jsx(Search$12, {}),
25271
25250
  showChannelList && /* @__PURE__ */ jsxRuntime.jsx(
@@ -25287,9 +25266,9 @@ const UnMemoizedChannelList = (props) => {
25287
25266
  }
25288
25267
  ),
25289
25268
  /* @__PURE__ */ jsxRuntime.jsx(NotificationList$1, { panel: "channel-list" })
25290
- ] })
25269
+ ] }) })
25291
25270
  }
25292
- ) });
25271
+ );
25293
25272
  };
25294
25273
  const ChannelList = React.memo(
25295
25274
  UnMemoizedChannelList
@@ -26016,11 +25995,13 @@ function ChannelListItemTimestamp({ lastMessage }) {
26016
25995
  function getAttachmentContentType(attachment) {
26017
25996
  if (!attachment) return "text";
26018
25997
  if (attachment.type === "giphy") return "giphy";
26019
- if (attachment.type === "image") return "image";
25998
+ if (attachment.type === "image") {
25999
+ if (attachment.og_scrape_url || attachment.title_link) return "link";
26000
+ return "image";
26001
+ }
26020
26002
  if (attachment.type === "video") return "video";
26021
26003
  if (attachment.type === "voiceRecording") return "voice";
26022
26004
  if (attachment.type === "file") return "file";
26023
- if (attachment.og_scrape_url || attachment.title_link) return "link";
26024
26005
  return "file";
26025
26006
  }
26026
26007
  function getAttachmentFallbackText(type, count, t) {
@@ -26100,13 +26081,13 @@ const useLatestMessagePreview = ({
26100
26081
  } else {
26101
26082
  contentType = "file";
26102
26083
  }
26103
- let text2 = contentType === "giphy" ? "Giphy" : (
26084
+ let text2 = contentType === "giphy" ? `GIPHY ${firstAttachment.title ?? ""}`.trim() : (
26104
26085
  // prioritize message text content if available
26105
26086
  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
26087
  (attachments.length === 1 && contentType !== "voice" ? firstAttachment.fallback || firstAttachment.title : "") || // then generic fallback text based on attachment type and count
26107
26088
  getAttachmentFallbackText(contentType, attachments.length, t)
26108
26089
  );
26109
- if (contentType !== "giphy" && attachments.length === 1 && typeof firstAttachment.duration === "number") {
26090
+ if (attachments.length === 1 && typeof firstAttachment.duration === "number") {
26110
26091
  const minutes = Math.floor(firstAttachment.duration / 60);
26111
26092
  const seconds = Math.ceil(firstAttachment.duration) % 60;
26112
26093
  const durationString = `${minutes}:${seconds.toString().padStart(2, "0")}`;
@@ -26147,7 +26128,7 @@ const contentTypeIconMap = {
26147
26128
  deleted: WithAudioPlayback.IconNoSign,
26148
26129
  error: WithAudioPlayback.IconExclamationCircleFill,
26149
26130
  file: WithAudioPlayback.IconFile,
26150
- giphy: WithAudioPlayback.IconFile,
26131
+ giphy: WithAudioPlayback.IconGiphy,
26151
26132
  image: WithAudioPlayback.IconCamera,
26152
26133
  link: WithAudioPlayback.IconLink,
26153
26134
  location: WithAudioPlayback.IconLocation,
@@ -26795,7 +26776,7 @@ const ThreadListLoadingIndicator = () => {
26795
26776
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__thread-list-loading-indicator", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator$1, {}) });
26796
26777
  };
26797
26778
  const ThreadListHeader = ({
26798
- ToggleButtonIcon = WithAudioPlayback.IconLayoutAlignLeft
26779
+ ToggleButtonIcon = WithAudioPlayback.IconSidebar
26799
26780
  }) => {
26800
26781
  const { t } = WithAudioPlayback.useTranslationContext();
26801
26782
  const { navOpen } = WithAudioPlayback.useChatContext();
@@ -26928,7 +26909,6 @@ const ThreadList = ({ virtuosoProps }) => {
26928
26909
  const IconsBySeverity = {
26929
26910
  error: WithAudioPlayback.IconExclamationMark,
26930
26911
  info: null,
26931
- // IconInfo,
26932
26912
  loading: WithAudioPlayback.IconRefresh,
26933
26913
  success: WithAudioPlayback.IconCheckmark,
26934
26914
  warning: WithAudioPlayback.IconExclamationTriangle
@@ -27769,7 +27749,7 @@ const Giphy = ({ attachment }) => {
27769
27749
  ] });
27770
27750
  };
27771
27751
  const GiphyBadge = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__giphy-badge", children: [
27772
- /* @__PURE__ */ jsxRuntime.jsx(IconGiphy, {}),
27752
+ /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconGiphy, {}),
27773
27753
  "Giphy"
27774
27754
  ] });
27775
27755
  const Geolocation = ({
@@ -28304,7 +28284,7 @@ const ChannelHeader = (props) => {
28304
28284
  const {
28305
28285
  Avatar: Avatar2 = ChannelAvatar,
28306
28286
  image: overrideImage,
28307
- MenuIcon = WithAudioPlayback.IconLayoutAlignLeft,
28287
+ MenuIcon = WithAudioPlayback.IconSidebar,
28308
28288
  title: overrideTitle
28309
28289
  } = props;
28310
28290
  const { channel } = WithAudioPlayback.useChannelStateContext();
@@ -28321,12 +28301,12 @@ const ChannelHeader = (props) => {
28321
28301
  "str-chat__channel-header--sidebar-collapsed": !navOpen
28322
28302
  }),
28323
28303
  children: [
28324
- /* @__PURE__ */ jsxRuntime.jsx(ToggleSidebarButton, { mode: "expand", children: /* @__PURE__ */ jsxRuntime.jsx(MenuIcon, {}) }),
28304
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__channel-header__start", children: /* @__PURE__ */ jsxRuntime.jsx(ToggleSidebarButton, { mode: "expand", children: /* @__PURE__ */ jsxRuntime.jsx(MenuIcon, {}) }) }),
28325
28305
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__channel-header__data", children: [
28326
28306
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__channel-header__data__title", children: displayTitle }),
28327
28307
  /* @__PURE__ */ jsxRuntime.jsx(ChannelHeaderSubtitle, {})
28328
28308
  ] }),
28329
- /* @__PURE__ */ jsxRuntime.jsx(
28309
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__channel-header__end", children: /* @__PURE__ */ jsxRuntime.jsx(
28330
28310
  Avatar2,
28331
28311
  {
28332
28312
  className: "str-chat__avatar--channel-header",
@@ -28336,7 +28316,7 @@ const ChannelHeader = (props) => {
28336
28316
  size: "lg",
28337
28317
  userName: displayTitle
28338
28318
  }
28339
- )
28319
+ ) })
28340
28320
  ]
28341
28321
  }
28342
28322
  );
@@ -28379,15 +28359,13 @@ exports.IconArchive = WithAudioPlayback.IconArchive;
28379
28359
  exports.IconArrowDown = WithAudioPlayback.IconArrowDown;
28380
28360
  exports.IconArrowDownCircle = WithAudioPlayback.IconArrowDownCircle;
28381
28361
  exports.IconArrowLeft = WithAudioPlayback.IconArrowLeft;
28382
- exports.IconArrowRight = WithAudioPlayback.IconArrowRight;
28383
28362
  exports.IconArrowUp = WithAudioPlayback.IconArrowUp;
28384
28363
  exports.IconArrowUpRight = WithAudioPlayback.IconArrowUpRight;
28385
28364
  exports.IconAttachment = WithAudioPlayback.IconAttachment;
28386
28365
  exports.IconAudio = WithAudioPlayback.IconAudio;
28387
28366
  exports.IconBell = WithAudioPlayback.IconBell;
28388
28367
  exports.IconBellOff = WithAudioPlayback.IconBellOff;
28389
- exports.IconBubble3ChatMessage = WithAudioPlayback.IconBubble3ChatMessage;
28390
- exports.IconBubbleText6SolidChatMessage = WithAudioPlayback.IconBubbleText6SolidChatMessage;
28368
+ exports.IconBolt = WithAudioPlayback.IconBolt;
28391
28369
  exports.IconCamera = WithAudioPlayback.IconCamera;
28392
28370
  exports.IconCheckmark = WithAudioPlayback.IconCheckmark;
28393
28371
  exports.IconCheckmark1Small = WithAudioPlayback.IconCheckmark1Small;
@@ -28409,20 +28387,16 @@ exports.IconExclamationTriangle = WithAudioPlayback.IconExclamationTriangle;
28409
28387
  exports.IconEyeOpen = WithAudioPlayback.IconEyeOpen;
28410
28388
  exports.IconFile = WithAudioPlayback.IconFile;
28411
28389
  exports.IconFlag = WithAudioPlayback.IconFlag;
28390
+ exports.IconGiphy = WithAudioPlayback.IconGiphy;
28412
28391
  exports.IconImage = WithAudioPlayback.IconImage;
28413
- exports.IconInfo = WithAudioPlayback.IconInfo;
28414
- exports.IconLayoutAlignLeft = WithAudioPlayback.IconLayoutAlignLeft;
28415
28392
  exports.IconLeave = WithAudioPlayback.IconLeave;
28416
- exports.IconLightBulbSimple = WithAudioPlayback.IconLightBulbSimple;
28417
28393
  exports.IconLink = WithAudioPlayback.IconLink;
28418
28394
  exports.IconLoading = WithAudioPlayback.IconLoading;
28419
28395
  exports.IconLocation = WithAudioPlayback.IconLocation;
28420
28396
  exports.IconMessageBubble = WithAudioPlayback.IconMessageBubble;
28421
28397
  exports.IconMessageBubbleFill = WithAudioPlayback.IconMessageBubbleFill;
28422
28398
  exports.IconMessageBubbles = WithAudioPlayback.IconMessageBubbles;
28423
- exports.IconMinus = WithAudioPlayback.IconMinus;
28424
28399
  exports.IconMinusCircle = WithAudioPlayback.IconMinusCircle;
28425
- exports.IconMinusSmall = WithAudioPlayback.IconMinusSmall;
28426
28400
  exports.IconMore = WithAudioPlayback.IconMore;
28427
28401
  exports.IconMute = WithAudioPlayback.IconMute;
28428
28402
  exports.IconNoSign = WithAudioPlayback.IconNoSign;
@@ -28441,10 +28415,9 @@ exports.IconRetry = WithAudioPlayback.IconRetry;
28441
28415
  exports.IconSave = WithAudioPlayback.IconSave;
28442
28416
  exports.IconSearch = WithAudioPlayback.IconSearch;
28443
28417
  exports.IconSend = WithAudioPlayback.IconSend;
28444
- exports.IconSettingsGear2 = WithAudioPlayback.IconSettingsGear2;
28418
+ exports.IconSidebar = WithAudioPlayback.IconSidebar;
28445
28419
  exports.IconThread = WithAudioPlayback.IconThread;
28446
28420
  exports.IconThreadFill = WithAudioPlayback.IconThreadFill;
28447
- exports.IconThunder = WithAudioPlayback.IconThunder;
28448
28421
  exports.IconTranslate = WithAudioPlayback.IconTranslate;
28449
28422
  exports.IconTrophy = WithAudioPlayback.IconTrophy;
28450
28423
  exports.IconUnpin = WithAudioPlayback.IconUnpin;
@@ -28457,7 +28430,6 @@ exports.IconUserRemove = WithAudioPlayback.IconUserRemove;
28457
28430
  exports.IconVideo = WithAudioPlayback.IconVideo;
28458
28431
  exports.IconVideoFill = WithAudioPlayback.IconVideoFill;
28459
28432
  exports.IconVoice = WithAudioPlayback.IconVoice;
28460
- exports.IconVoiceFill = WithAudioPlayback.IconVoiceFill;
28461
28433
  exports.IconXCircle = WithAudioPlayback.IconXCircle;
28462
28434
  exports.IconXmark = WithAudioPlayback.IconXmark;
28463
28435
  exports.LoadingChannel = WithAudioPlayback.LoadingChannel;
@@ -28625,7 +28597,6 @@ exports.GiphyPreviewMessage = GiphyPreviewMessage;
28625
28597
  exports.GlobalModal = GlobalModal;
28626
28598
  exports.GroupAvatar = GroupAvatar;
28627
28599
  exports.Header = Header$1;
28628
- exports.IconGiphy = IconGiphy;
28629
28600
  exports.ImageComponent = ImageComponent;
28630
28601
  exports.ImageContainer = ImageContainer;
28631
28602
  exports.ImagePlaceholder = ImagePlaceholder;