stream-chat-react 10.1.2 → 10.2.0

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 (68) hide show
  1. package/dist/browser.full-bundle.js +166 -44
  2. package/dist/browser.full-bundle.js.map +1 -1
  3. package/dist/browser.full-bundle.min.js +5 -5
  4. package/dist/browser.full-bundle.min.js.map +1 -1
  5. package/dist/components/Attachment/AttachmentContainer.d.ts.map +1 -1
  6. package/dist/components/Attachment/AttachmentContainer.js +67 -15
  7. package/dist/components/Attachment/attachment-sizing.d.ts +9 -0
  8. package/dist/components/Attachment/attachment-sizing.d.ts.map +1 -0
  9. package/dist/components/Attachment/attachment-sizing.js +72 -0
  10. package/dist/components/Channel/Channel.d.ts +7 -1
  11. package/dist/components/Channel/Channel.d.ts.map +1 -1
  12. package/dist/components/Channel/Channel.js +2 -1
  13. package/dist/components/Channel/hooks/useCreateChannelStateContext.d.ts.map +1 -1
  14. package/dist/components/Channel/hooks/useCreateChannelStateContext.js +5 -1
  15. package/dist/components/Gallery/Gallery.d.ts +7 -2
  16. package/dist/components/Gallery/Gallery.d.ts.map +1 -1
  17. package/dist/components/Gallery/Gallery.js +16 -5
  18. package/dist/components/Gallery/Image.d.ts +4 -0
  19. package/dist/components/Gallery/Image.d.ts.map +1 -1
  20. package/dist/components/Gallery/Image.js +3 -3
  21. package/dist/components/MessageInput/hooks/useFileUploads.d.ts.map +1 -1
  22. package/dist/components/MessageInput/hooks/useFileUploads.js +1 -0
  23. package/dist/components/MessageInput/hooks/useMessageInputState.d.ts +2 -0
  24. package/dist/components/MessageInput/hooks/useMessageInputState.d.ts.map +1 -1
  25. package/dist/components/MessageInput/hooks/useMessageInputState.js +2 -1
  26. package/dist/components/MessageInput/hooks/useSubmitHandler.d.ts.map +1 -1
  27. package/dist/components/MessageInput/hooks/useSubmitHandler.js +1 -0
  28. package/dist/components/MessageList/MessageList.d.ts.map +1 -1
  29. package/dist/components/MessageList/MessageList.js +1 -2
  30. package/dist/components/MessageList/VirtualizedMessageList.d.ts.map +1 -1
  31. package/dist/components/MessageList/VirtualizedMessageList.js +0 -1
  32. package/dist/components/MessageList/hooks/useMessageListElements.d.ts +0 -1
  33. package/dist/components/MessageList/hooks/useMessageListElements.d.ts.map +1 -1
  34. package/dist/components/MessageList/hooks/useMessageListElements.js +2 -3
  35. package/dist/components/MessageList/hooks/useScrollLocationLogic.d.ts +0 -1
  36. package/dist/components/MessageList/hooks/useScrollLocationLogic.d.ts.map +1 -1
  37. package/dist/components/MessageList/hooks/useScrollLocationLogic.js +0 -10
  38. package/dist/components/Thread/Thread.d.ts.map +1 -1
  39. package/dist/components/Thread/Thread.js +7 -2
  40. package/dist/context/ChannelStateContext.d.ts +5 -2
  41. package/dist/context/ChannelStateContext.d.ts.map +1 -1
  42. package/dist/css/index.css +1 -1
  43. package/dist/css/index.css.map +1 -1
  44. package/dist/css/v2/index.css +1 -1
  45. package/dist/css/v2/index.css.map +1 -1
  46. package/dist/css/v2/index.layout.css +1 -1
  47. package/dist/css/v2/index.layout.css.map +1 -1
  48. package/dist/index.cjs.js +166 -44
  49. package/dist/index.cjs.js.map +1 -1
  50. package/dist/scss/Attachment.scss +44 -17
  51. package/dist/scss/Audio.scss +1 -0
  52. package/dist/scss/Message.scss +28 -11
  53. package/dist/scss/v2/AttachmentList/AttachmentList-layout.scss +33 -19
  54. package/dist/scss/v2/Message/Message-layout.scss +12 -0
  55. package/dist/scss/v2/Message/Message-theme.scss +20 -0
  56. package/dist/scss/v2/MessageList/MessageList-layout.scss +1 -4
  57. package/dist/scss/v2/MessageList/VirtualizedMessageList-layout.scss +21 -0
  58. package/dist/scss/v2/MessageList/VirtualizedMessageList-theme.scss +9 -0
  59. package/dist/scss/v2/Notification/NotificationList-theme.scss +2 -2
  60. package/dist/scss/v2/_utils.scss +8 -0
  61. package/dist/stories/attachment-sizing.stories.d.ts +2 -0
  62. package/dist/stories/attachment-sizing.stories.d.ts.map +1 -0
  63. package/dist/stories/attachment-sizing.stories.js +179 -0
  64. package/dist/types/types.d.ts +9 -1
  65. package/dist/types/types.d.ts.map +1 -1
  66. package/dist/version.d.ts +1 -1
  67. package/dist/version.js +1 -1
  68. package/package.json +3 -3
