@uzum-tech/ui 1.9.0 → 1.9.1

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 (118) hide show
  1. package/dist/index.js +586 -265
  2. package/dist/index.prod.js +2 -2
  3. package/es/chat/index.d.ts +1 -1
  4. package/es/chat/src/Chat.d.ts +233 -11
  5. package/es/chat/src/Chat.js +73 -22
  6. package/es/chat/src/ChatParts/ChatAttachment.js +14 -12
  7. package/es/chat/src/ChatParts/MainArea.d.ts +1 -0
  8. package/es/chat/src/ChatParts/MainArea.js +95 -57
  9. package/es/chat/src/ChatParts/Sidebar.d.ts +920 -0
  10. package/es/chat/src/ChatParts/Sidebar.js +63 -12
  11. package/es/chat/src/interface.d.ts +24 -3
  12. package/es/chat/src/styles/index.cssr.js +13 -2
  13. package/es/date-picker/src/DatePicker.d.ts +1308 -43
  14. package/es/date-picker/src/DatePicker.js +54 -29
  15. package/es/date-picker/src/interface.d.ts +1 -0
  16. package/es/date-picker/src/panel/date.d.ts +141 -0
  17. package/es/date-picker/src/panel/daterange.d.ts +141 -0
  18. package/es/date-picker/src/panel/datetime.d.ts +141 -0
  19. package/es/date-picker/src/panel/datetimerange.d.ts +141 -0
  20. package/es/date-picker/src/panel/panelMonth.d.ts +282 -0
  21. package/es/date-picker/src/panel/panelMonthContent.d.ts +141 -0
  22. package/es/date-picker/src/panel/panelYear.d.ts +282 -0
  23. package/es/date-picker/src/panel/panelYearContent.d.ts +141 -0
  24. package/es/date-picker/src/panel/use-calendar.d.ts +141 -0
  25. package/es/date-picker/src/panel/use-dual-calendar.d.ts +141 -0
  26. package/es/date-picker/src/panel/use-panel-common.d.ts +141 -0
  27. package/es/date-picker/styles/dark.js +3 -1
  28. package/es/date-picker/styles/light.d.ts +123 -0
  29. package/es/date-picker/styles/light.js +3 -1
  30. package/es/descriptions/src/Descriptions.d.ts +30 -0
  31. package/es/descriptions/src/Descriptions.js +18 -10
  32. package/es/locales/common/arDZ.js +2 -0
  33. package/es/locales/common/deDE.js +2 -0
  34. package/es/locales/common/enGB.js +2 -0
  35. package/es/locales/common/enUS.d.ts +2 -0
  36. package/es/locales/common/enUS.js +2 -0
  37. package/es/locales/common/eo.js +2 -0
  38. package/es/locales/common/esAR.js +2 -0
  39. package/es/locales/common/faIR.js +2 -0
  40. package/es/locales/common/frFR.js +2 -0
  41. package/es/locales/common/idID.js +2 -0
  42. package/es/locales/common/itIT.js +2 -0
  43. package/es/locales/common/jaJP.js +2 -0
  44. package/es/locales/common/koKR.js +2 -0
  45. package/es/locales/common/nbNO.js +2 -0
  46. package/es/locales/common/nlNL.js +2 -0
  47. package/es/locales/common/plPL.js +2 -0
  48. package/es/locales/common/ptBR.js +2 -0
  49. package/es/locales/common/ruRU.js +2 -0
  50. package/es/locales/common/skSK.js +2 -0
  51. package/es/locales/common/svSE.js +2 -0
  52. package/es/locales/common/thTH.js +2 -0
  53. package/es/locales/common/trTR.js +2 -0
  54. package/es/locales/common/ukUA.js +2 -0
  55. package/es/locales/common/viVN.js +2 -0
  56. package/es/locales/common/zhCN.js +2 -0
  57. package/es/locales/common/zhTW.js +2 -0
  58. package/es/version.d.ts +1 -1
  59. package/es/version.js +1 -1
  60. package/lib/chat/index.d.ts +1 -1
  61. package/lib/chat/src/Chat.d.ts +233 -11
  62. package/lib/chat/src/Chat.js +73 -22
  63. package/lib/chat/src/ChatParts/ChatAttachment.js +14 -12
  64. package/lib/chat/src/ChatParts/MainArea.d.ts +1 -0
  65. package/lib/chat/src/ChatParts/MainArea.js +94 -56
  66. package/lib/chat/src/ChatParts/Sidebar.d.ts +920 -0
  67. package/lib/chat/src/ChatParts/Sidebar.js +62 -11
  68. package/lib/chat/src/interface.d.ts +24 -3
  69. package/lib/chat/src/styles/index.cssr.js +13 -2
  70. package/lib/date-picker/src/DatePicker.d.ts +1308 -43
  71. package/lib/date-picker/src/DatePicker.js +53 -28
  72. package/lib/date-picker/src/interface.d.ts +1 -0
  73. package/lib/date-picker/src/panel/date.d.ts +141 -0
  74. package/lib/date-picker/src/panel/daterange.d.ts +141 -0
  75. package/lib/date-picker/src/panel/datetime.d.ts +141 -0
  76. package/lib/date-picker/src/panel/datetimerange.d.ts +141 -0
  77. package/lib/date-picker/src/panel/panelMonth.d.ts +282 -0
  78. package/lib/date-picker/src/panel/panelMonthContent.d.ts +141 -0
  79. package/lib/date-picker/src/panel/panelYear.d.ts +282 -0
  80. package/lib/date-picker/src/panel/panelYearContent.d.ts +141 -0
  81. package/lib/date-picker/src/panel/use-calendar.d.ts +141 -0
  82. package/lib/date-picker/src/panel/use-dual-calendar.d.ts +141 -0
  83. package/lib/date-picker/src/panel/use-panel-common.d.ts +141 -0
  84. package/lib/date-picker/styles/dark.js +3 -1
  85. package/lib/date-picker/styles/light.d.ts +123 -0
  86. package/lib/date-picker/styles/light.js +3 -1
  87. package/lib/descriptions/src/Descriptions.d.ts +30 -0
  88. package/lib/descriptions/src/Descriptions.js +18 -10
  89. package/lib/locales/common/arDZ.js +2 -0
  90. package/lib/locales/common/deDE.js +2 -0
  91. package/lib/locales/common/enGB.js +2 -0
  92. package/lib/locales/common/enUS.d.ts +2 -0
  93. package/lib/locales/common/enUS.js +2 -0
  94. package/lib/locales/common/eo.js +2 -0
  95. package/lib/locales/common/esAR.js +2 -0
  96. package/lib/locales/common/faIR.js +2 -0
  97. package/lib/locales/common/frFR.js +2 -0
  98. package/lib/locales/common/idID.js +2 -0
  99. package/lib/locales/common/itIT.js +2 -0
  100. package/lib/locales/common/jaJP.js +2 -0
  101. package/lib/locales/common/koKR.js +2 -0
  102. package/lib/locales/common/nbNO.js +2 -0
  103. package/lib/locales/common/nlNL.js +2 -0
  104. package/lib/locales/common/plPL.js +2 -0
  105. package/lib/locales/common/ptBR.js +2 -0
  106. package/lib/locales/common/ruRU.js +2 -0
  107. package/lib/locales/common/skSK.js +2 -0
  108. package/lib/locales/common/svSE.js +2 -0
  109. package/lib/locales/common/thTH.js +2 -0
  110. package/lib/locales/common/trTR.js +2 -0
  111. package/lib/locales/common/ukUA.js +2 -0
  112. package/lib/locales/common/viVN.js +2 -0
  113. package/lib/locales/common/zhCN.js +2 -0
  114. package/lib/locales/common/zhTW.js +2 -0
  115. package/lib/version.d.ts +1 -1
  116. package/lib/version.js +1 -1
  117. package/package.json +3 -3
  118. package/web-types.json +95 -4
