@uzum-tech/ui 1.10.1 → 1.11.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 (91) hide show
  1. package/dist/index.js +1248 -263
  2. package/dist/index.prod.js +3 -3
  3. package/es/_internal/index.d.ts +2 -0
  4. package/es/_internal/index.js +1 -0
  5. package/es/_internal/safe-top-scrollbar/index.d.ts +2 -0
  6. package/es/_internal/safe-top-scrollbar/index.js +1 -0
  7. package/es/_internal/safe-top-scrollbar/src/SafeTopScrollbar.d.ts +356 -0
  8. package/es/_internal/safe-top-scrollbar/src/SafeTopScrollbar.js +708 -0
  9. package/es/_internal/safe-top-scrollbar/src/styles/index.cssr.d.ts +2 -0
  10. package/es/_internal/safe-top-scrollbar/src/styles/index.cssr.js +80 -0
  11. package/es/_internal/safe-top-scrollbar/src/styles/rtl.cssr.d.ts +2 -0
  12. package/es/_internal/safe-top-scrollbar/src/styles/rtl.cssr.js +10 -0
  13. package/es/_internal/safe-top-scrollbar/styles/common.d.ts +7 -0
  14. package/es/_internal/safe-top-scrollbar/styles/common.js +7 -0
  15. package/es/_internal/safe-top-scrollbar/styles/dark.d.ts +3 -0
  16. package/es/_internal/safe-top-scrollbar/styles/dark.js +8 -0
  17. package/es/_internal/safe-top-scrollbar/styles/index.d.ts +4 -0
  18. package/es/_internal/safe-top-scrollbar/styles/index.js +3 -0
  19. package/es/_internal/safe-top-scrollbar/styles/light.d.ts +18 -0
  20. package/es/_internal/safe-top-scrollbar/styles/light.js +12 -0
  21. package/es/_internal/safe-top-scrollbar/styles/rtl.d.ts +3 -0
  22. package/es/_internal/safe-top-scrollbar/styles/rtl.js +6 -0
  23. package/es/chat/src/Chat.d.ts +14 -1
  24. package/es/chat/src/Chat.js +5 -0
  25. package/es/chat/src/ChatParts/ChatAttachment.js +31 -3
  26. package/es/chat/src/ChatParts/MainArea.js +37 -41
  27. package/es/chat/src/interface.d.ts +6 -2
  28. package/es/components.d.ts +1 -0
  29. package/es/components.js +1 -0
  30. package/es/config-provider/src/internal-interface.d.ts +2 -0
  31. package/es/drawer/src/Drawer.d.ts +18 -0
  32. package/es/drawer/src/Drawer.js +28 -26
  33. package/es/drawer/src/DrawerBodyWrapper.d.ts +8 -0
  34. package/es/drawer/src/DrawerBodyWrapper.js +36 -8
  35. package/es/modal-fullscreen/src/ModalFull.d.ts +2 -2
  36. package/es/modal-fullscreen/src/ModalFull.js +31 -24
  37. package/es/modal-fullscreen/src/styles/index.cssr.js +11 -11
  38. package/es/safe-top-scrollbar/index.d.ts +2 -0
  39. package/es/safe-top-scrollbar/index.js +1 -0
  40. package/es/safe-top-scrollbar/src/SafeTopScrollbar.d.ts +177 -0
  41. package/es/safe-top-scrollbar/src/SafeTopScrollbar.js +38 -0
  42. package/es/themes/dark.js +2 -0
  43. package/es/themes/light.js +2 -0
  44. package/es/version.d.ts +1 -1
  45. package/es/version.js +1 -1
  46. package/lib/_internal/index.d.ts +2 -0
  47. package/lib/_internal/index.js +4 -1
  48. package/lib/_internal/safe-top-scrollbar/index.d.ts +2 -0
  49. package/lib/_internal/safe-top-scrollbar/index.js +9 -0
  50. package/lib/_internal/safe-top-scrollbar/src/SafeTopScrollbar.d.ts +356 -0
  51. package/lib/_internal/safe-top-scrollbar/src/SafeTopScrollbar.js +714 -0
  52. package/lib/_internal/safe-top-scrollbar/src/styles/index.cssr.d.ts +2 -0
  53. package/lib/_internal/safe-top-scrollbar/src/styles/index.cssr.js +85 -0
  54. package/lib/_internal/safe-top-scrollbar/src/styles/rtl.cssr.d.ts +2 -0
  55. package/lib/_internal/safe-top-scrollbar/src/styles/rtl.cssr.js +15 -0
  56. package/lib/_internal/safe-top-scrollbar/styles/common.d.ts +7 -0
  57. package/lib/_internal/safe-top-scrollbar/styles/common.js +10 -0
  58. package/lib/_internal/safe-top-scrollbar/styles/dark.d.ts +3 -0
  59. package/lib/_internal/safe-top-scrollbar/styles/dark.js +10 -0
  60. package/lib/_internal/safe-top-scrollbar/styles/index.d.ts +4 -0
  61. package/lib/_internal/safe-top-scrollbar/styles/index.js +12 -0
  62. package/lib/_internal/safe-top-scrollbar/styles/light.d.ts +18 -0
  63. package/lib/_internal/safe-top-scrollbar/styles/light.js +16 -0
  64. package/lib/_internal/safe-top-scrollbar/styles/rtl.d.ts +3 -0
  65. package/lib/_internal/safe-top-scrollbar/styles/rtl.js +12 -0
  66. package/lib/chat/src/Chat.d.ts +14 -1
  67. package/lib/chat/src/Chat.js +5 -0
  68. package/lib/chat/src/ChatParts/ChatAttachment.js +30 -2
  69. package/lib/chat/src/ChatParts/MainArea.js +37 -41
  70. package/lib/chat/src/interface.d.ts +6 -2
  71. package/lib/components.d.ts +1 -0
  72. package/lib/components.js +1 -0
  73. package/lib/config-provider/src/internal-interface.d.ts +2 -0
  74. package/lib/drawer/src/Drawer.d.ts +18 -0
  75. package/lib/drawer/src/Drawer.js +28 -26
  76. package/lib/drawer/src/DrawerBodyWrapper.d.ts +8 -0
  77. package/lib/drawer/src/DrawerBodyWrapper.js +36 -8
  78. package/lib/modal-fullscreen/src/ModalFull.d.ts +2 -2
  79. package/lib/modal-fullscreen/src/ModalFull.js +30 -23
  80. package/lib/modal-fullscreen/src/styles/index.cssr.js +11 -11
  81. package/lib/safe-top-scrollbar/index.d.ts +2 -0
  82. package/lib/safe-top-scrollbar/index.js +9 -0
  83. package/lib/safe-top-scrollbar/src/SafeTopScrollbar.d.ts +177 -0
  84. package/lib/safe-top-scrollbar/src/SafeTopScrollbar.js +41 -0
  85. package/lib/themes/dark.js +5 -0
  86. package/lib/themes/light.js +5 -0
  87. package/lib/version.d.ts +1 -1
  88. package/lib/version.js +1 -1
  89. package/package.json +1 -1
  90. package/volar.d.ts +1 -0
  91. package/web-types.json +58 -2