package/dist/index.cjs.js CHANGED
@@ -1345,7 +1345,7 @@ var ModalGallery = function (props) {
1345
1345
  };
1346
1346
 
1347
1347
  var UnMemoizedGallery = function (props) {
1348
- var images = props.images;
1348
+ var images = props.images, innerRefs = props.innerRefs;
1349
1349
  var _a = React.useState(0), index = _a[0], setIndex = _a[1];
1350
1350
  var _b = React.useState(false), modalOpen = _b[0], setModalOpen = _b[1];
1351
1351
  var _c = useComponentContext('Gallery').ModalGallery, ModalGallery$1 = _c === void 0 ? ModalGallery : _c;
@@ -1362,13 +1362,13 @@ var UnMemoizedGallery = function (props) {
1362
1362
  }
1363
1363
  };
1364
1364
  var renderImages = images.slice(0, countImagesDisplayedInPreview).map(function (image, i) {
1365
- return i === lastImageIndexInPreview && images.length > countImagesDisplayedInPreview ? (React__default["default"].createElement("button", { className: 'str-chat__gallery-placeholder', key: "gallery-image-".concat(i), onClick: function () { return toggleModal(i); }, style: {
1366
- backgroundImage: "url(".concat(images[lastImageIndexInPreview].image_url, ")"),
1367
- } },
1365
+ return i === lastImageIndexInPreview && images.length > countImagesDisplayedInPreview ? (React__default["default"].createElement("button", __assign({ className: 'str-chat__gallery-placeholder', "data-testid": 'gallery-image-last', key: "gallery-image-".concat(i), onClick: function () { return toggleModal(i); }, style: __assign({ backgroundImage: "url(".concat(images[lastImageIndexInPreview].previewUrl ||
1366
+ images[lastImageIndexInPreview].image_url ||
1367
+ images[lastImageIndexInPreview].thumb_url, ")") }, image.style) }, ((innerRefs === null || innerRefs === void 0 ? void 0 : innerRefs.current) && { ref: function (r) { return (innerRefs.current[i] = r); } })),
1368
1368
  React__default["default"].createElement("p", null, t('{{ imageCount }} more', {
1369
1369
  imageCount: images.length - countImagesDisplayedInPreview,
1370
1370
  })))) : (React__default["default"].createElement("button", { className: 'str-chat__gallery-image', "data-testid": 'gallery-image', key: "gallery-image-".concat(i), onClick: function () { return toggleModal(i); } },
1371
- React__default["default"].createElement("img", { alt: 'User uploaded content', src: image.image_url || image.thumb_url })));
1371
+ React__default["default"].createElement("img", __assign({ alt: 'User uploaded content', src: image.previewUrl || image.image_url || image.thumb_url, style: image.style }, ((innerRefs === null || innerRefs === void 0 ? void 0 : innerRefs.current) && { ref: function (r) { return (innerRefs.current[i] = r); } })))));
1372
1372
  });