@@ -61,6 +61,21 @@ exports.chatProps = Object.assign(Object.assign({}, _mixins_1.useTheme.props), {
61
61
  }, headerIconProps: {
62
62
  type: Object,
63
63
  default: undefined
64
+ }, headerShareButtonProps: {
65
+ type: Object,
66
+ default: undefined
67
+ }, headerProfileButtonProps: {
68
+ type: Object,
69
+ default: undefined
70
+ }, headerCloseButtonProps: {
71
+ type: Object,
72
+ default: undefined
73
+ }, headerShareIconProps: {
74
+ type: Object,
75
+ default: undefined
76
+ }, headerProfileIconProps: {
77
+ type: Object,
78
+ default: undefined
64
79
  }, messageSenderAvatarProps: {
65
80
  type: Object,
66
81
  default: undefined
@@ -97,6 +112,12 @@ exports.chatProps = Object.assign(Object.assign({}, _mixins_1.useTheme.props), {
97
112
  }, closeButtonText: {
98
113
  type: String,
99
114
  default: undefined
115
+ }, shareButtonTooltip: {
116
+ type: String,
117
+ default: undefined
118
+ }, profileButtonTooltip: {
119
+ type: String,
120
+ default: undefined
100
121
  }, unreadNotificationText: {
101
122
  type: String,
102
123
  default: undefined
@@ -136,7 +157,7 @@ exports.chatProps = Object.assign(Object.assign({}, _mixins_1.useTheme.props), {
136
157
  }, onFilterChange: {
137
158
  type: Function,
138
159
  default: undefined
139
- }, onLoadMoreChats: {
160
+ }, onFooterInputChange: {
140
161
  type: Function,
141
162
  default: undefined
142
163
  }, onNetworkError: {
@@ -148,6 +169,18 @@ exports.chatProps = Object.assign(Object.assign({}, _mixins_1.useTheme.props), {
148
169
  }, onSendError: {
149
170
  type: Function,
150
171
  default: undefined
172
+ }, onChatItemsScrollToTop: {
173
+ type: Function,
174
+ default: undefined
175
+ }, onChatItemsScrollToBottom: {
176
+ type: Function,
177
+ default: undefined
178
+ }, onMessagesScrollToTop: {
179
+ type: Function,
180
+ default: undefined
181
+ }, onMessagesScrollToBottom: {
182
+ type: Function,
183
+ default: undefined
151
184
  } });
152
185
  exports.default = (0, vue_1.defineComponent)({
153
186
  name: 'Chat',
@@ -159,12 +192,16 @@ exports.default = (0, vue_1.defineComponent)({
159
192
  'attachment-upload',
160
193
  'mark-messages-read',
161
194
  'filter-change',
162
- 'load-more-chats',
195
+ 'footer-input-change',
163
196
  'network-error',
164
197
  'upload-error',
165
- 'send-error'
198
+ 'send-error',
199
+ 'chat-items-scroll-to-top',
200
+ 'chat-items-scroll-to-bottom',
201
+ 'messages-scroll-to-top',
202
+ 'messages-scroll-to-bottom'
166
203
  ],
167
- setup(props, { slots, emit }) {
204
+ setup(props, { slots, emit, expose }) {
168
205
  const { mergedClsPrefixRef } = (0, _mixins_1.useConfig)(props);
169
206
  const themeRef = (0, _mixins_1.useTheme)('Chat', '-chat', index_cssr_1.default, styles_1.chatLight, props, mergedClsPrefixRef);
170
207
  const { localeRef } = (0, _mixins_1.useLocale)('Chat');
@@ -277,37 +314,25 @@ exports.default = (0, vue_1.defineComponent)({
277
314
  emit('message-send', content, attachments);
278
315
  };
279
316
  const handleMessageRetry = (message) => {
280
- var _a;
281
317
  emit('message-retry', message);
282
- (_a = props.onMessageRetry) === null || _a === void 0 ? void 0 : _a.call(props, message);
283
318
  };
284
319
  const markMessagesAsRead = (chatId) => {
285
320
  emit('mark-messages-read', chatId);
286
321
  };
287
322
  const handleFilterChange = (filter) => {
288
- var _a;
289
323
  emit('filter-change', filter);
290
- (_a = props.onFilterChange) === null || _a === void 0 ? void 0 : _a.call(props, filter);
291
324
  };
292
- const handleLoadMoreChats = (offset, limit) => {
293
- var _a;
294
- emit('load-more-chats', { offset, limit });
295
- (_a = props.onLoadMoreChats) === null || _a === void 0 ? void 0 : _a.call(props, offset, limit);
325
+ const handleFooterInputChange = (value, chatId) => {
326
+ emit('footer-input-change', value, chatId);
296
327
  };
297
328
  const handleNetworkError = (error) => {
298
- var _a;
299
329
  emit('network-error', error);
300
- (_a = props.onNetworkError) === null || _a === void 0 ? void 0 : _a.call(props, error);
301
330
  };
302
331
  const handleUploadError = (error) => {
303
- var _a;
304
332
  emit('upload-error', error);
305
- (_a = props.onUploadError) === null || _a === void 0 ? void 0 : _a.call(props, error);
306
333
  };
307
334
  const handleSendError = (error) => {
308
- var _a;
309
335
  emit('send-error', error);
310
- (_a = props.onSendError) === null || _a === void 0 ? void 0 : _a.call(props, error);
311
336
  };
312
337
  const mergedInputPlaceholderRef = (0, vue_1.computed)(() => {
313
338
  var _a;
@@ -320,6 +345,8 @@ exports.default = (0, vue_1.defineComponent)({
320
345
  const mergedRetryTextRef = (0, vue_1.computed)(() => { var _a; return (_a = props.retryText) !== null && _a !== void 0 ? _a : localeRef.value.retryText; });
321
346
  const mergedTypingTextRef = (0, vue_1.computed)(() => { var _a; return (_a = props.typingText) !== null && _a !== void 0 ? _a : localeRef.value.typingText; });
322
347
  const mergedCloseButtonTextRef = (0, vue_1.computed)(() => { var _a; return (_a = props.closeButtonText) !== null && _a !== void 0 ? _a : localeRef.value.closeButtonText; });
348
+ const mergedShareButtonTooltipRef = (0, vue_1.computed)(() => { var _a; return (_a = props.shareButtonTooltip) !== null && _a !== void 0 ? _a : localeRef.value.shareButtonTooltip; });
349
+ const mergedProfileButtonTooltipRef = (0, vue_1.computed)(() => { var _a; return (_a = props.profileButtonTooltip) !== null && _a !== void 0 ? _a : localeRef.value.profileButtonTooltip; });
323
350
  const mergedUnreadNotificationTextRef = (0, vue_1.computed)(() => { var _a; return (_a = props.unreadNotificationText) !== null && _a !== void 0 ? _a : localeRef.value.unreadNotificationText; });
324
351
  (0, vue_1.provide)(interface_1.chatInjectionKey, {
325
352
  mergedClsPrefixRef,
@@ -341,6 +368,11 @@ exports.default = (0, vue_1.defineComponent)({
341
368
  emptyPropsRef: (0, vue_1.toRef)(props, 'emptyProps'),
342
369
  headerButtonPropsRef: (0, vue_1.toRef)(props, 'headerButtonProps'),
343
370
  headerIconPropsRef: (0, vue_1.toRef)(props, 'headerIconProps'),
371
+ headerShareButtonPropsRef: (0, vue_1.toRef)(props, 'headerShareButtonProps'),
372
+ headerProfileButtonPropsRef: (0, vue_1.toRef)(props, 'headerProfileButtonProps'),
373
+ headerCloseButtonPropsRef: (0, vue_1.toRef)(props, 'headerCloseButtonProps'),
374
+ headerShareIconPropsRef: (0, vue_1.toRef)(props, 'headerShareIconProps'),
375
+ headerProfileIconPropsRef: (0, vue_1.toRef)(props, 'headerProfileIconProps'),
344
376
  messageSenderAvatarPropsRef: (0, vue_1.toRef)(props, 'messageSenderAvatarProps'),
345
377
  messageUploadPropsRef: (0, vue_1.toRef)(props, 'messageUploadProps'),
346
378
  messageButtonPropsRef: (0, vue_1.toRef)(props, 'messageButtonProps'),
@@ -353,6 +385,8 @@ exports.default = (0, vue_1.defineComponent)({
353
385
  retryTextRef: mergedRetryTextRef,
354
386
  typingTextRef: mergedTypingTextRef,
355
387
  closeButtonTextRef: mergedCloseButtonTextRef,
388
+ shareButtonTooltipRef: mergedShareButtonTooltipRef,
389
+ profileButtonTooltipRef: mergedProfileButtonTooltipRef,
356
390
  unreadNotificationTextRef: mergedUnreadNotificationTextRef,
357
391
  notificationsShownSetRef: notificationsShownSet,
358
392
  unreadCountsBeforeReadRef: unreadCountsBeforeRead,
@@ -362,20 +396,37 @@ exports.default = (0, vue_1.defineComponent)({
362
396
  handleMessageRetry,
363
397
  markMessagesAsRead,
364
398
  handleFilterChange,
365
- handleLoadMoreChats,
399
+ handleFooterInputChange,
366
400
  handleNetworkError,
367
401
  handleUploadError,
368
402
  handleSendError,
369
403
  onChatClose: (0, vue_1.toRef)(props, 'onChatClose'),
370
404
  onChatShare: (0, vue_1.toRef)(props, 'onChatShare'),
371
- onUserProfile: (0, vue_1.toRef)(props, 'onUserProfile')
405
+ onUserProfile: (0, vue_1.toRef)(props, 'onUserProfile'),
406
+ onChatItemsScrollToTop: (0, vue_1.toRef)(props, 'onChatItemsScrollToTop'),
407
+ onChatItemsScrollToBottom: (0, vue_1.toRef)(props, 'onChatItemsScrollToBottom'),
408
+ onMessagesScrollToTop: (0, vue_1.toRef)(props, 'onMessagesScrollToTop'),
409
+ onMessagesScrollToBottom: (0, vue_1.toRef)(props, 'onMessagesScrollToBottom')
410
+ });
411
+ const mainAreaRef = (0, vue_1.ref)(null);
412
+ const scrollToBottom = () => {
413
+ var _a;
414
+ (_a = mainAreaRef.value) === null || _a === void 0 ? void 0 : _a.scrollToBottom();
415
+ };
416
+ const sendMessage = (content, attachments) => {
417
+ handleMessageSend(content, attachments);
418
+ };
419
+ expose({
420
+ scrollToBottom,
421
+ sendMessage
372
422
  });
373
423
  return {
374
424
  mergedClsPrefix: mergedClsPrefixRef,
375
425
  mergedTheme: themeRef,
376
426
  cssVars: cssVarsRef,
377
427
  themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
378
- onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender
428
+ onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender,
429
+ mainAreaRef
379
430
  };
380
431
  },
381
432
  render() {
@@ -398,7 +449,7 @@ exports.default = (0, vue_1.defineComponent)({
398
449
  ]),
399
450
  this.selectedChatId &&
400
451
  (0, _utils_1.resolveSlot)($slots.default, () => [
401
- (0, vue_1.h)(MainArea_1.default, null, {
452
+ (0, vue_1.h)(MainArea_1.default, { ref: "mainAreaRef" }, {
402
453
  headerActions: $slots.headerActions
403
454
  })
404
455
  ])))
@@ -23,21 +23,21 @@ exports.default = (0, vue_1.defineComponent)({
23
23
  }
24
24
  },
25
25
  setup(props, { slots }) {
26
- const getThumbnailUrl = (att) => {
27
- const url = [att.preview, att.thumbnail].find((value) => typeof value === 'string');
26
+ const getThumbnailUrl = (attachment) => {
27
+ const url = [attachment.preview, attachment.thumbnail].find((value) => typeof value === 'string');
28
28
  return url !== null && url !== void 0 ? url : null;
29
29
  };
30
30
  const renderAttachment = () => {
31
- const fileList = props.attachments.map((att, index) => {
31
+ const fileList = props.attachments.map((attachment, index) => {
32
32
  var _a, _b, _c;
33
33
  return ({
34
34
  id: `${String(props.message.id)}-attachment-${index}`,
35
- name: att.name,
36
- status: att.status || 'finished',
37
- percentage: (_a = att.percentage) !== null && _a !== void 0 ? _a : null,
38
- url: (_b = att.url) !== null && _b !== void 0 ? _b : null,
39
- thumbnailUrl: getThumbnailUrl(att),
40
- type: (_c = att.type) !== null && _c !== void 0 ? _c : null,
35
+ name: attachment.name,
36
+ status: attachment.status || 'finished',
37
+ percentage: (_a = attachment.percentage) !== null && _a !== void 0 ? _a : null,
38
+ url: (_b = attachment.url) !== null && _b !== void 0 ? _b : null,
39
+ thumbnailUrl: getThumbnailUrl(attachment),
40
+ type: (_c = attachment.type) !== null && _c !== void 0 ? _c : null,
41
41
  file: null,
42
42
  batchId: null
43
43
  });
@@ -49,7 +49,9 @@ exports.default = (0, vue_1.defineComponent)({
49
49
  gap: '2px',
50
50
  marginTop: '0'
51
51
  }
52
- : undefined, showRemoveButton: false, showDownloadButton: props.attachments.some((att) => att.status === 'finished'), showRetryButton: props.attachments.some((att) => att.status === 'error') }, props.uploadProps), {
52
+ : undefined, showRemoveButton: false, showDownloadButton: props.attachments.some((attachment) => attachment.status === 'finished' &&
53
+ attachment.url &&
54
+ attachment.url !== '#'), showRetryButton: props.attachments.some((attachment) => attachment.status === 'error') }, props.uploadProps), {
53
55
  default: () => ((0, vue_1.h)(upload_1.UUploadFileList, null, {
54
56
  'upload-file-title': slots['upload-file-title']
55
57
  ? ({ file }) => { var _a; return (_a = slots['upload-file-title']) === null || _a === void 0 ? void 0 : _a.call(slots, file); }
@@ -58,8 +60,8 @@ exports.default = (0, vue_1.defineComponent)({
58
60
  ? ({ file }) => { var _a; return (_a = slots['upload-file-subtitle']) === null || _a === void 0 ? void 0 : _a.call(slots, file); }
59
61
  : ({ file }) => {
60
62
  var _a;
61
- const att = props.attachments.find((a) => a.name === file.name);
62
- return ((0, vue_1.h)("span", { style: { fontSize: '12px', color: '#999' } }, (att === null || att === void 0 ? void 0 : att.size) || ((_a = file.file) === null || _a === void 0 ? void 0 : _a.size)));
63
+ const attachment = props.attachments.find((attachment) => attachment.name === file.name);
64
+ return ((0, vue_1.h)("span", { style: { fontSize: '12px', color: '#999' } }, (attachment === null || attachment === void 0 ? void 0 : attachment.size) || ((_a = file.file) === null || _a === void 0 ? void 0 : _a.size)));
63
65
  }
64
66
  }))
65
67
  }));
@@ -8,6 +8,7 @@ declare const _default: import("vue").DefineComponent<{}, {
8
8
  inputRef: import("vue").Ref<HTMLInputElement | undefined>;
9
9
  inputValue: import("vue").Ref<string>;
10
10
  handleSendMessage: () => Promise<void>;
11
+ handleMessagesScroll: (e: Event) => void;
11
12
  scrollToBottom: () => void;
12
13
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
13
14
  export default _default;
@@ -18,24 +18,27 @@ const input_1 = require("../../../input");
18
18
  const button_1 = require("../../../button");
19
19
  const icon_1 = require("../../../icon");
20
20
  const scrollbar_1 = require("../../../scrollbar");
21
+ const tooltip_1 = require("../../../tooltip");
21
22
  const upload_1 = require("../../../upload");
22
23
  const flex_1 = require("../../../flex");
23
24
  const _utils_1 = require("../../../_utils");
24
25
  const typography_1 = require("../../../typography");
25
26
  const ChatMessages_1 = __importDefault(require("../ChatMessages"));
26
27
  const icons_1 = require("../../../_internal/icons");
27
- const SCROLL_DELAY = 50;
28
28
  const SENDING_DELAY = 100;
29
29
  exports.default = (0, vue_1.defineComponent)({
30
30
  name: 'ChatMainArea',
31
31
  setup(_, { slots }) {
32
- const { mergedClsPrefixRef, mergedThemeRef, selectedChatRef, messagesRef, typingChatIdsRef, messagesLoadingRef, messagesLoadingCountRef, headerButtonPropsRef, headerIconPropsRef, messageUploadPropsRef, footerInputPropsRef, footerButtonPropsRef, footerUploadPropsRef, footerIconPropsRef, inputPlaceholderRef, retryTextRef, typingTextRef, closeButtonTextRef, unreadNotificationTextRef, notificationsShownSetRef, unreadCountsBeforeReadRef, markNotificationShown, handleMessageSend, handleMessageRetry, onChatClose, onChatShare, onUserProfile
32
+ const { mergedClsPrefixRef, mergedThemeRef, selectedChatRef, messagesRef, typingChatIdsRef, messagesLoadingRef, messagesLoadingCountRef, headerButtonPropsRef, headerIconPropsRef, headerShareButtonPropsRef, headerProfileButtonPropsRef, headerCloseButtonPropsRef, headerShareIconPropsRef, headerProfileIconPropsRef, messageUploadPropsRef, footerInputPropsRef, footerButtonPropsRef, footerUploadPropsRef, footerIconPropsRef, inputPlaceholderRef, retryTextRef, typingTextRef, closeButtonTextRef, shareButtonTooltipRef, profileButtonTooltipRef, unreadNotificationTextRef, notificationsShownSetRef, unreadCountsBeforeReadRef, markNotificationShown, handleMessageSend, handleMessageRetry, handleFooterInputChange, onChatClose, onChatShare, onUserProfile, onMessagesScrollToTop, onMessagesScrollToBottom
33
33
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
34
34
  } = (0, vue_1.inject)(interface_1.chatInjectionKey);
35
35
  const messagesBodyRef = (0, vue_1.ref)();
36
36
  const inputRef = (0, vue_1.ref)();
37
37
  const inputValue = (0, vue_1.ref)('');
38
38
  const attachmentFileList = (0, vue_1.ref)([]);
39
+ const lastScrollTop = (0, vue_1.ref)(0);
40
+ const scrollTopFired = (0, vue_1.ref)(false);
41
+ const scrollBottomFired = (0, vue_1.ref)(false);
39
42
  const unreadMessagesCount = (0, vue_1.computed)(() => {
40
43
  if (!messagesRef.value)
41
44
  return 0;
@@ -46,12 +49,17 @@ exports.default = (0, vue_1.defineComponent)({
46
49
  const unreadCountOnOpen = (0, vue_1.ref)(0);
47
50
  const chatInputs = (0, vue_1.ref)({});
48
51
  const lastMessageId = (0, vue_1.ref)(null);
52
+ const shouldScrollOnLoad = (0, vue_1.ref)(false);
49
53
  (0, vue_1.watch)(selectedChatRef, (newChat, oldChat) => {
50
54
  if (newChat && newChat.id !== (oldChat === null || oldChat === void 0 ? void 0 : oldChat.id)) {
51
55
  inputValue.value = chatInputs.value[newChat.id] || '';
52
56
  const unreadBeforeRead = unreadCountsBeforeReadRef.value[newChat.id] || 0;
53
57
  unreadCountOnOpen.value = unreadBeforeRead;
54
58
  lastMessageId.value = null;
59
+ lastScrollTop.value = 0;
60
+ scrollTopFired.value = false;
61
+ scrollBottomFired.value = false;
62
+ shouldScrollOnLoad.value = true;
55
63
  if (unreadBeforeRead > 0 &&
56
64
  !notificationsShownSetRef.value.has(newChat.id)) {
57
65
  hasUnreadMessages.value = true;
@@ -62,12 +70,6 @@ exports.default = (0, vue_1.defineComponent)({
62
70
  hasUnreadMessages.value = false;
63
71
  showNotificationManually.value = false;
64
72
  }
65
- void (0, vue_1.nextTick)(() => {
66
- scrollToBottom();
67
- });
68
- setTimeout(() => {
69
- scrollToBottom();
70
- }, SCROLL_DELAY);
71
73
  }
72
74
  }, { immediate: true });
73
75
  (0, vue_1.watch)(messagesRef, (newMessages) => {
@@ -77,19 +79,18 @@ exports.default = (0, vue_1.defineComponent)({
77
79
  }
78
80
  const currentLastMessage = newMessages[newMessages.length - 1];
79
81
  const currentLastId = currentLastMessage === null || currentLastMessage === void 0 ? void 0 : currentLastMessage.id;
80
- if (currentLastId !== lastMessageId.value &&
81
- lastMessageId.value !== null) {
82
+ const hasLastMessageChanged = currentLastId !== lastMessageId.value;
83
+ if (hasLastMessageChanged &&
84
+ currentLastMessage &&
85
+ !currentLastMessage.isOwn &&
86
+ currentLastMessage.status === interface_1.MessageStatus.UNREAD) {
87
+ unreadCountOnOpen.value = unreadMessagesCount.value;
88
+ }
89
+ if (shouldScrollOnLoad.value && newMessages.length > 0) {
90
+ shouldScrollOnLoad.value = false;
82
91
  void (0, vue_1.nextTick)(() => {
83
92
  scrollToBottom();
84
93
  });
85
- setTimeout(() => {
86
- scrollToBottom();
87
- }, SCROLL_DELAY);
88
- if (currentLastMessage &&
89
- !currentLastMessage.isOwn &&
90
- currentLastMessage.status === interface_1.MessageStatus.UNREAD) {
91
- unreadCountOnOpen.value = unreadMessagesCount.value;
92
- }
93
94
  }
94
95
  lastMessageId.value = currentLastId !== null && currentLastId !== void 0 ? currentLastId : null;
95
96
  }, { deep: true, flush: 'post' });
@@ -102,17 +103,42 @@ exports.default = (0, vue_1.defineComponent)({
102
103
  notificationsShownSetRef.value = newSet;
103
104
  }
104
105
  });
106
+ (0, vue_1.watch)(inputValue, (newValue) => {
107
+ if (selectedChatRef.value) {
108
+ handleFooterInputChange(newValue, selectedChatRef.value.id);
109
+ }
110
+ });
105
111
  const showUnreadNotification = (0, vue_1.computed)(() => {
106
112
  return hasUnreadMessages.value && showNotificationManually.value;
107
113
  });
108
- (0, vue_1.onMounted)(() => {
109
- void (0, vue_1.nextTick)(() => {
110
- scrollToBottom();
111
- });
112
- setTimeout(() => {
113
- scrollToBottom();
114
- }, SCROLL_DELAY);
115
- });
114
+ const handleMessagesScroll = (e) => {
115
+ var _a, _b;
116
+ const target = e.target;
117
+ if (!target)
118
+ return;
119
+ const { scrollTop, scrollHeight, clientHeight } = target;
120
+ const threshold = 5;
121
+ const scrollDirection = scrollTop > lastScrollTop.value ? 'down' : 'up';
122
+ const nearTop = scrollTop <= threshold;
123
+ const nearBottom = scrollHeight - (scrollTop + clientHeight) <= threshold;
124
+ if (scrollTop > threshold) {
125
+ scrollTopFired.value = false;
126
+ }
127
+ if (scrollHeight - (scrollTop + clientHeight) > threshold) {
128
+ scrollBottomFired.value = false;
129
+ }
130
+ if (nearTop && scrollDirection === 'up' && !scrollTopFired.value) {
131
+ scrollTopFired.value = true;
132
+ (_a = onMessagesScrollToTop === null || onMessagesScrollToTop === void 0 ? void 0 : onMessagesScrollToTop.value) === null || _a === void 0 ? void 0 : _a.call(onMessagesScrollToTop);
133
+ }
134
+ if (nearBottom &&
135
+ scrollDirection === 'down' &&
136
+ !scrollBottomFired.value) {
137
+ scrollBottomFired.value = true;
138
+ (_b = onMessagesScrollToBottom === null || onMessagesScrollToBottom === void 0 ? void 0 : onMessagesScrollToBottom.value) === null || _b === void 0 ? void 0 : _b.call(onMessagesScrollToBottom);
139
+ }
140
+ lastScrollTop.value = scrollTop;
141
+ };
116
142
  const scrollToBottom = () => {
117
143
  const el = messagesBodyRef.value;
118
144
  if (!el)
@@ -134,27 +160,50 @@ exports.default = (0, vue_1.defineComponent)({
134
160
  };
135
161
  const renderHeader = () => {
136
162
  return ((0, vue_1.h)("div", { class: `${mergedClsPrefixRef.value}-chat-main__header` },
137
- (0, vue_1.h)(flex_1.UFlex, { justify: "space-between", align: "flex-start" }, {
163
+ (0, vue_1.h)(flex_1.UFlex, { justify: "space-between", align: "flex-start", wrap: false }, {
138
164
  default: () => ((0, vue_1.h)(vue_1.Fragment, null,
139
165
  (0, vue_1.h)(typography_1.UText, { variant: "heading-s-bold", class: `${mergedClsPrefixRef.value}-chat-main__header-title`, theme: mergedThemeRef.value.peers.Typography, themeOverrides: mergedThemeRef.value.peerOverrides.Typography }, {
140
- default: () => { var _a; return ((_a = selectedChatRef.value) === null || _a === void 0 ? void 0 : _a.title) || 'Select a chat'; }
166
+ default: () => { var _a, _b; return (_b = (_a = selectedChatRef.value) === null || _a === void 0 ? void 0 : _a.title) !== null && _b !== void 0 ? _b : ''; }
141
167
  }),
142
168
  (0, vue_1.h)(flex_1.UFlex, { align: "center", size: "small", class: `${mergedClsPrefixRef.value}-chat-main__header-actions` }, {
143
- default: () => (0, _utils_1.resolveSlot)(slots.headerActions, () => [
144
- (0, vue_1.h)(button_1.UButton, Object.assign({ secondary: true, circle: true, size: "large" }, headerButtonPropsRef.value, { theme: mergedThemeRef.value.peers.Button, themeOverrides: mergedThemeRef.value.peerOverrides.Button, onClick: () => { var _a; return (_a = onChatShare === null || onChatShare === void 0 ? void 0 : onChatShare.value) === null || _a === void 0 ? void 0 : _a.call(onChatShare); } }), {
145
- default: () => ((0, vue_1.h)(icon_1.UIcon, Object.assign({ size: 20 }, headerIconPropsRef.value, { theme: mergedThemeRef.value.peers.Icon, themeOverrides: mergedThemeRef.value.peerOverrides.Icon }), {
146
- default: () => (0, vue_1.h)(icons_1.ArrowHookUpRight, null)
147
- }))
148
- }),
149
- (0, vue_1.h)(button_1.UButton, Object.assign({ secondary: true, circle: true, size: "large" }, headerButtonPropsRef.value, { theme: mergedThemeRef.value.peers.Button, themeOverrides: mergedThemeRef.value.peerOverrides.Button, onClick: () => { var _a; return (_a = onUserProfile === null || onUserProfile === void 0 ? void 0 : onUserProfile.value) === null || _a === void 0 ? void 0 : _a.call(onUserProfile); } }), {
150
- default: () => ((0, vue_1.h)(icon_1.UIcon, Object.assign({ size: 20 }, headerIconPropsRef.value, { theme: mergedThemeRef.value.peers.Icon, themeOverrides: mergedThemeRef.value.peerOverrides.Icon }), {
151
- default: () => (0, vue_1.h)(icons_1.PersonNote, null)
152
- }))
153
- }),
154
- (0, vue_1.h)(button_1.UButton, Object.assign({ type: "primary", size: "large", round: true }, headerButtonPropsRef.value, { theme: mergedThemeRef.value.peers.Button, themeOverrides: mergedThemeRef.value.peerOverrides.Button, onClick: () => { var _a; return (_a = onChatClose === null || onChatClose === void 0 ? void 0 : onChatClose.value) === null || _a === void 0 ? void 0 : _a.call(onChatClose); } }), {
155
- default: () => closeButtonTextRef.value
156
- })
157
- ])
169
+ default: () => (0, _utils_1.resolveSlot)(slots.headerActions, () => {
170
+ const shareButtonProps = Object.assign(Object.assign({}, headerButtonPropsRef.value), headerShareButtonPropsRef.value);
171
+ const profileButtonProps = Object.assign(Object.assign({}, headerButtonPropsRef.value), headerProfileButtonPropsRef.value);
172
+ const closeButtonProps = Object.assign(Object.assign({}, headerButtonPropsRef.value), headerCloseButtonPropsRef.value);
173
+ const shareIconProps = Object.assign(Object.assign({}, headerIconPropsRef.value), headerShareIconPropsRef.value);
174
+ const profileIconProps = Object.assign(Object.assign({}, headerIconPropsRef.value), headerProfileIconPropsRef.value);
175
+ const buttons = [];
176
+ if (shareButtonProps.disabled !== true) {
177
+ buttons.push((0, vue_1.h)(tooltip_1.UTooltip, null, {
178
+ trigger: () => ((0, vue_1.h)(button_1.UButton, Object.assign({ secondary: true, circle: true, size: "large" }, shareButtonProps, { theme: mergedThemeRef.value.peers.Button, themeOverrides: mergedThemeRef.value.peerOverrides
179
+ .Button, onClick: () => { var _a; return (_a = onChatShare === null || onChatShare === void 0 ? void 0 : onChatShare.value) === null || _a === void 0 ? void 0 : _a.call(onChatShare); } }), {
180
+ default: () => ((0, vue_1.h)(icon_1.UIcon, Object.assign({ size: 20 }, shareIconProps, { theme: mergedThemeRef.value.peers.Icon, themeOverrides: mergedThemeRef.value.peerOverrides
181
+ .Icon }), {
182
+ default: () => ((0, vue_1.h)(icons_1.ArrowHookUpRight, null))
183
+ }))
184
+ })),
185
+ default: () => shareButtonTooltipRef.value
186
+ }));
187
+ }
188
+ if (profileButtonProps.disabled !== true) {
189
+ buttons.push((0, vue_1.h)(tooltip_1.UTooltip, null, {
190
+ trigger: () => ((0, vue_1.h)(button_1.UButton, Object.assign({ secondary: true, circle: true, size: "large" }, profileButtonProps, { theme: mergedThemeRef.value.peers.Button, themeOverrides: mergedThemeRef.value.peerOverrides
191
+ .Button, onClick: () => { var _a; return (_a = onUserProfile === null || onUserProfile === void 0 ? void 0 : onUserProfile.value) === null || _a === void 0 ? void 0 : _a.call(onUserProfile); } }), {
192
+ default: () => ((0, vue_1.h)(icon_1.UIcon, Object.assign({ size: 20 }, profileIconProps, { theme: mergedThemeRef.value.peers.Icon, themeOverrides: mergedThemeRef.value.peerOverrides
193
+ .Icon }), {
194
+ default: () => (0, vue_1.h)(icons_1.PersonNote, null)
195
+ }))
196
+ })),
197
+ default: () => profileButtonTooltipRef.value
198
+ }));
199
+ }
200
+ if (closeButtonProps.disabled !== true) {
201
+ buttons.push((0, vue_1.h)(button_1.UButton, Object.assign({ type: "primary", size: "large", round: true }, closeButtonProps, { theme: mergedThemeRef.value.peers.Button, themeOverrides: mergedThemeRef.value.peerOverrides.Button, onClick: () => { var _a; return (_a = onChatClose === null || onChatClose === void 0 ? void 0 : onChatClose.value) === null || _a === void 0 ? void 0 : _a.call(onChatClose); } }), {
202
+ default: () => closeButtonTextRef.value
203
+ }));
204
+ }
205
+ return buttons;
206
+ })
158
207
  })))
159
208
  })));
160
209
  };
@@ -201,12 +250,6 @@ exports.default = (0, vue_1.defineComponent)({
201
250
  chatInputs.value[selectedChatRef.value.id] = '';
202
251
  hasUnreadMessages.value = false;
203
252
  showNotificationManually.value = false;
204
- void (0, vue_1.nextTick)(() => {
205
- scrollToBottom();
206
- });
207
- setTimeout(() => {
208
- scrollToBottom();
209
- }, SCROLL_DELAY);
210
253
  }
211
254
  finally {
212
255
  setTimeout(() => {
@@ -246,12 +289,6 @@ exports.default = (0, vue_1.defineComponent)({
246
289
  handleMessageSend('', attachments);
247
290
  pendingFiles.value = [];
248
291
  attachmentFileList.value = [];
249
- void (0, vue_1.nextTick)(() => {
250
- scrollToBottom();
251
- });
252
- setTimeout(() => {
253
- scrollToBottom();
254
- }, SCROLL_DELAY);
255
292
  }
256
293
  }, SENDING_DELAY);
257
294
  }
@@ -291,6 +328,7 @@ exports.default = (0, vue_1.defineComponent)({
291
328
  inputRef,
292
329
  inputValue,
293
330
  handleSendMessage,
331
+ handleMessagesScroll,
294
332
  scrollToBottom
295
333
  };
296
334
  },
@@ -299,7 +337,7 @@ exports.default = (0, vue_1.defineComponent)({
299
337
  const { mergedClsPrefixRef } = (0, vue_1.inject)(interface_1.chatInjectionKey);
300
338
  return ((0, vue_1.h)("div", { class: `${mergedClsPrefixRef.value}-chat-main` },
301
339
  this.renderHeader(),
302
- (0, vue_1.h)(scrollbar_1.UScrollbar, { ref: "messagesBodyRef", class: `${mergedClsPrefixRef.value}-chat-main__body` }, {
340
+ (0, vue_1.h)(scrollbar_1.UScrollbar, { ref: "messagesBodyRef", class: `${mergedClsPrefixRef.value}-chat-main__body`, onScroll: this.handleMessagesScroll }, {
303
341
  default: () => this.renderMessages()
304
342
  }),
305
343
  this.renderFooter()));