@progress/kendo-angular-conversational-ui 24.0.0-develop.11 → 24.0.0-develop.13
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.
- package/chat/api/chat-load-more-event.d.ts +18 -0
- package/chat/api/chat-referenced-message-click-event.d.ts +18 -0
- package/chat/api/index.d.ts +4 -0
- package/chat/api/scroll-mode.d.ts +12 -0
- package/chat/chat.component.d.ts +164 -2
- package/chat/common/chat.service.d.ts +12 -3
- package/chat/common/endless-scroll-state.d.ts +36 -0
- package/chat/common/models/pending-scroll-action.d.ts +11 -0
- package/chat/common/scroll-anchor.directive.d.ts +38 -1
- package/chat/common/utils.d.ts +15 -0
- package/chat/message.component.d.ts +4 -2
- package/fesm2022/progress-kendo-angular-conversational-ui.mjs +1175 -83
- package/package-metadata.mjs +2 -2
- package/package.json +14 -14
- package/promptbox/affixes/promptbox-end-affix.component.d.ts +1 -1
- package/promptbox/affixes/promptbox-start-affix.component.d.ts +1 -1
- package/promptbox/affixes/promptbox-top-affix.component.d.ts +1 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
/**
|
|
6
|
+
* Arguments for the `loadMore` event of the Chat.
|
|
7
|
+
* Fires when the user scrolls near the edge of the rendered message window in endless scroll mode.
|
|
8
|
+
*/
|
|
9
|
+
export interface ChatLoadMoreEvent {
|
|
10
|
+
/**
|
|
11
|
+
* The inclusive start index into the full messages array.
|
|
12
|
+
*/
|
|
13
|
+
startIndex: number;
|
|
14
|
+
/**
|
|
15
|
+
* The exclusive end index into the full messages array.
|
|
16
|
+
*/
|
|
17
|
+
endIndex: number;
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
/**
|
|
6
|
+
* Arguments for the `referencedMessageClick` event of the Chat.
|
|
7
|
+
* Fires when the user clicks a pinned message indicator or a reply preview.
|
|
8
|
+
*/
|
|
9
|
+
export interface ChatReferencedMessageClickEvent {
|
|
10
|
+
/**
|
|
11
|
+
* The ID of the referenced message that was clicked.
|
|
12
|
+
*/
|
|
13
|
+
id: string | number;
|
|
14
|
+
/**
|
|
15
|
+
* Specifies whether the click originated from a pinned message indicator or a reply preview.
|
|
16
|
+
*/
|
|
17
|
+
type: 'pinned' | 'reply';
|
|
18
|
+
}
|
package/chat/api/index.d.ts
CHANGED
|
@@ -5,13 +5,17 @@
|
|
|
5
5
|
export * from './action.interface';
|
|
6
6
|
export * from './attachment.interface';
|
|
7
7
|
export * from './chat-file-interface';
|
|
8
|
+
export * from './chat-load-more-event';
|
|
9
|
+
export * from './chat-referenced-message-click-event';
|
|
8
10
|
export * from './chat-suggestion.interface';
|
|
9
11
|
export * from './execute-action-event';
|
|
10
12
|
export * from './message-action';
|
|
11
13
|
export * from './message-width-mode';
|
|
12
14
|
export * from './message.interface';
|
|
13
15
|
export * from './message-settings.interface';
|
|
16
|
+
export * from './message-status.interface';
|
|
14
17
|
export * from './post-message-event';
|
|
18
|
+
export * from './scroll-mode';
|
|
15
19
|
export * from './user.interface';
|
|
16
20
|
export * from './file-action';
|
|
17
21
|
export * from './file-download-event.interface';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
/**
|
|
6
|
+
* Defines the scroll behavior of the Chat message list.
|
|
7
|
+
*
|
|
8
|
+
* - `scrollable`—All messages are rendered with standard scroll behavior.
|
|
9
|
+
* - `endless`—The Chat starts by rendering the last `pageSize` messages
|
|
10
|
+
* and prepends older ones as the user scrolls up.
|
|
11
|
+
*/
|
|
12
|
+
export type ScrollMode = 'scrollable' | 'endless';
|
package/chat/chat.component.d.ts
CHANGED
|
@@ -7,19 +7,24 @@ import { SpeechToTextButtonSettings } from '@progress/kendo-angular-buttons';
|
|
|
7
7
|
import { LocalizationService } from '@progress/kendo-angular-l10n';
|
|
8
8
|
import { ContextMenuComponent, ContextMenuPopupEvent } from '@progress/kendo-angular-menu';
|
|
9
9
|
import { SelectEvent } from '@progress/kendo-angular-upload';
|
|
10
|
+
import { LicenseMessage } from '@progress/kendo-licensing';
|
|
10
11
|
import { SVGIcon } from '@progress/kendo-svg-icons';
|
|
11
12
|
import { FileSelectButtonSettings } from '../promptbox/common/models';
|
|
12
13
|
import { ExecuteActionEvent, FileAction, FileActionEvent, FileDownloadEvent, FilesLayoutMode, Message, MessageSettings, ResendMessageEvent, SendButtonSettings, SendMessageEvent } from './api';
|
|
13
14
|
import { ChatFile } from './api/chat-file-interface';
|
|
15
|
+
import { ChatLoadMoreEvent } from './api/chat-load-more-event';
|
|
16
|
+
import { ChatReferencedMessageClickEvent } from './api/chat-referenced-message-click-event';
|
|
14
17
|
import { ChatSuggestion } from './api/chat-suggestion.interface';
|
|
15
18
|
import { MessageAction, MessageActionEvent } from './api/message-action';
|
|
16
19
|
import { MessageBoxSettings, MessageBoxType } from './api/message-box';
|
|
17
20
|
import { MessageWidthMode } from './api/message-width-mode';
|
|
21
|
+
import { ScrollMode } from './api/scroll-mode';
|
|
18
22
|
import { QuickActionsLayoutMode, SuggestionsLayoutMode } from './api/suggestions-layout';
|
|
19
23
|
import { TimestampVisibilityMode } from './api/timestamp-visibility';
|
|
20
24
|
import { AuthorMessageContentTemplateDirective, AuthorMessageTemplateDirective, MessageContentTemplateDirective, MessageTemplateDirective, NoDataTemplateDirective, ReceiverMessageContentTemplateDirective, ReceiverMessageTemplateDirective } from './chat.directives';
|
|
21
25
|
import { ChatService } from './common/chat.service';
|
|
22
26
|
import { ConversationalUIModelFields } from './common/models/model-fields';
|
|
27
|
+
import { EndlessScrollState } from './common/endless-scroll-state';
|
|
23
28
|
import { MessageBoxComponent } from './message-box.component';
|
|
24
29
|
import { AttachmentTemplateDirective } from './templates/attachment-template.directive';
|
|
25
30
|
import { ChatHeaderTemplateDirective } from './templates/header-template.directive';
|
|
@@ -225,6 +230,86 @@ export declare class ChatComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
225
230
|
*/
|
|
226
231
|
set sendButtonSettings(value: boolean | SendButtonSettings);
|
|
227
232
|
get sendButtonSettings(): boolean | SendButtonSettings;
|
|
233
|
+
/**
|
|
234
|
+
* Controls the scrolling behavior of the message list.
|
|
235
|
+
*
|
|
236
|
+
* @default 'scrollable'
|
|
237
|
+
*/
|
|
238
|
+
scrollMode: ScrollMode;
|
|
239
|
+
/**
|
|
240
|
+
* Sets the number of messages loaded per page in endless scroll mode.
|
|
241
|
+
* Ignored in `scrollable` mode.
|
|
242
|
+
*
|
|
243
|
+
* @default 50
|
|
244
|
+
*/
|
|
245
|
+
pageSize: number;
|
|
246
|
+
/**
|
|
247
|
+
* Sets the minimum distance between a new receiver message and the top of the visible
|
|
248
|
+
* message area when auto-scrolling. Keeps older messages partially visible instead of
|
|
249
|
+
* scrolling them out of view.
|
|
250
|
+
*
|
|
251
|
+
* Accepts a percentage string relative to the visible area height (for example, `'30%'`)
|
|
252
|
+
* or a pixel value as a number. Negative values scroll the message fully to the bottom.
|
|
253
|
+
*
|
|
254
|
+
* Has no effect on author messages, which always scroll to the bottom.
|
|
255
|
+
*
|
|
256
|
+
* @default '20%'
|
|
257
|
+
*/
|
|
258
|
+
autoScrollThreshold: number | string;
|
|
259
|
+
/**
|
|
260
|
+
* Sets the total number of messages in the conversation.
|
|
261
|
+
*
|
|
262
|
+
* When `messages.length` equals `total` (or `total` is not set), the Chat operates in
|
|
263
|
+
* **built-in mode** and manages rendering internally. When `messages.length < total`,
|
|
264
|
+
* the Chat operates in **remote mode** — the consumer manages data via
|
|
265
|
+
* [`loadMore`](slug:api_conversational-ui_chatcomponent#loadMore) events.
|
|
266
|
+
*
|
|
267
|
+
* Only relevant when [`scrollMode`](slug:api_conversational-ui_chatcomponent#scrollMode)
|
|
268
|
+
* is `'endless'`.
|
|
269
|
+
*/
|
|
270
|
+
total: number;
|
|
271
|
+
/**
|
|
272
|
+
* Sets the index in the full conversation that `messages[0]` corresponds to.
|
|
273
|
+
*
|
|
274
|
+
* Only relevant in remote mode (`messages.length < total`). As the user scrolls up
|
|
275
|
+
* and the consumer prepends messages, `startIndex` decreases. The Chat uses this to
|
|
276
|
+
* compute the correct range for the next
|
|
277
|
+
* [`loadMore`](slug:api_conversational-ui_chatcomponent#loadMore) call.
|
|
278
|
+
*
|
|
279
|
+
* Ignored in built-in mode.
|
|
280
|
+
*/
|
|
281
|
+
startIndex: number;
|
|
282
|
+
/**
|
|
283
|
+
* Sets the exclusive end index of the current batch in the full conversation.
|
|
284
|
+
*
|
|
285
|
+
* Only relevant in remote mode (`messages.length < total`). As the user scrolls down
|
|
286
|
+
* and the consumer appends messages, `endIndex` increases. The Chat uses this to know
|
|
287
|
+
* whether more messages exist below the current batch.
|
|
288
|
+
*
|
|
289
|
+
* Ignored in built-in mode.
|
|
290
|
+
*/
|
|
291
|
+
endIndex: number;
|
|
292
|
+
/**
|
|
293
|
+
* Sets the full set of pinned messages in the conversation.
|
|
294
|
+
*
|
|
295
|
+
* Only needed in remote mode (`messages.length < total`). The Chat uses this to
|
|
296
|
+
* render the pinned message indicator when the pinned message is outside the current
|
|
297
|
+
* batch. In built-in mode, the Chat has all messages and can look them up directly.
|
|
298
|
+
*
|
|
299
|
+
* @default []
|
|
300
|
+
*/
|
|
301
|
+
pinnedMessages: Message[];
|
|
302
|
+
/**
|
|
303
|
+
* Sets the reply targets that live outside the current batch.
|
|
304
|
+
*
|
|
305
|
+
* Only needed in remote mode (`messages.length < total`). The Chat uses this to
|
|
306
|
+
* render reply previews when the replied-to message is not in the current batch.
|
|
307
|
+
* The consumer resolves this after each data fetch by finding which `replyToId`
|
|
308
|
+
* targets are missing from the batch and fetching only those.
|
|
309
|
+
*
|
|
310
|
+
* @default []
|
|
311
|
+
*/
|
|
312
|
+
repliedToMessages: Message[];
|
|
228
313
|
/**
|
|
229
314
|
* Sets the names of the model fields from which the Chat reads its data.
|
|
230
315
|
* Lets you map custom data types to the expected `Message` format.
|
|
@@ -298,6 +383,14 @@ export declare class ChatComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
298
383
|
* Fires when the user types in the message input box.
|
|
299
384
|
*/
|
|
300
385
|
inputValueChange: EventEmitter<string>;
|
|
386
|
+
/**
|
|
387
|
+
* Fires when the user scrolls near the edge of the rendered message window in endless scroll mode.
|
|
388
|
+
*/
|
|
389
|
+
loadMore: EventEmitter<ChatLoadMoreEvent>;
|
|
390
|
+
/**
|
|
391
|
+
* Fires when the user clicks a referenced message (pinned indicator or reply preview).
|
|
392
|
+
*/
|
|
393
|
+
referencedMessageClick: EventEmitter<ChatReferencedMessageClickEvent>;
|
|
301
394
|
get className(): string;
|
|
302
395
|
get dirAttr(): string;
|
|
303
396
|
set messagesContextMenu(contextMenu: ContextMenuComponent);
|
|
@@ -328,6 +421,18 @@ export declare class ChatComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
328
421
|
* Returns processed messages when model fields are used, otherwise returns original messages.
|
|
329
422
|
*/
|
|
330
423
|
get processedMessages(): Message[];
|
|
424
|
+
/**
|
|
425
|
+
* @hidden
|
|
426
|
+
* Returns `true` when the Chat is in remote endless scroll mode.
|
|
427
|
+
* Remote mode is active whenever the consumer provides a `total`.
|
|
428
|
+
*/
|
|
429
|
+
get isRemoteMode(): boolean;
|
|
430
|
+
/**
|
|
431
|
+
* @hidden
|
|
432
|
+
* Returns the messages to render — sliced in endless mode, full in scrollable mode.
|
|
433
|
+
* In remote mode, returns processedMessages as-is (consumer already provides only the current batch).
|
|
434
|
+
*/
|
|
435
|
+
get renderedMessages(): Message[];
|
|
331
436
|
/**
|
|
332
437
|
* @hidden
|
|
333
438
|
*/
|
|
@@ -362,6 +467,19 @@ export declare class ChatComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
362
467
|
* @hidden
|
|
363
468
|
*/
|
|
364
469
|
scrollToBottomIcon: SVGIcon;
|
|
470
|
+
/**
|
|
471
|
+
* @hidden
|
|
472
|
+
*/
|
|
473
|
+
endlessState: EndlessScrollState;
|
|
474
|
+
/**
|
|
475
|
+
* @hidden
|
|
476
|
+
*/
|
|
477
|
+
showLicenseWatermark: boolean;
|
|
478
|
+
/**
|
|
479
|
+
* @hidden
|
|
480
|
+
*/
|
|
481
|
+
licenseMessage?: LicenseMessage;
|
|
482
|
+
private anchor;
|
|
365
483
|
private direction;
|
|
366
484
|
private subs;
|
|
367
485
|
private _modelFields;
|
|
@@ -372,6 +490,16 @@ export declare class ChatComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
372
490
|
private _lastModelFields;
|
|
373
491
|
private _cachedContextMenuActions;
|
|
374
492
|
private _lastContextMenuActionsReference;
|
|
493
|
+
private _previousMessagesLength;
|
|
494
|
+
private _pendingScrollAction;
|
|
495
|
+
private _scrollHandledBeforePaint;
|
|
496
|
+
private _lastNewMessageId;
|
|
497
|
+
private _cachedRenderedMessages;
|
|
498
|
+
private _renderedMessagesSource;
|
|
499
|
+
private _renderedMessagesStart;
|
|
500
|
+
private _renderedMessagesEnd;
|
|
501
|
+
private _pendingRemoteScrollToMessageId;
|
|
502
|
+
private _remoteScrollToBottom;
|
|
375
503
|
constructor(localization: LocalizationService, zone: NgZone, renderer: Renderer2, element: ElementRef, chatService: ChatService);
|
|
376
504
|
/**
|
|
377
505
|
* @hidden
|
|
@@ -400,7 +528,23 @@ export declare class ChatComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
400
528
|
/**
|
|
401
529
|
* @hidden
|
|
402
530
|
*/
|
|
403
|
-
scrollToPinnedMessage(): void;
|
|
531
|
+
scrollToPinnedMessage(event?: MouseEvent): void;
|
|
532
|
+
/**
|
|
533
|
+
* @hidden
|
|
534
|
+
*/
|
|
535
|
+
onNearTop(): void;
|
|
536
|
+
/**
|
|
537
|
+
* @hidden
|
|
538
|
+
*/
|
|
539
|
+
onNearBottom(): void;
|
|
540
|
+
/**
|
|
541
|
+
* @hidden
|
|
542
|
+
*/
|
|
543
|
+
onScrollToBottomClick(): void;
|
|
544
|
+
/**
|
|
545
|
+
* @hidden
|
|
546
|
+
*/
|
|
547
|
+
handleReferencedMessageClick(messageId: string | number, type: 'pinned' | 'reply'): void;
|
|
404
548
|
/**
|
|
405
549
|
* @hidden
|
|
406
550
|
*/
|
|
@@ -413,9 +557,27 @@ export declare class ChatComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
413
557
|
* @hidden
|
|
414
558
|
*/
|
|
415
559
|
onActionButtonClick(event: MouseEvent): void;
|
|
560
|
+
/**
|
|
561
|
+
* @hidden
|
|
562
|
+
*/
|
|
563
|
+
onMessageListResize(): void;
|
|
564
|
+
/**
|
|
565
|
+
* Schedules the new-message scroll adjustment on zone.onStable so it runs
|
|
566
|
+
* after Angular renders the new DOM but before the browser paints,
|
|
567
|
+
* preventing a visible intermediate frame.
|
|
568
|
+
*/
|
|
569
|
+
private scheduleNewMessageScroll;
|
|
570
|
+
private detectNewMessageScrollAction;
|
|
571
|
+
private getLastNewMessageElement;
|
|
416
572
|
private findLastPinnedMessage;
|
|
573
|
+
private initEndlessScroll;
|
|
574
|
+
private handleMessagesChange;
|
|
575
|
+
private handleRemoteMessagesChange;
|
|
576
|
+
private handleRemoteReferencedMessageClick;
|
|
577
|
+
private handlePendingRemoteScroll;
|
|
417
578
|
private updateChatServiceProperties;
|
|
579
|
+
private validateRemoteInputs;
|
|
418
580
|
private mergeWithDefaultActions;
|
|
419
581
|
static ɵfac: i0.ɵɵFactoryDeclaration<ChatComponent, never>;
|
|
420
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<ChatComponent, "kendo-chat", never, { "messages": { "alias": "messages"; "required": false; }; "authorId": { "alias": "authorId"; "required": false; }; "messageBoxType": { "alias": "messageBoxType"; "required": false; }; "height": { "alias": "height"; "required": false; }; "width": { "alias": "width"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "messageWidthMode": { "alias": "messageWidthMode"; "required": false; }; "timestampVisibility": { "alias": "timestampVisibility"; "required": false; }; "showUsername": { "alias": "showUsername"; "required": false; }; "showAvatar": { "alias": "showAvatar"; "required": false; }; "allowMessageCollapse": { "alias": "allowMessageCollapse"; "required": false; }; "speechToTextButton": { "alias": "speechToTextButton"; "required": false; }; "fileSelectButton": { "alias": "fileSelectButton"; "required": false; }; "messageBoxSettings": { "alias": "messageBoxSettings"; "required": false; }; "messageToolbarActions": { "alias": "messageToolbarActions"; "required": false; }; "inputValue": { "alias": "inputValue"; "required": false; }; "authorMessageSettings": { "alias": "authorMessageSettings"; "required": false; }; "receiverMessageSettings": { "alias": "receiverMessageSettings"; "required": false; }; "messageContextMenuActions": { "alias": "messageContextMenuActions"; "required": false; }; "fileActions": { "alias": "fileActions"; "required": false; }; "messageFilesLayout": { "alias": "messageFilesLayout"; "required": false; }; "suggestionsLayout": { "alias": "suggestionsLayout"; "required": false; }; "quickActionsLayout": { "alias": "quickActionsLayout"; "required": false; }; "suggestions": { "alias": "suggestions"; "required": false; }; "sendButton": { "alias": "sendButton"; "required": false; }; "sendButtonSettings": { "alias": "sendButtonSettings"; "required": false; }; "modelFields": { "alias": "modelFields"; "required": false; }; "scrollToBottomButton": { "alias": "scrollToBottomButton"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; }, { "sendMessage": "sendMessage"; "resendMessage": "resendMessage"; "toolbarActionClick": "toolbarActionClick"; "contextMenuActionClick": "contextMenuActionClick"; "fileActionClick": "fileActionClick"; "download": "download"; "executeAction": "executeAction"; "suggestionExecute": "suggestionExecute"; "fileSelect": "fileSelect"; "fileRemove": "fileRemove"; "unpin": "unpin"; "inputValueChange": "inputValueChange"; }, ["attachmentTemplate", "chatHeaderTemplate", "chatNoDataTemplate", "authorMessageContentTemplate", "receiverMessageContentTemplate", "messageContentTemplate", "authorMessageTemplate", "receiverMessageTemplate", "messageTemplate", "timestampTemplate", "suggestionTemplate", "statusTemplate", "messageBoxTemplate", "messageBoxStartAffixTemplate", "messageBoxEndAffixTemplate", "messageBoxTopAffixTemplate", "userStatusTemplate"], never, true, never>;
|
|
582
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ChatComponent, "kendo-chat", never, { "messages": { "alias": "messages"; "required": false; }; "authorId": { "alias": "authorId"; "required": false; }; "messageBoxType": { "alias": "messageBoxType"; "required": false; }; "height": { "alias": "height"; "required": false; }; "width": { "alias": "width"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "messageWidthMode": { "alias": "messageWidthMode"; "required": false; }; "timestampVisibility": { "alias": "timestampVisibility"; "required": false; }; "showUsername": { "alias": "showUsername"; "required": false; }; "showAvatar": { "alias": "showAvatar"; "required": false; }; "allowMessageCollapse": { "alias": "allowMessageCollapse"; "required": false; }; "speechToTextButton": { "alias": "speechToTextButton"; "required": false; }; "fileSelectButton": { "alias": "fileSelectButton"; "required": false; }; "messageBoxSettings": { "alias": "messageBoxSettings"; "required": false; }; "messageToolbarActions": { "alias": "messageToolbarActions"; "required": false; }; "inputValue": { "alias": "inputValue"; "required": false; }; "authorMessageSettings": { "alias": "authorMessageSettings"; "required": false; }; "receiverMessageSettings": { "alias": "receiverMessageSettings"; "required": false; }; "messageContextMenuActions": { "alias": "messageContextMenuActions"; "required": false; }; "fileActions": { "alias": "fileActions"; "required": false; }; "messageFilesLayout": { "alias": "messageFilesLayout"; "required": false; }; "suggestionsLayout": { "alias": "suggestionsLayout"; "required": false; }; "quickActionsLayout": { "alias": "quickActionsLayout"; "required": false; }; "suggestions": { "alias": "suggestions"; "required": false; }; "sendButton": { "alias": "sendButton"; "required": false; }; "sendButtonSettings": { "alias": "sendButtonSettings"; "required": false; }; "scrollMode": { "alias": "scrollMode"; "required": false; }; "pageSize": { "alias": "pageSize"; "required": false; }; "autoScrollThreshold": { "alias": "autoScrollThreshold"; "required": false; }; "total": { "alias": "total"; "required": false; }; "startIndex": { "alias": "startIndex"; "required": false; }; "endIndex": { "alias": "endIndex"; "required": false; }; "pinnedMessages": { "alias": "pinnedMessages"; "required": false; }; "repliedToMessages": { "alias": "repliedToMessages"; "required": false; }; "modelFields": { "alias": "modelFields"; "required": false; }; "scrollToBottomButton": { "alias": "scrollToBottomButton"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; }, { "sendMessage": "sendMessage"; "resendMessage": "resendMessage"; "toolbarActionClick": "toolbarActionClick"; "contextMenuActionClick": "contextMenuActionClick"; "fileActionClick": "fileActionClick"; "download": "download"; "executeAction": "executeAction"; "suggestionExecute": "suggestionExecute"; "fileSelect": "fileSelect"; "fileRemove": "fileRemove"; "unpin": "unpin"; "inputValueChange": "inputValueChange"; "loadMore": "loadMore"; "referencedMessageClick": "referencedMessageClick"; }, ["attachmentTemplate", "chatHeaderTemplate", "chatNoDataTemplate", "authorMessageContentTemplate", "receiverMessageContentTemplate", "messageContentTemplate", "authorMessageTemplate", "receiverMessageTemplate", "messageTemplate", "timestampTemplate", "suggestionTemplate", "statusTemplate", "messageBoxTemplate", "messageBoxStartAffixTemplate", "messageBoxEndAffixTemplate", "messageBoxTopAffixTemplate", "userStatusTemplate"], never, true, never>;
|
|
421
583
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
3
|
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { ViewContainerRef, ElementRef } from '@angular/core';
|
|
5
|
+
import { ViewContainerRef, ElementRef, NgZone } from '@angular/core';
|
|
6
6
|
import { SpeechToTextButtonSettings } from '@progress/kendo-angular-buttons';
|
|
7
7
|
import { MessageWidthMode } from '../api/message-width-mode';
|
|
8
8
|
import { FileAction, FileActionEvent, FileDownloadEvent, FilesLayoutMode, Message, MessageAction, MessageActionEvent, MessageSettings, QuickActionsLayoutMode, ResendMessageEvent, SendButtonSettings, SuggestionsLayoutMode } from '../api';
|
|
@@ -15,15 +15,17 @@ import * as i0 from "@angular/core";
|
|
|
15
15
|
* @hidden
|
|
16
16
|
*/
|
|
17
17
|
export declare class ChatService {
|
|
18
|
+
private zone;
|
|
18
19
|
authorId: string | number;
|
|
19
20
|
messageWidthMode: MessageWidthMode;
|
|
20
|
-
messageToolbarActions: MessageAction[];
|
|
21
21
|
messageContextMenuActions: MessageAction[];
|
|
22
22
|
calculatedContextMenuActions: MessageAction[];
|
|
23
23
|
fileActions: FileAction[];
|
|
24
24
|
toggleMessageState: boolean;
|
|
25
|
+
layoutChangeInProgress: boolean;
|
|
25
26
|
reply: Message;
|
|
26
27
|
messages: Message[];
|
|
28
|
+
repliedToMessages: Message[];
|
|
27
29
|
chatElement: ViewContainerRef;
|
|
28
30
|
messageElementsMap: Map<string | number, ElementRef>;
|
|
29
31
|
messagesContextMenu: ContextMenuComponent;
|
|
@@ -41,6 +43,7 @@ export declare class ChatService {
|
|
|
41
43
|
private _messageBoxSettings;
|
|
42
44
|
private _suggestionsLayout;
|
|
43
45
|
private _quickActionsLayout;
|
|
46
|
+
private _messageToolbarActions;
|
|
44
47
|
_authorMessageSettings: MessageSettings;
|
|
45
48
|
_receiverMessageSettings: MessageSettings;
|
|
46
49
|
private _allowMessageCollapse;
|
|
@@ -58,6 +61,8 @@ export declare class ChatService {
|
|
|
58
61
|
authorMessageSettingsChange$: import("rxjs").Observable<MessageSettings>;
|
|
59
62
|
receiverMessageSettingsChange$: import("rxjs").Observable<MessageSettings>;
|
|
60
63
|
allowMessageCollapseChange$: import("rxjs").Observable<boolean>;
|
|
64
|
+
messageToolbarActionsChange$: import("rxjs").Observable<MessageAction[]>;
|
|
65
|
+
constructor(zone: NgZone);
|
|
61
66
|
set authorMessageSettings(settings: MessageSettings);
|
|
62
67
|
get authorMessageSettings(): MessageSettings;
|
|
63
68
|
set receiverMessageSettings(settings: MessageSettings);
|
|
@@ -74,6 +79,8 @@ export declare class ChatService {
|
|
|
74
79
|
get suggestionsLayout(): SuggestionsLayoutMode;
|
|
75
80
|
set quickActionsLayout(layoutMode: QuickActionsLayoutMode);
|
|
76
81
|
get quickActionsLayout(): QuickActionsLayoutMode;
|
|
82
|
+
set messageToolbarActions(value: MessageAction[]);
|
|
83
|
+
get messageToolbarActions(): MessageAction[];
|
|
77
84
|
set allowMessageCollapse(value: boolean);
|
|
78
85
|
get allowMessageCollapse(): boolean;
|
|
79
86
|
calculateContextMenuActions(isOwn: boolean): void;
|
|
@@ -81,9 +88,11 @@ export declare class ChatService {
|
|
|
81
88
|
getMessageById(id: string | number): Message | undefined;
|
|
82
89
|
registerMessageElement(messageId: string | number, elementRef: ElementRef): void;
|
|
83
90
|
unregisterMessageElement(messageId: string | number): void;
|
|
84
|
-
scrollToMessage(messageId: string | number): void;
|
|
91
|
+
scrollToMessage(messageId: string | number, behavior?: ScrollBehavior): void;
|
|
85
92
|
focusActiveMessageElement(): void;
|
|
86
93
|
isOwnMessage(message: Message): boolean;
|
|
94
|
+
private getScrollContainer;
|
|
95
|
+
private computeScrollTarget;
|
|
87
96
|
private updateComponentSettings;
|
|
88
97
|
static ɵfac: i0.ɵɵFactoryDeclaration<ChatService, never>;
|
|
89
98
|
static ɵprov: i0.ɵɵInjectableDeclaration<ChatService>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
/**
|
|
6
|
+
* @hidden
|
|
7
|
+
*
|
|
8
|
+
* Tracks the rendered range for endless scroll mode.
|
|
9
|
+
* Pure logic — no Angular dependency.
|
|
10
|
+
*/
|
|
11
|
+
export interface EndlessScrollRange {
|
|
12
|
+
start: number;
|
|
13
|
+
end: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @hidden
|
|
17
|
+
*/
|
|
18
|
+
export declare class EndlessScrollState {
|
|
19
|
+
startIndex: number;
|
|
20
|
+
endIndex: number;
|
|
21
|
+
isLoading: boolean;
|
|
22
|
+
get isAtStart(): boolean;
|
|
23
|
+
get isAtEnd(): boolean;
|
|
24
|
+
private _total;
|
|
25
|
+
private _pageSize;
|
|
26
|
+
get pageSize(): number;
|
|
27
|
+
init(total: number, pageSize: number): EndlessScrollRange;
|
|
28
|
+
extendUp(): EndlessScrollRange | null;
|
|
29
|
+
extendDown(): EndlessScrollRange | null;
|
|
30
|
+
jumpTo(targetIndex: number): EndlessScrollRange;
|
|
31
|
+
jumpToEnd(): EndlessScrollRange;
|
|
32
|
+
updateTotal(total: number): void;
|
|
33
|
+
reset(): void;
|
|
34
|
+
contains(index: number): boolean;
|
|
35
|
+
syncFromInputs(start: number, end: number, total: number): void;
|
|
36
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
/**
|
|
6
|
+
* @hidden
|
|
7
|
+
* Scroll action scheduled after a new message is appended.
|
|
8
|
+
* `author` — the local user sent the message; scroll fully to the bottom.
|
|
9
|
+
* `receiver` — a remote message arrived while the user was near the bottom; scroll with threshold.
|
|
10
|
+
*/
|
|
11
|
+
export type PendingScrollAction = 'author' | 'receiver';
|
|
@@ -13,13 +13,35 @@ export declare class ScrollAnchorDirective implements AfterViewInit, OnInit, OnD
|
|
|
13
13
|
private renderer;
|
|
14
14
|
private cdr;
|
|
15
15
|
autoScroll: boolean;
|
|
16
|
+
autoScrollThreshold: number | string;
|
|
17
|
+
set endlessMode(value: boolean);
|
|
18
|
+
get endlessMode(): boolean;
|
|
19
|
+
rangeIsAtEnd: boolean;
|
|
16
20
|
autoScrollChange: EventEmitter<boolean>;
|
|
21
|
+
nearTop: EventEmitter<void>;
|
|
22
|
+
nearBottom: EventEmitter<void>;
|
|
17
23
|
overflowAnchor: string;
|
|
24
|
+
get scrollBehaviorStyle(): string;
|
|
18
25
|
showScrollToBottomButton: boolean;
|
|
19
26
|
showMessageBoxSeparator: boolean;
|
|
20
27
|
private scrolling;
|
|
21
28
|
private unsubscribe;
|
|
22
29
|
private scrollUpdate;
|
|
30
|
+
private _previousScrollHeight;
|
|
31
|
+
private _previousScrollTop;
|
|
32
|
+
private _pendingScrollPreservation;
|
|
33
|
+
private _endlessMode;
|
|
34
|
+
private _nearTopLocked;
|
|
35
|
+
private _nearBottomLocked;
|
|
36
|
+
private _scrollingToMessage;
|
|
37
|
+
private _initialScrollDone;
|
|
38
|
+
private _subs;
|
|
39
|
+
private _streamingFollow;
|
|
40
|
+
private _thresholdScrollCap;
|
|
41
|
+
private _streamingPrevScrollTop;
|
|
42
|
+
private _streamingPrevHeight;
|
|
43
|
+
private _streamingPrevMsgCount;
|
|
44
|
+
private _mutationObserver;
|
|
23
45
|
constructor(element: ElementRef, zone: NgZone, renderer: Renderer2, cdr: ChangeDetectorRef);
|
|
24
46
|
ngOnInit(): void;
|
|
25
47
|
ngAfterViewInit(): void;
|
|
@@ -27,9 +49,24 @@ export declare class ScrollAnchorDirective implements AfterViewInit, OnInit, OnD
|
|
|
27
49
|
onScroll(): void;
|
|
28
50
|
autoScrollToBottom(): void;
|
|
29
51
|
scrollToBottom(): void;
|
|
52
|
+
scrollToBottomWithSettle(onComplete?: () => void): void;
|
|
53
|
+
scrollWithThreshold(messageEl: HTMLElement): void;
|
|
54
|
+
recordScrollHeight(): void;
|
|
55
|
+
preserveScrollPosition(): void;
|
|
30
56
|
calculateMessageBoxSeparator(): void;
|
|
57
|
+
getDistanceFromBottom(): number;
|
|
58
|
+
setAriaLive(value: string): void;
|
|
59
|
+
lockForMessageScroll(): void;
|
|
60
|
+
unlockForMessageScroll(): void;
|
|
61
|
+
getAutoScrollThresholdPx(): number;
|
|
62
|
+
get isFollowingThreshold(): boolean;
|
|
63
|
+
private followStreamingContent;
|
|
64
|
+
private updateScrollToBottomButton;
|
|
65
|
+
private detectStreamingScrollUp;
|
|
66
|
+
private parseThreshold;
|
|
67
|
+
private getPinnedBarHeight;
|
|
31
68
|
private setupScrollUpdate;
|
|
32
69
|
private performScroll;
|
|
33
70
|
static ɵfac: i0.ɵɵFactoryDeclaration<ScrollAnchorDirective, never>;
|
|
34
|
-
static ɵdir: i0.ɵɵDirectiveDeclaration<ScrollAnchorDirective, "[kendoChatScrollAnchor]", ["scrollAnchor"], { "autoScroll": { "alias": "autoScroll"; "required": false; }; }, { "autoScrollChange": "autoScrollChange"; }, never, never, true, never>;
|
|
71
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<ScrollAnchorDirective, "[kendoChatScrollAnchor]", ["scrollAnchor"], { "autoScroll": { "alias": "autoScroll"; "required": false; }; "autoScrollThreshold": { "alias": "autoScrollThreshold"; "required": false; }; "endlessMode": { "alias": "endlessMode"; "required": false; }; "rangeIsAtEnd": { "alias": "rangeIsAtEnd"; "required": false; }; }, { "autoScrollChange": "autoScrollChange"; "nearTop": "nearTop"; "nearBottom": "nearBottom"; }, never, never, true, never>;
|
|
35
72
|
}
|
package/chat/common/utils.d.ts
CHANGED
|
@@ -7,6 +7,21 @@ import { ConversationalUIModelFields } from "./models/model-fields";
|
|
|
7
7
|
import { FileSelectButtonSettings } from '../../promptbox/common/models';
|
|
8
8
|
import { SpeechToTextButtonSettings } from "@progress/kendo-angular-buttons";
|
|
9
9
|
import { MessageBoxSettings } from "../api/message-box";
|
|
10
|
+
import { NgZone } from "@angular/core";
|
|
11
|
+
/**
|
|
12
|
+
* @hidden
|
|
13
|
+
*
|
|
14
|
+
* Show the scroll-to-bottom button when the user is this many pixels from the bottom.
|
|
15
|
+
*/
|
|
16
|
+
export declare const scrollButtonThreshold = 100;
|
|
17
|
+
/**
|
|
18
|
+
* @hidden
|
|
19
|
+
*
|
|
20
|
+
* Pins a scroll container to a computed target across layout shifts.
|
|
21
|
+
* Observers extend the idle window until layout has settled; the initial and
|
|
22
|
+
* final pins bracket the settle window so the viewport lands exactly on target.
|
|
23
|
+
*/
|
|
24
|
+
export declare const settleScroll: (zone: NgZone, el: HTMLElement, computeTarget: () => number | null, onComplete: () => void, idleMs?: number, timeoutMs?: number) => void;
|
|
10
25
|
/**
|
|
11
26
|
* @hidden
|
|
12
27
|
*/
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
3
|
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { ChangeDetectorRef, ElementRef, OnDestroy, OnInit } from '@angular/core';
|
|
5
|
+
import { ChangeDetectorRef, ElementRef, NgZone, OnDestroy, OnInit } from '@angular/core';
|
|
6
6
|
import { Message } from './api/message.interface';
|
|
7
7
|
import { MessageStatus } from './api/message-status.interface';
|
|
8
8
|
import { ChatItem } from './chat-item';
|
|
@@ -31,6 +31,7 @@ export declare class MessageComponent extends ChatItem implements OnInit, OnDest
|
|
|
31
31
|
chatService: ChatService;
|
|
32
32
|
private localization;
|
|
33
33
|
private cdr;
|
|
34
|
+
private zone;
|
|
34
35
|
set message(value: Message);
|
|
35
36
|
get message(): Message;
|
|
36
37
|
tabbable: boolean;
|
|
@@ -71,7 +72,7 @@ export declare class MessageComponent extends ChatItem implements OnInit, OnDest
|
|
|
71
72
|
get showToolbar(): boolean;
|
|
72
73
|
private subs;
|
|
73
74
|
private _message;
|
|
74
|
-
constructor(element: ElementRef, intl: IntlService, chatService: ChatService, localization: LocalizationService, cdr: ChangeDetectorRef);
|
|
75
|
+
constructor(element: ElementRef, intl: IntlService, chatService: ChatService, localization: LocalizationService, cdr: ChangeDetectorRef, zone: NgZone);
|
|
75
76
|
ngOnInit(): void;
|
|
76
77
|
ngAfterViewInit(): void;
|
|
77
78
|
ngOnDestroy(): void;
|
|
@@ -99,6 +100,7 @@ export declare class MessageComponent extends ChatItem implements OnInit, OnDest
|
|
|
99
100
|
private getMessageSettings;
|
|
100
101
|
private getToolbarActions;
|
|
101
102
|
private getFileActions;
|
|
103
|
+
private updateExpandCollapseIconAfterStable;
|
|
102
104
|
static ɵfac: i0.ɵɵFactoryDeclaration<MessageComponent, never>;
|
|
103
105
|
static ɵcmp: i0.ɵɵComponentDeclaration<MessageComponent, "kendo-chat-message", never, { "message": { "alias": "message"; "required": false; }; "tabbable": { "alias": "tabbable"; "required": false; }; "authorMessageContentTemplate": { "alias": "authorMessageContentTemplate"; "required": false; }; "receiverMessageContentTemplate": { "alias": "receiverMessageContentTemplate"; "required": false; }; "messageContentTemplate": { "alias": "messageContentTemplate"; "required": false; }; "authorMessageTemplate": { "alias": "authorMessageTemplate"; "required": false; }; "receiverMessageTemplate": { "alias": "receiverMessageTemplate"; "required": false; }; "messageTemplate": { "alias": "messageTemplate"; "required": false; }; "statusTemplate": { "alias": "statusTemplate"; "required": false; }; "showMessageTime": { "alias": "showMessageTime"; "required": false; }; "authorId": { "alias": "authorId"; "required": false; }; }, {}, never, never, true, never>;
|
|
104
106
|
}
|