1373
1373
  var className = clsx('str-chat__gallery', {
1374
1374
  'str-chat__gallery--square': images.length > lastImageIndexInPreview,
@@ -1388,13 +1388,13 @@ var Gallery = React__default["default"].memo(UnMemoizedGallery);
1388
1388
  * A simple component that displays an image.
1389
1389
  */
1390
1390
  var ImageComponent = function (props) {
1391
- var _a = props.dimensions, dimensions = _a === void 0 ? {} : _a, fallback = props.fallback, image_url = props.image_url, thumb_url = props.thumb_url;
1391
+ var _a = props.dimensions, dimensions = _a === void 0 ? {} : _a, fallback = props.fallback, image_url = props.image_url, thumb_url = props.thumb_url, innerRef = props.innerRef, previewUrl = props.previewUrl, style = props.style;
1392
1392
  var _b = React.useState(false), modalIsOpen = _b[0], setModalIsOpen = _b[1];
1393
1393
  var _c = useComponentContext('ImageComponent').ModalGallery, ModalGallery$1 = _c === void 0 ? ModalGallery : _c;
1394
- var imageSrc = sanitizeUrl.sanitizeUrl(image_url || thumb_url);
1394
+ var imageSrc = sanitizeUrl.sanitizeUrl(previewUrl || image_url || thumb_url);
1395
1395
  var toggleModal = function () { return setModalIsOpen(function (modalIsOpen) { return !modalIsOpen; }); };
1396
1396
  return (React__default["default"].createElement(React__default["default"].Fragment, null,
1397
- React__default["default"].createElement("img", __assign({ alt: fallback, className: 'str-chat__message-attachment--img', "data-testid": 'image-test', onClick: toggleModal, src: imageSrc, tabIndex: 0 }, dimensions)),
1397
+ React__default["default"].createElement("img", __assign({ alt: fallback, className: 'str-chat__message-attachment--img', "data-testid": 'image-test', onClick: toggleModal, src: imageSrc, style: style, tabIndex: 0 }, dimensions, (innerRef && { ref: innerRef }))),
1398
1398
  React__default["default"].createElement(Modal, { onClose: toggleModal, open: modalIsOpen },
1399
1399
  React__default["default"].createElement(ModalGallery$1, { images: [props], index: 0 }))));
1400
1400
  };
@@ -1713,7 +1713,7 @@ var AttachmentWithinContainer = function (_a) {
1713
1713
  ? 'actions'
1714
1714
  : '';
1715
1715
  }
1716
- var classNames = clsx('str-chat__message-attachment', (_b = {},
1716
+ var classNames = clsx('str-chat__message-attachment str-chat__message-attachment-dynamic-size', (_b = {},
1717
1717
  _b["str-chat__message-attachment--".concat(componentType)] = componentType,
1718
1718
  _b["str-chat__message-attachment--".concat(attachment === null || attachment === void 0 ? void 0 : attachment.type)] = attachment === null || attachment === void 0 ? void 0 : attachment.type,
1719
1719
  _b["str-chat__message-attachment--".concat(componentType, "--").concat(extra)] = componentType && extra,
@@ -1729,22 +1729,68 @@ var AttachmentActionsContainer = function (_a) {
1729
1729
  return null;
1730
1730
  return (React__default["default"].createElement(AttachmentActions$1, __assign({}, attachment, { actionHandler: actionHandler, actions: attachment.actions, id: attachment.id || '', text: attachment.text || '' })));
1731
1731
  };
1732
+ function getCssDimensionsVariables(url) {
1733
+ var _a;
1734
+ var cssVars = (_a = {},
1735
+ _a['--original-height'] = 1000000,
1736
+ _a['--original-width'] = 1000000,
1737
+ _a);
1738
+ if (url) {
1739
+ var urlParams = new URL(url).searchParams;
1740
+ var oh = Number(urlParams.get('oh'));
1741
+ var ow = Number(urlParams.get('ow'));
1742
+ var originalHeight = oh > 1 ? oh : 1000000;
1743
+ var originalWidth = ow > 1 ? ow : 1000000;
1744
+ cssVars['--original-width'] = originalWidth;
1745
+ cssVars['--original-height'] = originalHeight;
1746
+ }
1747
+ return cssVars;
1748
+ }
1732
1749
  var GalleryContainer = function (_a) {
1733
1750
  var attachment = _a.attachment, _b = _a.Gallery, Gallery$1 = _b === void 0 ? Gallery : _b;
1751
+ var imageElements = React.useRef([]);
1752
+ var imageAttachmentSizeHandler = useChannelStateContext().imageAttachmentSizeHandler;
1753
+ var _c = React.useState([]), attachmentConfigurations = _c[0], setAttachmentConfigurations = _c[1];
1754
+ React.useLayoutEffect(function () {
1755
+ if (imageElements.current &&
1756
+ imageElements.current.every(function (element) { return !!element; }) &&
1757
+ imageAttachmentSizeHandler) {
1758
+ var newConfigurations_1 = [];
1759
+ imageElements.current.forEach(function (element, i) {
1760
+ var config = imageAttachmentSizeHandler(attachment.images[i], element);
1761
+ newConfigurations_1.push(config);
1762
+ });
1763
+ setAttachmentConfigurations(newConfigurations_1);
1764
+ }
1765
+ }, [imageElements, imageAttachmentSizeHandler, attachment]);
1766
+ var images = attachment.images.map(function (image, i) {
1767
+ var _a, _b, _c;
1768
+ return (__assign(__assign({}, image), { previewUrl: ((_a = attachmentConfigurations[i]) === null || _a === void 0 ? void 0 : _a.url) || 'about:blank', style: getCssDimensionsVariables(((_b = attachment.images[i]) === null || _b === void 0 ? void 0 : _b.image_url) || ((_c = attachment.images[i]) === null || _c === void 0 ? void 0 : _c.thumb_url) || '') }));
1769
+ });
1734
1770
  return (React__default["default"].createElement(AttachmentWithinContainer, { attachment: attachment, componentType: 'gallery' },
1735
- React__default["default"].createElement(Gallery$1, { images: attachment.images || [], key: 'gallery' })));
1771
+ React__default["default"].createElement(Gallery$1, { images: images || [], innerRefs: imageElements, key: 'gallery' })));
1736
1772
  };
1737
1773
  var ImageContainer = function (props) {
1738
1774
  var attachment = props.attachment, _a = props.Image, Image = _a === void 0 ? ImageComponent : _a;
1739
1775
  var componentType = 'image';
1776
+ var imageElement = React.useRef(null);
1777
+ var imageAttachmentSizeHandler = useChannelStateContext().imageAttachmentSizeHandler;
1778
+ var _b = React.useState(undefined), attachmentConfiguration = _b[0], setAttachmentConfiguration = _b[1];
1779
+ React.useLayoutEffect(function () {
1780
+ if (imageElement.current && imageAttachmentSizeHandler) {
1781
+ var config = imageAttachmentSizeHandler(attachment, imageElement.current);
1782
+ setAttachmentConfiguration(config);
1783
+ }
1784
+ }, [imageElement, imageAttachmentSizeHandler, attachment]);
1785
+ var imageConfig = __assign(__assign({}, attachment), { previewUrl: (attachmentConfiguration === null || attachmentConfiguration === void 0 ? void 0 : attachmentConfiguration.url) || 'about:blank', style: getCssDimensionsVariables(attachment.image_url || attachment.thumb_url || '') });
1740
1786
  if (attachment.actions && attachment.actions.length) {
1741
1787
  return (React__default["default"].createElement(AttachmentWithinContainer, { attachment: attachment, componentType: componentType },
1742
1788
  React__default["default"].createElement("div", { className: 'str-chat__attachment' },
1743
- React__default["default"].createElement(Image, __assign({}, attachment)),
1789
+ React__default["default"].createElement(Image, __assign({}, imageConfig, { innerRef: imageElement })),
1744
1790
  React__default["default"].createElement(AttachmentActionsContainer, __assign({}, props)))));
1745
1791
  }
1746
1792
  return (React__default["default"].createElement(AttachmentWithinContainer, { attachment: attachment, componentType: componentType },
1747
- React__default["default"].createElement(Image, __assign({}, attachment))));
1793
+ React__default["default"].createElement(Image, __assign({}, imageConfig, { innerRef: imageElement }))));
1748
1794
  };
1749
1795
  var CardContainer = function (props) {
1750
1796
  var attachment = props.attachment, _a = props.Card, Card$1 = _a === void 0 ? Card : _a;
@@ -1775,16 +1821,21 @@ var MediaContainer = function (props) {
1775
1821
  var _a;
1776
1822
  var attachment = props.attachment, _b = props.Media, Media = _b === void 0 ? ReactPlayer__default["default"] : _b;
1777
1823
  var componentType = 'media';
1778
- if ((_a = attachment.actions) === null || _a === void 0 ? void 0 : _a.length) {
1779
- return (React__default["default"].createElement(AttachmentWithinContainer, { attachment: attachment, componentType: componentType },
1780
- React__default["default"].createElement("div", { className: 'str-chat__attachment str-chat__attachment-media' },
1781
- React__default["default"].createElement("div", { className: 'str-chat__player-wrapper' },
1782
- React__default["default"].createElement(Media, { className: 'react-player', controls: true, height: '100%', url: attachment.asset_url, width: '100%' })),
1783
- React__default["default"].createElement(AttachmentActionsContainer, __assign({}, props)))));
1784
- }
1785
- return (React__default["default"].createElement(AttachmentWithinContainer, { attachment: attachment, componentType: componentType },
1786
- React__default["default"].createElement("div", { className: 'str-chat__player-wrapper' },
1787
- React__default["default"].createElement(Media, { className: 'react-player', controls: true, height: '100%', url: attachment.asset_url, width: '100%' }))));
1824
+ var _c = useChannelStateContext(), shouldGenerateVideoThumbnail = _c.shouldGenerateVideoThumbnail, videoAttachmentSizeHandler = _c.videoAttachmentSizeHandler;
1825
+ var videoElement = React.useRef(null);
1826
+ var _d = React.useState(), attachmentConfiguration = _d[0], setAttachmentConfiguration = _d[1];
1827
+ React.useLayoutEffect(function () {
1828
+ if (videoElement.current && videoAttachmentSizeHandler) {
1829
+ var config = videoAttachmentSizeHandler(attachment, videoElement.current, shouldGenerateVideoThumbnail);
1830
+ setAttachmentConfiguration(config);
1831
+ }
1832
+ }, [videoElement, videoAttachmentSizeHandler, attachment]);
1833
+ var content = (React__default["default"].createElement("div", { className: 'str-chat__player-wrapper', "data-testid": 'video-wrapper', ref: videoElement, style: getCssDimensionsVariables(attachment.thumb_url || '') },
1834
+ React__default["default"].createElement(Media, { className: 'react-player', config: { file: { attributes: { poster: attachmentConfiguration === null || attachmentConfiguration === void 0 ? void 0 : attachmentConfiguration.thumbUrl } } }, controls: true, height: '100%', url: attachmentConfiguration === null || attachmentConfiguration === void 0 ? void 0 : attachmentConfiguration.url, width: '100%' })));
1835
+ return ((_a = attachment.actions) === null || _a === void 0 ? void 0 : _a.length) ? (React__default["default"].createElement(AttachmentWithinContainer, { attachment: attachment, componentType: componentType },
1836
+ React__default["default"].createElement("div", { className: 'str-chat__attachment str-chat__attachment-media' },
1837
+ content,
1838
+ React__default["default"].createElement(AttachmentActionsContainer, __assign({}, props))))) : (React__default["default"].createElement(AttachmentWithinContainer, { attachment: attachment, componentType: componentType }, content));
1788
1839
  };
1789
1840
 
1790
1841
  var CONTAINER_MAP = {
@@ -3961,7 +4012,7 @@ var getStrippedEmojiData = function (data) { return (__assign(__assign({}, data)
3961
4012
 
3962
4013
  var useCreateChannelStateContext = function (value) {
3963
4014
  var _a;
3964
- var acceptedFiles = value.acceptedFiles, channel = value.channel, _b = value.channelCapabilitiesArray, channelCapabilitiesArray = _b === void 0 ? [] : _b, channelConfig = value.channelConfig, dragAndDropWindow = value.dragAndDropWindow, giphyVersion = value.giphyVersion, error = value.error, hasMore = value.hasMore, hasMoreNewer = value.hasMoreNewer, suppressAutoscroll = value.suppressAutoscroll, highlightedMessageId = value.highlightedMessageId, loading = value.loading, loadingMore = value.loadingMore, maxNumberOfFiles = value.maxNumberOfFiles, members = value.members, _c = value.messages, messages = _c === void 0 ? [] : _c, multipleUploads = value.multipleUploads, mutes = value.mutes, notifications = value.notifications, pinnedMessages = value.pinnedMessages, quotedMessage = value.quotedMessage, _d = value.read, read = _d === void 0 ? {} : _d, skipMessageDataMemoization = value.skipMessageDataMemoization, thread = value.thread, threadHasMore = value.threadHasMore, threadLoadingMore = value.threadLoadingMore, _e = value.threadMessages, threadMessages = _e === void 0 ? [] : _e, watcherCount = value.watcherCount, watcher_count = value.watcher_count, watchers = value.watchers;
4015
+ var acceptedFiles = value.acceptedFiles, channel = value.channel, _b = value.channelCapabilitiesArray, channelCapabilitiesArray = _b === void 0 ? [] : _b, channelConfig = value.channelConfig, dragAndDropWindow = value.dragAndDropWindow, giphyVersion = value.giphyVersion, error = value.error, hasMore = value.hasMore, hasMoreNewer = value.hasMoreNewer, imageAttachmentSizeHandler = value.imageAttachmentSizeHandler, suppressAutoscroll = value.suppressAutoscroll, highlightedMessageId = value.highlightedMessageId, loading = value.loading, loadingMore = value.loadingMore, maxNumberOfFiles = value.maxNumberOfFiles, members = value.members, _c = value.messages, messages = _c === void 0 ? [] : _c, multipleUploads = value.multipleUploads, mutes = value.mutes, notifications = value.notifications, pinnedMessages = value.pinnedMessages, quotedMessage = value.quotedMessage, _d = value.read, read = _d === void 0 ? {} : _d, shouldGenerateVideoThumbnail = value.shouldGenerateVideoThumbnail, skipMessageDataMemoization = value.skipMessageDataMemoization, thread = value.thread, threadHasMore = value.threadHasMore, threadLoadingMore = value.threadLoadingMore, _e = value.threadMessages, threadMessages = _e === void 0 ? [] : _e, videoAttachmentSizeHandler = value.videoAttachmentSizeHandler, watcherCount = value.watcherCount, watcher_count = value.watcher_count, watchers = value.watchers;
3965
4016
  var channelId = channel.cid;
3966
4017
  var lastRead = channel.initialized && ((_a = channel.lastRead()) === null || _a === void 0 ? void 0 : _a.getTime());
3967
4018
  var membersLength = Object.keys(members || []).length;
@@ -4012,6 +4063,7 @@ var useCreateChannelStateContext = function (value) {
4012
4063
  hasMore: hasMore,
4013
4064
  hasMoreNewer: hasMoreNewer,
4014
4065
  highlightedMessageId: highlightedMessageId,
4066
+ imageAttachmentSizeHandler: imageAttachmentSizeHandler,
4015
4067
  loading: loading,
4016
4068
  loadingMore: loadingMore,
4017
4069
  maxNumberOfFiles: maxNumberOfFiles,
@@ -4023,11 +4075,13 @@ var useCreateChannelStateContext = function (value) {
4023
4075
  pinnedMessages: pinnedMessages,
4024
4076
  quotedMessage: quotedMessage,
4025
4077
  read: read,
4078
+ shouldGenerateVideoThumbnail: shouldGenerateVideoThumbnail,
4026
4079
  suppressAutoscroll: suppressAutoscroll,
4027
4080
  thread: thread,
4028
4081
  threadHasMore: threadHasMore,
4029
4082
  threadLoadingMore: threadLoadingMore,
4030
4083
  threadMessages: threadMessages,
4084
+ videoAttachmentSizeHandler: videoAttachmentSizeHandler,
4031
4085
  watcher_count: watcher_count,
4032
4086
  watcherCount: watcherCount,
4033
4087
  watchers: watchers,
@@ -4047,6 +4101,7 @@ var useCreateChannelStateContext = function (value) {
4047
4101
  quotedMessage,
4048
4102
  readUsersLength,
4049
4103
  readUsersLastReads,
4104
+ shouldGenerateVideoThumbnail,
4050
4105
  skipMessageDataMemoization,
4051
4106
  suppressAutoscroll,
4052
4107
  thread,
@@ -9552,6 +9607,7 @@ var useFileUploads = function (props, state, dispatch) {
9552
9607
  dispatch({
9553
9608
  id: id,
9554
9609
  state: 'finished',
9610
+ thumb_url: response.thumb_url,
9555
9611
  type: 'setFileUpload',
9556
9612
  url: response.file,
9557
9613
  });
@@ -9816,6 +9872,7 @@ var useSubmitHandler = function (props, state, dispatch, numberOfUploads) {
9816
9872
  asset_url: upload.url,
9817
9873
  file_size: upload.file.size,
9818
9874
  mime_type: upload.file.type,
9875
+ thumb_url: upload.thumb_url,
9819
9876
  title: upload.file.name,
9820
9877
  type: getAttachmentTypeFromMime(upload.file.type || ''),
9821
9878
  }); });
@@ -10002,7 +10059,7 @@ var initState = function (message) {
10002
10059
  var type = _a.type;
10003
10060
  return type === 'file';
10004
10061
  }).reduce(function (acc, _a) {
10005
- var asset_url = _a.asset_url, file_size = _a.file_size, mime_type = _a.mime_type, _b = _a.title, title = _b === void 0 ? '' : _b;
10062
+ var asset_url = _a.asset_url, file_size = _a.file_size, mime_type = _a.mime_type, thumb_url = _a.thumb_url, _b = _a.title, title = _b === void 0 ? '' : _b;
10006
10063
  var id = nanoid.nanoid();
10007
10064
  acc[id] = {
10008
10065
  file: {
@@ -10012,6 +10069,7 @@ var initState = function (message) {
10012
10069
  },
10013
10070
  id: id,
10014
10071
  state: 'finished',
10072
+ thumb_url: thumb_url,
10015
10073
  url: asset_url,
10016
10074
  };
10017
10075
  return acc;
@@ -10916,6 +10974,79 @@ var useChannelContainerClasses = function (_a) {
10916
10974
  };
10917
10975
  };
10918
10976
 
10977
+ var getImageAttachmentConfiguration = function (attachment, element) {
10978
+ var url = new URL((attachment.image_url || attachment.thumb_url || ''));
10979
+ var resizeDimensions = getSizingRestrictions(url, element);
10980
+ if (resizeDimensions) {
10981
+ // Apply 2x for retina displays
10982
+ resizeDimensions.height *= 2;
10983
+ resizeDimensions.width *= 2;
10984
+ addResizingParamsToUrl(resizeDimensions, url);
10985
+ }
10986
+ return {
10987
+ url: url.href,
10988
+ };
10989
+ };
10990
+ var getVideoAttachmentConfiguration = function (attachment, element, shouldGenerateVideoThumbnail) {
10991
+ var thumbUrl = undefined;
10992
+ if (attachment.thumb_url && shouldGenerateVideoThumbnail) {
10993
+ var url = new URL(attachment.thumb_url);
10994
+ var resizeDimensions = getSizingRestrictions(url, element);
10995
+ if (resizeDimensions) {
10996
+ // Apply 2x for retina displays
10997
+ resizeDimensions.height *= 2;
10998
+ resizeDimensions.width *= 2;
10999
+ addResizingParamsToUrl(resizeDimensions, url);
11000
+ }
11001
+ thumbUrl = url.href;
11002
+ }
11003
+ return {
11004
+ thumbUrl: thumbUrl,
11005
+ url: attachment.asset_url || '',
11006
+ };
11007
+ };
11008
+ var getSizingRestrictions = function (url, htmlElement) {
11009
+ var urlParams = url.searchParams;
11010
+ var originalHeight = Number(urlParams.get('oh')) || 1;
11011
+ var originalWidth = Number(urlParams.get('ow')) || 1;
11012
+ var cssSizeRestriction = getCSSSizeRestrictions(htmlElement);
11013
+ var resizeDimensions;
11014
+ if ((cssSizeRestriction.maxHeight || cssSizeRestriction.height) && cssSizeRestriction.maxWidth) {
11015
+ resizeDimensions = getResizeDimensions(originalHeight, originalWidth,
11016
+ /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
11017
+ cssSizeRestriction.maxHeight || cssSizeRestriction.height, cssSizeRestriction.maxWidth);
11018
+ }
11019
+ else {
11020
+ resizeDimensions = undefined;
11021
+ }
11022
+ return resizeDimensions;
11023
+ };
11024
+ var getResizeDimensions = function (originalHeight, originalWidth, maxHeight, maxWidth) { return ({
11025
+ height: Math.round(Math.max(maxHeight, (maxWidth / originalWidth) * originalHeight)),
11026
+ width: Math.round(Math.max(maxHeight, (maxWidth / originalHeight) * originalWidth)),
11027
+ }); };
11028
+ var getCSSSizeRestrictions = function (htmlElement) {
11029
+ var computedStylesheet = getComputedStyle(htmlElement);
11030
+ var height = getValueRepresentationOfCSSProperty(computedStylesheet.getPropertyValue('height'));
11031
+ var maxHeight = getValueRepresentationOfCSSProperty(computedStylesheet.getPropertyValue('max-height'));
11032
+ var maxWidth = getValueRepresentationOfCSSProperty(computedStylesheet.getPropertyValue('max-width'));
11033
+ if (!((height || maxHeight) && maxWidth)) {
11034
+ console.warn("Invalid value set for height/max-height and/or max-width for HTML element, this can cause scrolling issues inside the message list, more info https://getstream.io/chat/docs/sdk/react/message-components/attachment/#image-and-video-sizing");
11035
+ }
11036
+ return { height: height, maxHeight: maxHeight, maxWidth: maxWidth };
11037
+ };
11038
+ var getValueRepresentationOfCSSProperty = function (property) {
11039
+ if (!property.endsWith('px')) {
11040
+ return undefined;
11041
+ }
11042
+ var number = parseFloat(property);
11043
+ return isNaN(number) ? undefined : number;
11044
+ };
11045
+ var addResizingParamsToUrl = function (resizeDimensions, url) {
11046
+ url.searchParams.set('h', resizeDimensions.height.toString());
11047
+ url.searchParams.set('w', resizeDimensions.width.toString());
11048
+ };
11049
+
10919
11050
  var UnMemoizedChannel = function (props) {
10920
11051
  var propsChannel = props.channel, _a = props.EmptyPlaceholder, EmptyPlaceholder = _a === void 0 ? null : _a, LoadingErrorIndicator = props.LoadingErrorIndicator, _b = props.LoadingIndicator, LoadingIndicator = _b === void 0 ? LoadingChannel : _b;
10921
11052
  var _c = useChatContext('Channel'), contextChannel = _c.channel, channelsQueryState = _c.channelsQueryState, customClasses = _c.customClasses, theme = _c.theme;
@@ -11402,7 +11533,7 @@ var ChannelInner = function (props) {
11402
11533
  var onMentionsHoverOrClick = useMentionsHandlers(onMentionsHover, onMentionsClick);
11403
11534
  var editMessage = useEditMessageHandler(doUpdateMessageRequest);
11404
11535
  var typing = state.typing, restState = __rest(state, ["typing"]);
11405
- var channelStateContextValue = useCreateChannelStateContext(__assign(__assign({}, restState), { acceptedFiles: acceptedFiles, channel: channel, channelCapabilitiesArray: channelCapabilitiesArray, channelConfig: channelConfig, dragAndDropWindow: dragAndDropWindow, giphyVersion: props.giphyVersion || 'fixed_height', maxNumberOfFiles: maxNumberOfFiles, multipleUploads: multipleUploads, mutes: mutes, notifications: notifications, quotedMessage: quotedMessage, watcher_count: state.watcherCount }));
11536
+ var channelStateContextValue = useCreateChannelStateContext(__assign(__assign({}, restState), { acceptedFiles: acceptedFiles, channel: channel, channelCapabilitiesArray: channelCapabilitiesArray, channelConfig: channelConfig, dragAndDropWindow: dragAndDropWindow, giphyVersion: props.giphyVersion || 'fixed_height', imageAttachmentSizeHandler: props.imageAttachmentSizeHandler || getImageAttachmentConfiguration, maxNumberOfFiles: maxNumberOfFiles, multipleUploads: multipleUploads, mutes: mutes, notifications: notifications, quotedMessage: quotedMessage, shouldGenerateVideoThumbnail: props.shouldGenerateVideoThumbnail || true, videoAttachmentSizeHandler: props.videoAttachmentSizeHandler || getVideoAttachmentConfiguration, watcher_count: state.watcherCount }));
11406
11537
  var channelActionContextValue = React.useMemo(function () { return ({
11407
11538
  addNotification: addNotification,
11408
11539
  closeThread: closeThread,
@@ -12648,7 +12779,7 @@ var UnMemoizedChannelList = function (props) {
12648
12779
  */
12649
12780
  var ChannelList = React__default["default"].memo(UnMemoizedChannelList);
12650
12781
 
12651
- var version = '10.1.2';
12782
+ var version = '10.2.0';
12652
12783
 
12653
12784
  var useChat = function (_a) {
12654
12785
  var _b, _c;
@@ -13701,7 +13832,7 @@ var useLastReadData = function (props) {
13701
13832
  };
13702
13833
 
13703
13834
  var useMessageListElements = function (props) {
13704
- var enrichedMessages = props.enrichedMessages, internalMessageProps = props.internalMessageProps, messageGroupStyles = props.messageGroupStyles, onMessageLoadCaptured = props.onMessageLoadCaptured, read = props.read, returnAllReadData = props.returnAllReadData, threadList = props.threadList;
13835
+ var enrichedMessages = props.enrichedMessages, internalMessageProps = props.internalMessageProps, messageGroupStyles = props.messageGroupStyles, read = props.read, returnAllReadData = props.returnAllReadData, threadList = props.threadList;
13705
13836
  var _a = useChatContext('useMessageListElements'), client = _a.client, customClasses = _a.customClasses;
13706
13837
  var _b = useComponentContext('useMessageListElements'), _c = _b.DateSeparator, DateSeparator$1 = _c === void 0 ? DateSeparator : _c, HeaderComponent = _b.HeaderComponent, _d = _b.MessageSystem, MessageSystem = _d === void 0 ? EventComponent : _d;
13707
13838
  // get the readData, but only for messages submitted by the user themselves
@@ -13733,7 +13864,7 @@ var useMessageListElements = function (props) {
13733
13864
  }
13734
13865
  var groupStyles = messageGroupStyles[message.id] || '';
13735
13866
  var messageClass = (customClasses === null || customClasses === void 0 ? void 0 : customClasses.message) || "str-chat__li str-chat__li--".concat(groupStyles);
13736
- return (React__default["default"].createElement("li", { className: messageClass, "data-message-id": message.id, "data-testid": messageClass, key: message.id || message.created_at, onLoadCapture: onMessageLoadCaptured },
13867
+ return (React__default["default"].createElement("li", { className: messageClass, "data-message-id": message.id, "data-testid": messageClass, key: message.id || message.created_at },
13737
13868
  React__default["default"].createElement(Message, __assign({ groupStyles: [groupStyles], lastReceivedId: lastReceivedId, message: message, readBy: readData[message.id] || [], threadList: threadList }, internalMessageProps))));
13738
13869
  });
13739
13870
  }, [
@@ -13741,7 +13872,6 @@ var useMessageListElements = function (props) {
13741
13872
  internalMessageProps,
13742
13873
  lastReceivedId,
13743
13874
  messageGroupStyles,
13744
- onMessageLoadCaptured,
13745
13875
  readData,
13746
13876
  threadList,
13747
13877
  ]);
@@ -13860,19 +13990,9 @@ var useScrollLocationLogic = function (params) {
13860
13990
  setIsMessageListScrolledToBottom(true);
13861
13991
  }
13862
13992
  }, [updateScrollTop, closeToTop, closeToBottom, scrolledUpThreshold]);
13863
- var onMessageLoadCaptured = React.useCallback(function () {
13864
- /**
13865
- * A load event (emitted by e.g. an <img>) was captured on a message.
13866
- * In some cases, the loaded asset is larger than the placeholder, which means we have to scroll down.
13867
- */
13868
- if (closeToBottom.current) {
13869
- scrollToBottom();
13870
- }
13871
- }, [closeToTop, closeToBottom, scrollToBottom]);
13872
13993
  return {
13873
13994
  hasNewMessages: hasNewMessages,
13874
13995
  isMessageListScrolledToBottom: isMessageListScrolledToBottom,
13875
- onMessageLoadCaptured: onMessageLoadCaptured,
13876
13996
  onScroll: onScroll,
13877
13997
  scrollToBottom: scrollToBottom,
13878
13998
  wrapperRect: wrapperRect,
@@ -14000,7 +14120,7 @@ var MessageListWithContext = function (props) {
14000
14120
  messages: messages,
14001
14121
  scrolledUpThreshold: props.scrolledUpThreshold,
14002
14122
  suppressAutoscroll: suppressAutoscroll,
14003
- }), hasNewMessages = _x.hasNewMessages, isMessageListScrolledToBottom = _x.isMessageListScrolledToBottom, onMessageLoadCaptured = _x.onMessageLoadCaptured, onScroll = _x.onScroll, scrollToBottom = _x.scrollToBottom, wrapperRect = _x.wrapperRect;
14123
+ }), hasNewMessages = _x.hasNewMessages, isMessageListScrolledToBottom = _x.isMessageListScrolledToBottom, onScroll = _x.onScroll, scrollToBottom = _x.scrollToBottom, wrapperRect = _x.wrapperRect;
14004
14124
  var _y = useEnrichedMessages({
14005
14125
  channel: channel,
14006
14126
  disableDateSeparator: disableDateSeparator,
@@ -14040,7 +14160,6 @@ var MessageListWithContext = function (props) {
14040
14160
  unsafeHTML: unsafeHTML,
14041
14161
  },
14042
14162
  messageGroupStyles: messageGroupStyles,
14043
- onMessageLoadCaptured: onMessageLoadCaptured,
14044
14163
  read: read,
14045
14164
  returnAllReadData: returnAllReadData,
14046
14165
  threadList: threadList,
@@ -14484,7 +14603,6 @@ var VirtualizedMessageListWithContext = function (props) {
14484
14603
  return Item;
14485
14604
  }, [
14486
14605
  customClasses === null || customClasses === void 0 ? void 0 : customClasses.virtualMessage,
14487
- messageGroupStyles,
14488
14606
  numItemsPrepended,
14489
14607
  // processedMessages were incorrectly rebuilt with a new object identity at some point, hence the .length usage
14490
14608
  processedMessages.length,
@@ -14622,9 +14740,13 @@ var ThreadInner = function (props) {
14622
14740
  }, []);
14623
14741
  if (!thread)
14624
14742
  return null;
14625
- var threadClass = (customClasses === null || customClasses === void 0 ? void 0 : customClasses.thread) || 'str-chat__thread-container str-chat__thread';
14743
+ var threadClass = (customClasses === null || customClasses === void 0 ? void 0 : customClasses.thread) ||
14744
+ clsx('str-chat__thread-container str-chat__thread', {
14745
+ 'str-chat__thread--full': fullWidth,
14746
+ 'str-chat__thread--virtualized': virtualized,
14747
+ });
14626
14748
  var head = (React__default["default"].createElement(ThreadHead$1, __assign({ key: thread.id, message: thread, Message: MessageUIComponent }, additionalParentMessageProps)));
14627
- return (React__default["default"].createElement("div", { className: "".concat(threadClass, " ").concat(fullWidth ? 'str-chat__thread--full' : '') },
14749
+ return (React__default["default"].createElement("div", { className: threadClass },
14628
14750
  React__default["default"].createElement(ThreadHeader$1, { closeThread: closeThread, thread: thread }),
14629
14751
  React__default["default"].createElement(ThreadMessageList, __assign({ disableDateSeparator: !enableDateSeparator, hasMore: threadHasMore, head: head, loadingMore: threadLoadingMore, loadMore: loadMoreThread, Message: MessageUIComponent, messageActions: messageActions, messages: threadMessages || [], suppressAutoscroll: threadSuppressAutoscroll, threadList: true }, (virtualized ? additionalVirtualizedMessageListProps : additionalMessageListProps))),
14630
14752
  React__default["default"].createElement(MessageInput, __assign({ focus: autoFocus, Input: ThreadInput, parent: thread, publishTypingEvent: false }, additionalMessageInputProps))));