@@ -0,0 +1,2 @@
1
+ declare const _default: import("css-render").CNode;
2
+ export default _default;
@@ -0,0 +1,80 @@
1
+ import { fadeInTransition } from '../../../../_styles/transitions/fade-in.cssr';
2
+ import { c, cB, cE, cM } from '../../../../_utils/cssr';
3
+ // vars:
4
+ // --u-scrollbar-bezier
5
+ // --u-scrollbar-color
6
+ // --u-scrollbar-color-hover
7
+ // --u-scrollbar-width
8
+ // --u-scrollbar-height
9
+ // --u-scrollbar-border-radius
10
+ // --u-scrollbar-rail-inset-horizontal
11
+ // --u-scrollbar-rail-inset-vertical
12
+ // --u-scrollbar-rail-color
13
+ export default cB('safe-top-scrollbar', `
14
+ overflow: hidden;
15
+ position: relative;
16
+ z-index: auto;
17
+ height: 100%;
18
+ width: 100%;
19
+ `, [c('>', [cB('scrollbar-container', `
20
+ width: 100%;
21
+ overflow: scroll;
22
+ height: 100%;
23
+ min-height: inherit;
24
+ max-height: inherit;
25
+ scrollbar-width: none;
26
+ `, [c('&::-webkit-scrollbar, &::-webkit-scrollbar-track-piece, &::-webkit-scrollbar-thumb', `
27
+ width: 0;
28
+ height: 0;
29
+ display: none;
30
+ `), c('>', [
31
+ // We can't set overflow hidden since it affects positioning.
32
+ cB('scrollbar-content', `
33
+ box-sizing: border-box;
34
+ min-width: 100%;
35
+ `)])])]), c('>, +', [cB('scrollbar-rail', `
36
+ position: absolute;
37
+ pointer-events: none;
38
+ user-select: none;
39
+ background: var(--u-scrollbar-rail-color);
40
+ -webkit-user-select: none;
41
+ `, [cM('horizontal', `
42
+ height: var(--u-scrollbar-height);
43
+ `, [c('>', [cE('scrollbar', `
44
+ height: var(--u-scrollbar-height);
45
+ border-radius: var(--u-scrollbar-border-radius);
46
+ right: 0;
47
+ `)])]), cM('horizontal--top', `
48
+ top: var(--u-scrollbar-rail-top-horizontal-top);
49
+ right: var(--u-scrollbar-rail-right-horizontal-top);
50
+ bottom: var(--u-scrollbar-rail-bottom-horizontal-top);
51
+ left: var(--u-scrollbar-rail-left-horizontal-top);
52
+ `), cM('horizontal--bottom', `
53
+ top: var(--u-scrollbar-rail-top-horizontal-bottom);
54
+ right: var(--u-scrollbar-rail-right-horizontal-bottom);
55
+ bottom: var(--u-scrollbar-rail-bottom-horizontal-bottom);
56
+ left: var(--u-scrollbar-rail-left-horizontal-bottom);
57
+ `), cM('vertical', `
58
+ width: var(--u-scrollbar-width);
59
+ `, [c('>', [cE('scrollbar', `
60
+ width: var(--u-scrollbar-width);
61
+ border-radius: var(--u-scrollbar-border-radius);
62
+ bottom: 0;
63
+ `)])]), cM('vertical--left', `
64
+ top: var(--u-scrollbar-rail-top-vertical-left);
65
+ right: var(--u-scrollbar-rail-right-vertical-left);
66
+ bottom: var(--u-scrollbar-rail-bottom-vertical-left);
67
+ left: var(--u-scrollbar-rail-left-vertical-left);
68
+ `), cM('vertical--right', `
69
+ top: var(--u-scrollbar-rail-top-vertical-right);
70
+ right: var(--u-scrollbar-rail-right-vertical-right);
71
+ bottom: var(--u-scrollbar-rail-bottom-vertical-right);
72
+ left: var(--u-scrollbar-rail-left-vertical-right);
73
+ `), cM('disabled', [c('>', [cE('scrollbar', 'pointer-events: none;')])]), c('>', [cE('scrollbar', `
74
+ z-index: 1;
75
+ position: absolute;
76
+ cursor: pointer;
77
+ pointer-events: all;
78
+ background-color: var(--u-scrollbar-color);
79
+ transition: background-color .2s var(--u-scrollbar-bezier);
80
+ `, [fadeInTransition(), c('&:hover', 'background-color: var(--u-scrollbar-color-hover);')])])])])]);
@@ -0,0 +1,2 @@
1
+ declare const _default: import("css-render").CNode;
2
+ export default _default;
@@ -0,0 +1,10 @@
1
+ import { cB, c, cM, cE } from '../../../../_utils/cssr';
2
+ export default cB('scrollbar', [cM('rtl', `
3
+ direction: rtl;
4
+ `, [c('>', [cB('scrollbar-rail', [cM('horizontal', [c('>', [cE('scrollbar', `
5
+ left: 0;
6
+ right: unset;
7
+ `)])]), cM('vertical', `
8
+ left: 4px;
9
+ right: unset;
10
+ `)])])])]);
@@ -0,0 +1,7 @@
1
+ export declare const commonVars: {
2
+ railInsetHorizontalBottom: string;
3
+ railInsetHorizontalTop: string;
4
+ railInsetVerticalRight: string;
5
+ railInsetVerticalLeft: string;
6
+ railColor: string;
7
+ };
@@ -0,0 +1,7 @@
1
+ export const commonVars = {
2
+ railInsetHorizontalBottom: 'auto 2px 4px 2px',
3
+ railInsetHorizontalTop: '4px 2px auto 2px',
4
+ railInsetVerticalRight: '2px 4px 2px auto',
5
+ railInsetVerticalLeft: '2px auto 2px 4px',
6
+ railColor: 'transparent'
7
+ };
@@ -0,0 +1,3 @@
1
+ import type { SafeTopScrollbarTheme } from './light';
2
+ declare const safeTopScrollbarDark: SafeTopScrollbarTheme;
3
+ export default safeTopScrollbarDark;
@@ -0,0 +1,8 @@
1
+ import { commonDark } from '../../../_styles/common';
2
+ import { self } from './light';
3
+ const safeTopScrollbarDark = {
4
+ name: 'SafeTopScrollbar',
5
+ common: commonDark,
6
+ self
7
+ };
8
+ export default safeTopScrollbarDark;
@@ -0,0 +1,4 @@
1
+ export { default as scrollbarDark } from './dark';
2
+ export { default as scrollbarLight } from './light';
3
+ export { default as scrollbarRtl } from './rtl';
4
+ export type { SafeTopScrollbarTheme, SafeTopScrollbarThemeVars } from './light';
@@ -0,0 +1,3 @@
1
+ export { default as scrollbarDark } from './dark';
2
+ export { default as scrollbarLight } from './light';
3
+ export { default as scrollbarRtl } from './rtl';
@@ -0,0 +1,18 @@
1
+ import type { ThemeCommonVars } from '../../../_styles/common';
2
+ import type { Theme } from '../../../_mixins';
3
+ export declare const self: (vars: ThemeCommonVars) => {
4
+ height: string;
5
+ width: string;
6
+ borderRadius: string;
7
+ color: string;
8
+ colorHover: string;
9
+ railInsetHorizontalBottom: string;
10
+ railInsetHorizontalTop: string;
11
+ railInsetVerticalRight: string;
12
+ railInsetVerticalLeft: string;
13
+ railColor: string;
14
+ };
15
+ export type SafeTopScrollbarThemeVars = ReturnType<typeof self>;
16
+ declare const safeTopScrollbarLight: Theme<'SafeTopScrollbar', SafeTopScrollbarThemeVars>;
17
+ export default safeTopScrollbarLight;
18
+ export type SafeTopScrollbarTheme = typeof safeTopScrollbarLight;
@@ -0,0 +1,12 @@
1
+ import { commonLight } from '../../../_styles/common';
2
+ import { commonVars } from './common';
3
+ export const self = (vars) => {
4
+ const { scrollbarColor, scrollbarColorHover, scrollbarHeight, scrollbarWidth, scrollbarBorderRadius } = vars;
5
+ return Object.assign(Object.assign({}, commonVars), { height: scrollbarHeight, width: scrollbarWidth, borderRadius: scrollbarBorderRadius, color: scrollbarColor, colorHover: scrollbarColorHover });
6
+ };
7
+ const safeTopScrollbarLight = {
8
+ name: 'SafeTopScrollbar',
9
+ common: commonLight,
10
+ self
11
+ };
12
+ export default safeTopScrollbarLight;
@@ -0,0 +1,3 @@
1
+ import type { RtlItem } from '../../../config-provider/src/internal-interface';
2
+ export declare const scrollbarRtl: RtlItem;
3
+ export default scrollbarRtl;
@@ -0,0 +1,6 @@
1
+ import rtlStyle from '../src/styles/rtl.cssr';
2
+ export const scrollbarRtl = {
3
+ name: 'SafeTopScrollbar',
4
+ style: rtlStyle
5
+ };
6
+ export default scrollbarRtl;
@@ -191,6 +191,10 @@ export declare const chatProps: {
191
191
  type: PropType<ChatPropsType["onAttachmentUpload"]>;
192
192
  default: undefined;
193
193
  };
194
+ onAttachmentDownload: {
195
+ type: PropType<ChatPropsType["onAttachmentDownload"]>;
196
+ default: undefined;
197
+ };
194
198
  onFilterChange: {
195
199
  type: PropType<ChatPropsType["onFilterChange"]>;
196
200
  default: undefined;
@@ -2413,6 +2417,10 @@ declare const _default: import("vue").DefineComponent<{
2413
2417
  type: PropType<ChatPropsType["onAttachmentUpload"]>;
2414
2418
  default: undefined;
2415
2419
  };
2420
+ onAttachmentDownload: {
2421
+ type: PropType<ChatPropsType["onAttachmentDownload"]>;
2422
+ default: undefined;
2423
+ };
2416
2424
  onFilterChange: {
2417
2425
  type: PropType<ChatPropsType["onFilterChange"]>;
2418
2426
  default: undefined;
@@ -5652,6 +5660,10 @@ declare const _default: import("vue").DefineComponent<{
5652
5660
  type: PropType<ChatPropsType["onAttachmentUpload"]>;
5653
5661
  default: undefined;
5654
5662
  };
5663
+ onAttachmentDownload: {
5664
+ type: PropType<ChatPropsType["onAttachmentDownload"]>;
5665
+ default: undefined;
5666
+ };
5655
5667
  onFilterChange: {
5656
5668
  type: PropType<ChatPropsType["onFilterChange"]>;
5657
5669
  default: undefined;
@@ -7716,6 +7728,7 @@ declare const _default: import("vue").DefineComponent<{
7716
7728
  onChatItemsScrollToBottom: () => void;
7717
7729
  messages: ChatMessageData[] | undefined;
7718
7730
  onMessageRetry: ((message: ChatMessageData) => void) | undefined;
7731
+ onAttachmentUpload: import("./interface").OnAttachmentUpload | undefined;
7719
7732
  onChatClose: () => void;
7720
7733
  onChatShare: () => void;
7721
7734
  onUserProfile: () => void;
@@ -7749,7 +7762,7 @@ declare const _default: import("vue").DefineComponent<{
7749
7762
  chatItemsLoadingCount: number | undefined;
7750
7763
  messagesLoading: boolean | undefined;
7751
7764
  messagesLoadingCount: number | undefined;
7752
- onAttachmentUpload: import("./interface").OnAttachmentUpload | undefined;
7765
+ onAttachmentDownload: import("./interface").OnAttachmentDownload | undefined;
7753
7766
  onFilterChange: import("./interface").OnFilterChange | undefined;
7754
7767
  onNetworkError: import("./interface").OnNetworkError | undefined;
7755
7768
  onUploadError: import("./interface").OnUploadError | undefined;
@@ -148,6 +148,9 @@ export const chatProps = Object.assign(Object.assign({}, useTheme.props), { chat
148
148
  }, onAttachmentUpload: {
149
149
  type: Function,
150
150
  default: undefined
151
+ }, onAttachmentDownload: {
152
+ type: Function,
153
+ default: undefined
151
154
  }, onFilterChange: {
152
155
  type: Function,
153
156
  default: undefined
@@ -394,6 +397,8 @@ export default defineComponent({
394
397
  handleNetworkError,
395
398
  handleUploadError,
396
399
  handleSendError,
400
+ onAttachmentUpload: toRef(props, 'onAttachmentUpload'),
401
+ onAttachmentDownload: toRef(props, 'onAttachmentDownload'),
397
402
  onChatClose: toRef(props, 'onChatClose'),
398
403
  onChatShare: toRef(props, 'onChatShare'),
399
404
  onUserProfile: toRef(props, 'onUserProfile'),
@@ -1,5 +1,15 @@
1
- import { h, defineComponent } from 'vue';
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { h, defineComponent, inject } from 'vue';
2
11
  import { UUpload, UUploadFileList } from '../../../upload';
12
+ import { chatInjectionKey } from '../interface';
3
13
  export default defineComponent({
4
14
  name: 'ChatAttachment',
5
15
  props: {
@@ -21,10 +31,28 @@ export default defineComponent({
21
31
  }
22
32
  },
23
33
  setup(props, { slots }) {
34
+ const UChat = inject(chatInjectionKey, null);
35
+ const onAttachmentDownload = UChat === null || UChat === void 0 ? void 0 : UChat.onAttachmentDownload;
24
36
  const getThumbnailUrl = (attachment) => {
25
37
  const url = [attachment.preview, attachment.thumbnail].find((value) => typeof value === 'string');
26
38
  return url !== null && url !== void 0 ? url : null;
27
39
  };
40
+ const handleDownload = (file) => __awaiter(this, void 0, void 0, function* () {
41
+ if (onAttachmentDownload === null || onAttachmentDownload === void 0 ? void 0 : onAttachmentDownload.value) {
42
+ const attachment = props.attachments.find((att) => att.name === file.name);
43
+ if (attachment) {
44
+ try {
45
+ yield onAttachmentDownload.value(attachment);
46
+ return false;
47
+ }
48
+ catch (error) {
49
+ console.error('Download failed:', error);
50
+ return false;
51
+ }
52
+ }
53
+ }
54
+ return true;
55
+ });
28
56
  const renderAttachment = () => {
29
57
  const fileList = props.attachments.map((attachment, index) => {
30
58
  var _a, _b, _c;
@@ -40,7 +68,7 @@ export default defineComponent({
40
68
  batchId: null
41
69
  });
42
70
  });
43
- const uploadComponent = (h(UUpload, Object.assign({ abstract: true, fileList: fileList, fileListStyle: props.withPadding
71
+ const uploadComponent = (h(UUpload, Object.assign({ abstract: true }, props.uploadProps, { fileList: fileList, fileListStyle: props.withPadding
44
72
  ? {
45
73
  display: 'flex',
46
74
  flexDirection: 'column',
@@ -49,7 +77,7 @@ export default defineComponent({
49
77
  }
50
78
  : undefined, showRemoveButton: false, showDownloadButton: props.attachments.some((attachment) => attachment.status === 'finished' &&
51
79
  attachment.url &&
52
- attachment.url !== '#'), showRetryButton: props.attachments.some((attachment) => attachment.status === 'error') }, props.uploadProps), {
80
+ attachment.url !== '#'), showRetryButton: props.attachments.some((attachment) => attachment.status === 'error'), onDownload: handleDownload }), {
53
81
  default: () => (h(UUploadFileList, null, {
54
82
  'upload-file-title': slots['upload-file-title']
55
83
  ? ({ file }) => { var _a; return (_a = slots['upload-file-title']) === null || _a === void 0 ? void 0 : _a.call(slots, file); }
@@ -12,7 +12,7 @@ import { MessageStatus, ChatMessageType, chatInjectionKey } from '../interface';
12
12
  import { UInput } from '../../../input';
13
13
  import { UButton } from '../../../button';
14
14
  import { UIcon } from '../../../icon';
15
- import { UScrollbar } from '../../../scrollbar';
15
+ import { USafeTopScrollbar } from '../../../safe-top-scrollbar';
16
16
  import { UTooltip } from '../../../tooltip';
17
17
  import { UUpload, UUploadTrigger } from '../../../upload';
18
18
  import { UFlex } from '../../../flex';
@@ -24,13 +24,14 @@ const SENDING_DELAY = 100;
24
24
  export default defineComponent({
25
25
  name: 'ChatMainArea',
26
26
  setup(_, { slots }) {
27
- 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
27
+ 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, onAttachmentUpload, onChatClose, onChatShare, onUserProfile, onMessagesScrollToTop, onMessagesScrollToBottom
28
28
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
29
29
  } = inject(chatInjectionKey);
30
30
  const messagesBodyRef = ref();
31
31
  const inputRef = ref();
32
32
  const inputValue = ref('');
33
33
  const attachmentFileList = ref([]);
34
+ const uploadedAttachmentsMap = ref(new Map());
34
35
  const lastScrollTop = ref(0);
35
36
  const scrollTopFired = ref(false);
36
37
  const scrollBottomFired = ref(false);
@@ -55,6 +56,8 @@ export default defineComponent({
55
56
  scrollTopFired.value = false;
56
57
  scrollBottomFired.value = false;
57
58
  shouldScrollOnLoad.value = true;
59
+ attachmentFileList.value = [];
60
+ uploadedAttachmentsMap.value.clear();
58
61
  if (unreadBeforeRead > 0 &&
59
62
  !notificationsShownSetRef.value.has(newChat.id)) {
60
63
  hasUnreadMessages.value = true;
@@ -236,7 +239,11 @@ export default defineComponent({
236
239
  const attachments = attachmentFileList.value.length > 0
237
240
  ? attachmentFileList.value.map((file) => {
238
241
  var _a, _b, _c;
239
- return ({
242
+ const uploadedAttachment = uploadedAttachmentsMap.value.get(file.id);
243
+ if (uploadedAttachment) {
244
+ return uploadedAttachment;
245
+ }
246
+ return {
240
247
  id: file.id,
241
248
  type: ChatMessageType.FILE,
242
249
  name: file.name,
@@ -246,13 +253,14 @@ export default defineComponent({
246
253
  thumbnail: (_b = file.thumbnailUrl) !== null && _b !== void 0 ? _b : undefined,
247
254
  status: file.status,
248
255
  percentage: (_c = file.percentage) !== null && _c !== void 0 ? _c : undefined
249
- });
256
+ };
250
257
  })
251
258
  : undefined;
252
259
  handleMessageSend(inputValue.value.trim(), attachments);
253
260
  inputValue.value = '';
254
261
  attachmentFileList.value = [];
255
262
  chatInputs.value[selectedChatRef.value.id] = '';
263
+ uploadedAttachmentsMap.value.clear();
256
264
  hasUnreadMessages.value = false;
257
265
  showNotificationManually.value = false;
258
266
  }
@@ -263,39 +271,24 @@ export default defineComponent({
263
271
  }
264
272
  }
265
273
  });
266
- let fileUploadTimer = null;
267
- const pendingFiles = ref([]);
268
274
  const handleFileListUpdate = (fileList) => {
269
- const newFiles = fileList.filter((file) => !attachmentFileList.value.some((existing) => existing.id === file.id) &&
270
- !pendingFiles.value.some((existing) => existing.id === file.id));
271
- if (newFiles.length > 0) {
272
- pendingFiles.value = [...pendingFiles.value, ...newFiles];
273
- if (fileUploadTimer) {
274
- clearTimeout(fileUploadTimer);
275
- }
276
- fileUploadTimer = setTimeout(() => {
277
- if (pendingFiles.value.length > 0 && handleMessageSend) {
278
- const hasError = pendingFiles.value.some((file) => file.status === 'error');
279
- const batchStatus = hasError ? 'error' : 'finished';
280
- const attachments = pendingFiles.value.map((file) => {
281
- var _a, _b, _c;
282
- return ({
283
- id: file.id,
284
- type: ChatMessageType.FILE,
285
- name: file.name,
286
- url: file.url ||
287
- (file.file ? URL.createObjectURL(file.file) : '#'),
288
- size: (_a = file.file) === null || _a === void 0 ? void 0 : _a.size,
289
- thumbnail: (_b = file.thumbnailUrl) !== null && _b !== void 0 ? _b : undefined,
290
- status: batchStatus,
291
- percentage: (_c = file.percentage) !== null && _c !== void 0 ? _c : undefined
292
- });
293
- });
294
- handleMessageSend('', attachments);
295
- pendingFiles.value = [];
296
- attachmentFileList.value = [];
275
+ attachmentFileList.value = fileList;
276
+ const uploadCallback = onAttachmentUpload === null || onAttachmentUpload === void 0 ? void 0 : onAttachmentUpload.value;
277
+ if (uploadCallback) {
278
+ const newFiles = fileList.filter((file) => file.file && !uploadedAttachmentsMap.value.has(file.id));
279
+ void (() => __awaiter(this, void 0, void 0, function* () {
280
+ for (const uploadFile of newFiles) {
281
+ if (uploadFile.file) {
282
+ try {
283
+ const attachment = yield uploadCallback(uploadFile.file);
284
+ uploadedAttachmentsMap.value.set(uploadFile.id, attachment);
285
+ }
286
+ catch (error) {
287
+ console.error('File upload failed:', error);
288
+ }
289
+ }
297
290
  }
298
- }, SENDING_DELAY);
291
+ }))();
299
292
  }
300
293
  };
301
294
  const renderFooter = () => {
@@ -304,11 +297,14 @@ export default defineComponent({
304
297
  default: () => (h(UFlex, { align: "center", size: "small", class: `${mergedClsPrefixRef.value}-chat-main__input-container` }, {
305
298
  default: () => (h(Fragment, null,
306
299
  h(UUploadTrigger, { abstract: true }, {
307
- default: ({ handleClick }) => (h(UButton, Object.assign({ secondary: true, size: "large", class: `${mergedClsPrefixRef.value}-chat-main__attach-btn` }, footerButtonPropsRef.value, { theme: mergedThemeRef.value.peers.Button, themeOverrides: mergedThemeRef.value.peerOverrides.Button, onClick: handleClick }), {
308
- default: () => (h(UIcon, Object.assign({ size: 24 }, footerIconPropsRef.value, { theme: mergedThemeRef.value.peers.Icon, themeOverrides: mergedThemeRef.value.peerOverrides.Icon }), {
309
- default: () => h(AttachIcon, null)
310
- }))
311
- }))
300
+ default: ({ handleClick }) => {
301
+ var _a;
302
+ return (h(UButton, Object.assign({ secondary: true, size: "large", class: `${mergedClsPrefixRef.value}-chat-main__attach-btn` }, footerButtonPropsRef.value, { disabled: (_a = footerInputPropsRef.value) === null || _a === void 0 ? void 0 : _a.disabled, theme: mergedThemeRef.value.peers.Button, themeOverrides: mergedThemeRef.value.peerOverrides.Button, onClick: handleClick }), {
303
+ default: () => (h(UIcon, Object.assign({ size: 24 }, footerIconPropsRef.value, { theme: mergedThemeRef.value.peers.Icon, themeOverrides: mergedThemeRef.value.peerOverrides.Icon }), {
304
+ default: () => h(AttachIcon, null)
305
+ }))
306
+ }));
307
+ }
312
308
  }),
313
309
  h(UInput, Object.assign({ ref: "inputRef", value: inputValue.value, placeholder: inputPlaceholderRef.value, class: `${mergedClsPrefixRef.value}-chat-main__input` }, footerInputPropsRef.value, { theme: mergedThemeRef.value.peers.Input, themeOverrides: mergedThemeRef.value.peerOverrides.Input, onUpdateValue: (value) => {
314
310
  inputValue.value = value;
@@ -342,7 +338,7 @@ export default defineComponent({
342
338
  const { mergedClsPrefixRef } = inject(chatInjectionKey);
343
339
  return (h("div", { class: `${mergedClsPrefixRef.value}-chat-main` },
344
340
  this.renderHeader(),
345
- h(UScrollbar, { ref: "messagesBodyRef", class: `${mergedClsPrefixRef.value}-chat-main__body`, onScroll: this.handleMessagesScroll }, {
341
+ h(USafeTopScrollbar, { ref: "messagesBodyRef", class: `${mergedClsPrefixRef.value}-chat-main__body`, onScroll: this.handleMessagesScroll }, {
346
342
  default: () => this.renderMessages()
347
343
  }),
348
344
  this.renderFooter()));
@@ -67,7 +67,7 @@ export interface ChatMessageData {
67
67
  timestamp?: string | number | Date | (() => VNodeChild);
68
68
  status?: MessageStatus;
69
69
  date?: string;
70
- attachment?: ChatAttachment | ChatAttachment[];
70
+ attachment?: ChatAttachment[];
71
71
  uploadProps?: Partial<UploadProps>;
72
72
  senderAvatar?: string | (() => VNodeChild);
73
73
  senderName?: string | (() => VNodeChild);
@@ -80,7 +80,7 @@ export interface ChatMessageProps {
80
80
  content?: string;
81
81
  timestamp?: string | number | Date | (() => VNodeChild);
82
82
  status?: MessageStatus;
83
- attachment?: ChatAttachment | ChatAttachment[];
83
+ attachment?: ChatAttachment[];
84
84
  uploadProps?: Partial<UploadProps>;
85
85
  senderAvatar?: string | (() => VNodeChild);
86
86
  senderName?: string | (() => VNodeChild);
@@ -165,6 +165,7 @@ export interface ChatProps {
165
165
  onMessageSend?: OnMessageSend;
166
166
  onMessageRetry?: (message: ChatMessageData) => void;
167
167
  onAttachmentUpload?: OnAttachmentUpload;
168
+ onAttachmentDownload?: OnAttachmentDownload;
168
169
  onFilterChange?: OnFilterChange;
169
170
  onFooterInputChange?: (value: string, chatId: ChatId) => void;
170
171
  onNetworkError?: OnNetworkError;
@@ -225,6 +226,7 @@ export interface ChatFooterProps {
225
226
  export type OnChatSelect = (key: ChatId, item: ChatListItemData) => void;
226
227
  export type OnMessageSend = (content: string, attachments?: ChatAttachment[]) => void;
227
228
  export type OnAttachmentUpload = (file: File) => Promise<ChatAttachment>;
229
+ export type OnAttachmentDownload = (attachment: ChatAttachment) => Promise<void>;
228
230
  export type OnFilterChange = (filter: {
229
231
  type: string;
230
232
  value: any;
@@ -311,6 +313,8 @@ export declare const chatInjectionKey: InjectionKey<{
311
313
  message: string;
312
314
  content: string;
313
315
  }) => void;
316
+ onAttachmentUpload?: Ref<OnAttachmentUpload | undefined>;
317
+ onAttachmentDownload?: Ref<OnAttachmentDownload | undefined>;
314
318
  onChatClose?: Ref<(() => void) | undefined>;
315
319
  onChatShare?: Ref<(() => void) | undefined>;
316
320
  onUserProfile?: Ref<(() => void) | undefined>;
@@ -69,6 +69,7 @@ export * from './radio';
69
69
  export * from './rate';
70
70
  export * from './result';
71
71
  export * from './scrollbar';
72
+ export * from './safe-top-scrollbar';
72
73
  export * from './select';
73
74
  export * from './skeleton';
74
75
  export * from './slider';
package/es/components.js CHANGED
@@ -69,6 +69,7 @@ export * from './radio';
69
69
  export * from './rate';
70
70
  export * from './result';
71
71
  export * from './scrollbar';
72
+ export * from './safe-top-scrollbar';
72
73
  export * from './select';
73
74
  export * from './skeleton';
74
75
  export * from './slider';
@@ -104,6 +104,7 @@ import { ActionCardTheme } from '../../action-card';
104
104
  import { ChatTheme } from '../../chat/styles';
105
105
  import { ModalFullscreenTheme } from '../../modal-fullscreen/styles';
106
106
  import { CropTheme } from '../../crop/styles';
107
+ import { SafeTopScrollbarTheme } from '../../_internal/safe-top-scrollbar/styles';
107
108
  export interface GlobalThemeWithoutCommon {
108
109
  Alert?: AlertTheme;
109
110
  Anchor?: AnchorTheme;
@@ -165,6 +166,7 @@ export interface GlobalThemeWithoutCommon {
165
166
  Rate?: RateTheme;
166
167
  Result?: ResultTheme;
167
168
  Scrollbar?: ScrollbarTheme;
169
+ SafeTopScrollbar?: SafeTopScrollbarTheme;
168
170
  Select?: SelectTheme;
169
171
  Skeleton?: SkeletonTheme;
170
172
  Slider?: SliderTheme;
@@ -65,6 +65,12 @@ export declare const drawerProps: {
65
65
  readonly minHeight: NumberConstructor;
66
66
  readonly resizable: BooleanConstructor;
67
67
  readonly fullscreen: BooleanConstructor;
68
+ readonly defaultWidth: {
69
+ readonly type: PropType<string | number>;
70
+ };
71
+ readonly defaultHeight: {
72
+ readonly type: PropType<string | number>;
73
+ };
68
74
  readonly onUpdateWidth: PropType<MaybeArray<(value: number) => void>>;
69
75
  readonly onUpdateHeight: PropType<MaybeArray<(value: number) => void>>;
70
76
  readonly 'onUpdate:width': PropType<MaybeArray<(value: number) => void>>;
@@ -282,6 +288,12 @@ declare const _default: import("vue").DefineComponent<{
282
288
  readonly minHeight: NumberConstructor;
283
289
  readonly resizable: BooleanConstructor;
284
290
  readonly fullscreen: BooleanConstructor;
291
+ readonly defaultWidth: {
292
+ readonly type: PropType<string | number>;
293
+ };
294
+ readonly defaultHeight: {
295
+ readonly type: PropType<string | number>;
296
+ };
285
297
  readonly onUpdateWidth: PropType<MaybeArray<(value: number) => void>>;
286
298
  readonly onUpdateHeight: PropType<MaybeArray<(value: number) => void>>;
287
299
  readonly 'onUpdate:width': PropType<MaybeArray<(value: number) => void>>;
@@ -597,6 +609,12 @@ declare const _default: import("vue").DefineComponent<{
597
609
  readonly minHeight: NumberConstructor;
598
610
  readonly resizable: BooleanConstructor;
599
611
  readonly fullscreen: BooleanConstructor;
612
+ readonly defaultWidth: {
613
+ readonly type: PropType<string | number>;
614
+ };
615
+ readonly defaultHeight: {
616
+ readonly type: PropType<string | number>;
617
+ };
600
618
  readonly onUpdateWidth: PropType<MaybeArray<(value: number) => void>>;
601
619
  readonly onUpdateHeight: PropType<MaybeArray<(value: number) => void>>;
602
620
  readonly 'onUpdate:width': PropType<MaybeArray<(value: number) => void>>;