@progress/kendo-angular-conversational-ui
Version:
Kendo UI for Angular Conversational UI components
1,224 lines (1,205 loc) • 309 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import * as i0 from '@angular/core';
import { InjectionToken, Directive, Inject, HostBinding, ViewChild, Input, Injectable, Optional, forwardRef, EventEmitter, Component, ContentChildren, ContentChild, Output, isDevMode, ViewChildren, HostListener, ElementRef, ViewContainerRef, inject, SkipSelf, NgModule } from '@angular/core';
import { IconWrapperComponent, IconsService } from '@progress/kendo-angular-icons';
import * as i1$2 from '@progress/kendo-angular-popup';
import { PopupComponent, KENDO_POPUP, PopupService } from '@progress/kendo-angular-popup';
import { isPresent, normalizeNumpadKeys, Keys, focusableSelector, guid, getter, closest as closest$1, ResizeSensorComponent, isChanged, processCssValue, isDocumentAvailable, ResizeBatchService } from '@progress/kendo-angular-common';
import { DialogContainerService, DialogService, WindowService, WindowContainerService } from '@progress/kendo-angular-dialog';
import { NgFor, NgIf, NgTemplateOutlet, NgClass, NgSwitch, NgSwitchCase } from '@angular/common';
import { Subject, Subscription, fromEvent } from 'rxjs';
import { sparklesIcon, commentIcon, moreHorizontalIcon, stopSmIcon, thumbUpIcon, thumbDownOutlineIcon, thumbDownIcon, thumbUpOutlineIcon, copyIcon, arrowRotateCwIcon, chevronUpIcon, chevronDownIcon, paperPlaneIcon, undoIcon, downloadIcon, xIcon, moreVerticalIcon, paperclipIcon, fileIcon, chevronLeftIcon, chevronRightIcon, pinIcon, cancelOutlineIcon, menuIcon } from '@progress/kendo-svg-icons';
import * as i1 from '@progress/kendo-angular-l10n';
import { ComponentMessages, LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
import { validatePackage } from '@progress/kendo-licensing';
import * as i2 from '@progress/kendo-angular-buttons';
import { ButtonComponent, FloatingActionButtonComponent, SpeechToTextButtonComponent, DropDownButtonComponent, KENDO_BUTTONS, KENDO_BUTTON } from '@progress/kendo-angular-buttons';
import { take, debounceTime } from 'rxjs/operators';
import * as i5 from '@progress/kendo-angular-layout';
import { PanelBarComponent, KENDO_CARD } from '@progress/kendo-angular-layout';
import * as i3 from '@progress/kendo-angular-inputs';
import { TextAreaComponent, TextAreaSuffixComponent, TextAreaPrefixComponent, InputSpacerComponent, KENDO_TEXTAREA } from '@progress/kendo-angular-inputs';
import { fileSVGGroupIcon, fileGroupClass, getTotalFilesSizeMessage, FileSelectComponent } from '@progress/kendo-angular-upload';
import { FormsModule } from '@angular/forms';
import * as i1$1 from '@progress/kendo-angular-intl';
import * as i4 from '@progress/kendo-angular-menu';
import { ContextMenuComponent, KENDO_CONTEXTMENU } from '@progress/kendo-angular-menu';
import { ToolBarComponent, ToolBarButtonComponent } from '@progress/kendo-angular-toolbar';
import { AppBarComponent } from '@progress/kendo-angular-navigation';
/**
* @hidden
*/
class PreventableEvent {
prevented = false;
/**
* Prevents the default action for a specified event.
* In this way, the source component suppresses
* the built-in behavior that follows the event.
*/
preventDefault() {
this.prevented = true;
}
/**
* Returns `true` if the event was prevented
* by any of its subscribers.
*
* @returns `true` if the default action was prevented.
* Otherwise, returns `false`.
*/
isDefaultPrevented() {
return this.prevented;
}
}
/**
* Represents the arguments for the `executeAction` event.
*
* The `executeAction` event fires when the user clicks a quick action button.
* Call `preventDefault()` to suppress the built-in action handler.
*/
class ExecuteActionEvent extends PreventableEvent {
/**
* Represents the action to execute.
*/
action;
/**
* Represents the message that contains the action.
*/
message;
/**
* @hidden
*/
constructor(action, message) {
super();
this.action = action;
this.message = message;
}
}
/**
* Describes the arguments for the `sendMessage` event.
*/
class SendMessageEvent {
/**
* Represents the message that contains the metadata and user input.
*
* The Chat does not automatically add the message to its data. For more information, see [Data Binding](slug:databinding_chat).
*/
message;
/**
* @hidden
*/
constructor(message) {
this.message = message;
}
}
/**
* @hidden
*/
const MY_TOKEN = new InjectionToken('COMMAND_TOKEN');
/**
* @hidden
*/
const DEFAULT_SVG_ICONS = {
prompt: sparklesIcon,
output: commentIcon,
command: moreHorizontalIcon
};
/**
* @hidden
*/
const DEFAULT_ICONS = {
prompt: 'sparkles',
output: 'comment',
command: 'more-horizontal'
};
/**
* @hidden
*/
class BaseView {
viewType;
localization;
hostClasses = true;
/**
* @hidden
*/
template;
constructor(viewType, localization) {
this.viewType = viewType;
this.localization = localization;
if (this.viewType !== 'custom') {
this.icon = DEFAULT_ICONS[this.viewType];
this.svgIcon = DEFAULT_SVG_ICONS[this.viewType];
}
}
/**
* Sets the text for the Toolbar button of the current view.
*/
set buttonText(value) {
this._buttonText = value;
}
get buttonText() {
return isPresent(this._buttonText) ?
this._buttonText :
this.messageFor(`${this.viewType}View`);
}
/**
* Sets the font icon for the Toolbar button of the current view.
*/
set icon(value) {
if (isPresent(value)) {
this._icon = value;
}
else {
this.icon = DEFAULT_ICONS[this.viewType];
}
}
get icon() {
return this._icon;
}
/**
* Sets the SVG icon for the Toolbar button of the current view.
*/
set svgIcon(value) {
if (isPresent(value)) {
this._svgIcon = value;
}
else {
this.svgIcon = DEFAULT_SVG_ICONS[this.viewType];
}
}
get svgIcon() {
return this._svgIcon;
}
/**
* @hidden
*/
messageFor(text) {
return this.localization.get(text);
}
_buttonText;
_icon;
_svgIcon;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: BaseView, deps: [{ token: MY_TOKEN }, { token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: BaseView, inputs: { buttonText: "buttonText", icon: "icon", svgIcon: "svgIcon" }, host: { properties: { "class.k-prompt-view": "this.hostClasses" } }, viewQueries: [{ propertyName: "template", first: true, predicate: ["content"], descendants: true, static: true }], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: BaseView, decorators: [{
type: Directive
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [MY_TOKEN]
}] }, { type: i1.LocalizationService }]; }, propDecorators: { hostClasses: [{
type: HostBinding,
args: ['class.k-prompt-view']
}], template: [{
type: ViewChild,
args: ['content', { static: true }]
}], buttonText: [{
type: Input
}], icon: [{
type: Input
}], svgIcon: [{
type: Input
}] } });
/**
* @hidden
*/
const packageMetadata = {
name: '@progress/kendo-angular-conversational-ui',
productName: 'Kendo UI for Angular',
productCode: 'KENDOUIANGULAR',
productCodes: ['KENDOUIANGULAR'],
publishDate: 1756992870,
version: '20.0.3',
licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
};
/**
* @hidden
* Default settings for the Speech to Text button.
* These settings can be overridden by the user.
*/
const STB_DEFAULT_SETTINGS$1 = {
continuous: false,
disabled: false,
fillMode: 'flat',
integrationMode: 'webSpeech',
interimResults: false,
lang: 'en-US',
maxAlternatives: 1,
rounded: 'medium',
size: 'medium',
themeColor: 'base'
};
/**
* @hidden
*/
class AIPromptService {
aiPrompt;
promptValue = '';
showOutputRating = false;
requestEvent = new Subject();
executeEvent = new Subject();
outputCopyEvent = new Subject();
outputRatingChangeEvent = new Subject();
promptCommands;
promptOutputs;
promptSuggestions;
textAreaSettings;
outputTemplate;
outputBodyTemplate;
_speechToTextButton;
get speechToTextButton() {
return this._speechToTextButton;
}
set speechToTextButton(settings) {
if (settings === true) {
this._speechToTextButton = STB_DEFAULT_SETTINGS$1;
}
else if (settings === false) {
this._speechToTextButton = null;
}
else {
this._speechToTextButton = { ...settings };
}
}
getFlattenPromptCommands(commands = this.promptCommands) {
let newArr = [];
commands.forEach(c => {
if (c.hasOwnProperty('children')) {
const childrenArr = c.children;
newArr = newArr.concat(childrenArr);
if (childrenArr.length > 0) {
this.getFlattenPromptCommands(childrenArr);
}
}
});
return newArr.concat(this.promptCommands);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptService, decorators: [{
type: Injectable
}] });
/**
* Represents a template for additional Toolbar actions.
* The actions appear after the Toolbar buttons for all views.
*
* To define the template, nest an `<ng-template>` tag
* with the `kendoAIPromptToolbarActionsTemplate` directive inside the `<kendo-aiprompt>` tag.
*
* @example
* ```html
* <kendo-aiprompt>
* <ng-template kendoAIPromptToolbarActionsTemplate>
* <button kendoButton>Custom Action</button>
* </ng-template>
* </kendo-aiprompt>
* ```
*/
class AIPromptToolbarActionsDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptToolbarActionsDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: AIPromptToolbarActionsDirective, isStandalone: true, selector: "[kendoAIPromptToolbarActionsTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptToolbarActionsDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoAIPromptToolbarActionsTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{
type: Optional
}] }]; } });
/**
* @hidden
*/
class ToolbarNavigationService {
localizationService;
focusableElements = [];
currentFocusedIndex = 0;
constructor(localizationService) {
this.localizationService = localizationService;
}
register(tool) {
if (!this.focusableElements.some(el => el === tool)) {
this.focusableElements.push(tool);
}
}
unregister(tool) {
this.currentFocusedIndex = 0;
this.focusableElements = this.focusableElements.filter(el => el !== tool);
}
isActive(focusable) {
return this.focusableElements[this.currentFocusedIndex] === focusable;
}
setActiveIndex(tool) {
this.currentFocusedIndex = Math.max(this.focusableElements.indexOf(tool), 0);
}
move(direction) {
let delta = direction === 'right' ? 1 : -1;
if (this.localizationService.rtl) {
delta = -delta;
}
this.currentFocusedIndex += delta;
if (this.currentFocusedIndex < 0) {
this.currentFocusedIndex = this.focusableElements.length - 1;
}
else if (this.currentFocusedIndex >= this.focusableElements.length) {
this.currentFocusedIndex = 0;
}
this.focusableElements[this.currentFocusedIndex].activate();
}
focusFirst() {
this.focusableElements[this.currentFocusedIndex].activate();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ToolbarNavigationService, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ToolbarNavigationService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ToolbarNavigationService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/**
* @hidden
*/
class AIPromptToolbarFocusableDirective {
host;
navigationService;
renderer;
constructor(host, navigationService, renderer) {
this.host = host;
this.navigationService = navigationService;
this.renderer = renderer;
navigationService.register(this);
}
get element() {
return this.host.nativeElement;
}
ngAfterViewInit() {
this.renderer.setAttribute(this.element, 'tabindex', this.navigationService.isActive(this) ? '0' : '-1');
this.element.addEventListener('keydown', this.keyDownHandler, { capture: true });
this.element.addEventListener('click', this.clickHandler, { capture: true });
}
ngOnDestroy() {
this.navigationService.unregister(this);
this.element.removeEventListener('keydown', this.keyDownHandler, { capture: true });
this.element.removeEventListener('click', this.clickHandler, { capture: true });
}
activate() {
this.renderer.setAttribute(this.element, 'tabindex', '0');
this.element.focus();
}
keyDownHandler = (e) => {
const code = normalizeNumpadKeys(e);
const targetsSelf = e.target === this.element;
const isLeftArrow = code === Keys.ArrowLeft;
const isRightArrow = code === Keys.ArrowRight;
const isArrow = isLeftArrow || isRightArrow;
if (!targetsSelf || !isArrow) {
return;
}
this.renderer.setAttribute(this.element, 'tabindex', '-1');
this.element.querySelectorAll(focusableSelector).forEach(el => {
this.renderer.setAttribute(el, 'tabindex', '-1');
});
if (isRightArrow) {
this.navigationService.move('right');
}
else if (isLeftArrow) {
this.navigationService.move('left');
}
};
clickHandler = () => {
this.navigationService.setActiveIndex(this);
};
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptToolbarFocusableDirective, deps: [{ token: i0.ElementRef }, { token: ToolbarNavigationService }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: AIPromptToolbarFocusableDirective, isStandalone: true, selector: "[kendoAIPromptToolbarFocusable]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptToolbarFocusableDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoAIPromptToolbarFocusable]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ToolbarNavigationService }, { type: i0.Renderer2 }]; } });
/**
* @hidden
*/
let Messages$2 = class Messages extends ComponentMessages {
/**
* Sets the Toolbar button text for the **Prompt** view.
*/
promptView;
/**
* Sets the Toolbar button text for the **Output** view.
*/
outputView;
/**
* Sets the text for the **Generate** button in the **Prompt** view.
*/
generateOutput;
/**
* Sets the placeholder text for the **Prompt** view text area.
*/
promptPlaceholder;
/**
* Sets the text for the **Copy** button text in each **Output** view card.
*/
copyOutput;
/**
* Sets the **Retry** button text in each **Output** view card.
*/
retryGeneration;
/**
* Sets the title of each card in the **Output** view.
*/
outputTitle;
/**
* Sets the title of each retry card in the **Output** view.
*/
outputRetryTitle;
/**
* Sets the title of the **Prompt suggestions** button.
*/
promptSuggestions;
/**
* Sets the aria-label for the **Speech to Text** button.
*/
speechToTextButton;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: Messages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: Messages, inputs: { promptView: "promptView", outputView: "outputView", generateOutput: "generateOutput", promptPlaceholder: "promptPlaceholder", copyOutput: "copyOutput", retryGeneration: "retryGeneration", outputTitle: "outputTitle", outputRetryTitle: "outputRetryTitle", promptSuggestions: "promptSuggestions", speechToTextButton: "speechToTextButton" }, usesInheritance: true, ngImport: i0 });
};
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: Messages$2, decorators: [{
type: Directive
}], propDecorators: { promptView: [{
type: Input
}], outputView: [{
type: Input
}], generateOutput: [{
type: Input
}], promptPlaceholder: [{
type: Input
}], copyOutput: [{
type: Input
}], retryGeneration: [{
type: Input
}], outputTitle: [{
type: Input
}], outputRetryTitle: [{
type: Input
}], promptSuggestions: [{
type: Input
}], speechToTextButton: [{
type: Input
}] } });
/**
* @hidden
*/
let LocalizedMessagesDirective$2 = class LocalizedMessagesDirective extends Messages$2 {
service;
constructor(service) {
super();
this.service = service;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LocalizedMessagesDirective, isStandalone: true, selector: "[kendoAIPromptLocalizedMessages]", providers: [
{
provide: Messages$2,
useExisting: forwardRef(() => LocalizedMessagesDirective)
}
], usesInheritance: true, ngImport: i0 });
};
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedMessagesDirective$2, decorators: [{
type: Directive,
args: [{
providers: [
{
provide: Messages$2,
useExisting: forwardRef(() => LocalizedMessagesDirective$2)
}
],
selector: '[kendoAIPromptLocalizedMessages]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/**
* Represents the template for the response in the AIPrompt component. The template context is set to the current output object.
*
* @example
* ```html
* <kendo-aiprompt>
* <ng-template kendoAIPromptOutputTemplate let-output>
* <div>{{output.prompt}}</div>
* </ng-template>
* </kendo-aiprompt>
* ```
*/
class AIPromptOutputTemplateDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptOutputTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: AIPromptOutputTemplateDirective, isStandalone: true, selector: "[kendoAIPromptOutputTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptOutputTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoAIPromptOutputTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
/**
* Represents the template for the body of the response in the AIPrompt component. The template context is set to the current output object.
*
* @example
* ```html
* <kendo-aiprompt>
* <ng-template kendoAIPromptOutputBodyTemplate let-output>
* <div>{{output.prompt}}</div>
* </ng-template>
* </kendo-aiprompt>
* ```
*/
class AIPromptOutputBodyTemplateDirective {
templateRef;
constructor(templateRef) {
this.templateRef = templateRef;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptOutputBodyTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: AIPromptOutputBodyTemplateDirective, isStandalone: true, selector: "[kendoAIPromptOutputBodyTemplate]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptOutputBodyTemplateDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoAIPromptOutputBodyTemplate]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
/**
* Represents the [Kendo UI AIPrompt component for Angular](slug:overview_aiprompt).
*
* @example
* ```html
* <kendo-aiprompt
* [promptCommands]="commands"
* [promptSuggestions]="suggestions"
* [promptOutputs]="outputs"
* [showOutputRating]="true"
* (promptRequest)="onPromptRequest($event)">
* </kendo-aiprompt>
* ```
*
* @remarks
* Supported children components are: {@link AIPromptCustomMessagesComponent}, {@link CustomViewComponent}, {@link CommandViewComponent}, {@link PromptViewComponent}, {@link OutputViewComponent}.
*/
class AIPromptComponent {
localization;
service;
navigationService;
ngZone;
element;
renderer;
hostClasses = true;
get dirAttr() {
return this.direction;
}
constructor(localization, service, navigationService, ngZone, element, renderer) {
this.localization = localization;
this.service = service;
this.navigationService = navigationService;
this.ngZone = ngZone;
this.element = element;
this.renderer = renderer;
validatePackage(packageMetadata);
this.direction = localization.rtl ? 'rtl' : 'ltr';
this.subs.add(localization.changes.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
}));
}
/**
* @hidden
*/
fabButton;
/**
* @hidden
*/
views;
/**
* @hidden
*/
toolbarActionsTemplate;
/**
* @hidden
*/
outputTemplate;
/**
* @hidden
*/
outputBodyTemplate;
/**
* The active view index of the AIPrompt component.
*/
set activeView(idx) {
if (this._activeView !== idx) {
this._activeView = idx;
this.service.promptValue && (this.service.promptValue = '');
}
}
get activeView() {
return this._activeView;
}
/**
* Sets the collection of commands to render in the Command view.
*/
set promptCommands(value) {
this.service.promptCommands = value;
}
/**
* Sets the collection of suggestions to render in the Prompt view.
*/
set promptSuggestions(value) {
this.service.promptSuggestions = value;
}
/**
* Sets the collection of generated prompt outputs to render in the Output view.
*/
set promptOutputs(value) {
this.service.promptOutputs = value;
}
/**
* Specifies whether the rating buttons appear in each Output view card.
* The rating buttons do not appear by default.
* @default false
*/
set showOutputRating(value) {
this.service.showOutputRating = value;
}
/**
* Specifies whether the Stop generation button appears in the Output view.
* The Stop generation button does not appear by default.
* @default false
*/
streaming = false;
/**
* Sets the settings for the Speech to Text button in the Prompt view
* ([see example](slug:configuration_aiprompt#enabling-speech-to-text)).
*/
set speechToTextButton(settings) {
if (settings) {
this.service.speechToTextButton = settings;
}
else {
this.service.speechToTextButton = false;
}
}
/**
* Sets the settings for the TextArea in the Prompt view
* ([see example](slug:configuration_aiprompt#configuring-the-prompt-text-area)).
*/
set textAreaSettings(settings) {
this.service.textAreaSettings = settings;
}
/**
* Sets the SVG icon for the Generate button in the Prompt view.
*/
generateButtonSVGIcon = sparklesIcon;
/**
* Sets the icon for the Generate button in the Prompt view.
* @default 'sparkles'
*/
generateButtonIcon = 'sparkles';
/**
* Sets the disabled state for the Generate button in the Prompt view.
* @default false
*/
disabledGenerateButton = false;
/**
* Fires when the `activeView` property is updated.
* Use this event for two-way binding of the `activeView` property.
*/
activeViewChange = new EventEmitter();
/**
* Fires when you click the Generate button in the Prompt view or the Retry button in the Output view.
* Use the event's `isRetry` field to determine the source element.
*/
promptRequest = new EventEmitter();
/**
* Fires when you click a Command view command.
* The event data contains the selected command.
*/
commandExecute = new EventEmitter();
/**
* Fires when you click a Copy button in any Output view card.
*/
outputCopy = new EventEmitter();
/**
* Fires when you click a rating button in any Output view card.
*/
outputRatingChange = new EventEmitter();
/**
* Fires when you click the Stop Generation button in the Output view.
*/
promptRequestCancel = new EventEmitter();
ngOnInit() {
const aiPromptElement = this.element.nativeElement;
this.subs.add(this.renderer.listen(aiPromptElement, 'keydown', (event) => {
if (event.key === 'Escape') {
this.promptRequestCancel.emit();
}
}));
}
ngOnChanges(changes) {
if (changes['streaming'] && changes['streaming'].currentValue === true) {
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
this.fabButton?.focus();
});
}
}
ngAfterContentChecked() {
if (this.outputTemplate !== this.service.outputTemplate) {
this.service.outputTemplate = this.outputTemplate;
}
if (this.outputBodyTemplate !== this.service.outputBodyTemplate) {
this.service.outputBodyTemplate = this.outputBodyTemplate;
}
}
ngAfterViewInit() {
this.ngZone.runOutsideAngular(() => {
this.service.aiPrompt = this;
this.subs.add(this.service.requestEvent.subscribe(ev => this.promptRequest.emit(ev)));
this.subs.add(this.service.executeEvent.subscribe(ev => this.commandExecute.emit(ev)));
this.subs.add(this.service.outputCopyEvent.subscribe(ev => this.outputCopy.emit(ev)));
this.subs.add(this.service.outputRatingChangeEvent.subscribe(ev => this.outputRatingChange.emit(ev)));
});
}
ngOnDestroy() {
this.subs.unsubscribe();
}
/**
* Focuses the first focusable element in the AIPrompt component.
*/
focus() {
this.navigationService.focusFirst();
}
subs = new Subscription();
/**
* @hidden
*/
get selectedView() {
return this.viewsArray[this.activeView];
}
/**
* @hidden
*/
sparklesIcon = sparklesIcon;
/**
* @hidden
*/
outputIcon = commentIcon;
/**
* @hidden
*/
fabStopGenerationSVGIcon = stopSmIcon;
/**
* @hidden
*/
get viewsArray() {
return this.views?.toArray();
}
/**
* @hidden
*/
fabPositionMode = 'absolute';
/**
* @hidden
*/
fabAlignment = { vertical: 'bottom', horizontal: 'end' };
direction;
_activeView = 0;
/**
* @hidden
*/
viewChange(idx) {
if (idx !== this.activeView) {
this.activeView = idx;
this.activeViewChange.emit(idx);
}
}
/**
* @hidden
*/
messageFor(text) {
return this.localization.get(text);
}
/**
* @hidden
*/
get viewTemplate() {
return this.selectedView?.viewType === 'custom' ? this.selectedView?.viewTemplate : this.selectedView?.template;
}
/**
* @hidden
*/
handleGenerateOutput() {
const value = this.service.promptValue;
const eventArgs = {
prompt: value,
sender: this,
isRetry: false
};
this.promptRequest.emit(eventArgs);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptComponent, deps: [{ token: i1.LocalizationService }, { token: AIPromptService }, { token: ToolbarNavigationService }, { token: i0.NgZone }, { token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AIPromptComponent, isStandalone: true, selector: "kendo-aiprompt", inputs: { activeView: "activeView", promptCommands: "promptCommands", promptSuggestions: "promptSuggestions", promptOutputs: "promptOutputs", showOutputRating: "showOutputRating", streaming: "streaming", speechToTextButton: "speechToTextButton", textAreaSettings: "textAreaSettings", generateButtonSVGIcon: "generateButtonSVGIcon", generateButtonIcon: "generateButtonIcon", disabledGenerateButton: "disabledGenerateButton" }, outputs: { activeViewChange: "activeViewChange", promptRequest: "promptRequest", commandExecute: "commandExecute", outputCopy: "outputCopy", outputRatingChange: "outputRatingChange", promptRequestCancel: "promptRequestCancel" }, host: { properties: { "class.k-prompt": "this.hostClasses", "attr.dir": "this.dirAttr" } }, providers: [
LocalizationService,
AIPromptService,
ToolbarNavigationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.aiprompt'
}
], queries: [{ propertyName: "toolbarActionsTemplate", first: true, predicate: AIPromptToolbarActionsDirective, descendants: true }, { propertyName: "outputTemplate", first: true, predicate: AIPromptOutputTemplateDirective, descendants: true }, { propertyName: "outputBodyTemplate", first: true, predicate: AIPromptOutputBodyTemplateDirective, descendants: true }, { propertyName: "views", predicate: BaseView }], viewQueries: [{ propertyName: "fabButton", first: true, predicate: ["fabButton"], descendants: true }], exportAs: ["kendoAIPrompt"], usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoAIPromptLocalizedMessages
i18n-promptView="kendo.aiprompt.promptView|The Toolbar button text for the Prompt view."
promptView="Ask AI"
i18n-outputView="kendo.aiprompt.outputView|The Toolbar button text for the Output view."
outputView="Output"
i18n-generateOutput="kendo.aiprompt.generateOutput|The text for the Generate button in the Prompt view."
generateOutput="Generate"
i18n-promptPlaceholder="kendo.aiprompt.promptPlaceholder|The placeholder text for the Prompt View text area."
promptPlaceholder="Ask or generate content with AI"
i18n-copyOutput="kendo.aiprompt.copyOutput|The Copy button text in each Output view card."
copyOutput="Copy"
i18n-retryGeneration="kendo.aiprompt.retryGeneration|The Retry button text in each Output view card."
retryGeneration="Retry"
i18n-outputTitle="kendo.aiprompt.outputTitle|The title of each Output view card."
outputTitle="Generated with AI"
i18n-outputRetryTitle="kendo.aiprompt.outputRetryTitle|The title of each Output view retry card."
outputRetryTitle="Generated with AI"
i18n-promptSuggestions="kendo.aiprompt.promptSuggestions|The title of the Prompt suggestions button."
promptSuggestions="Prompt suggestions"
i18n-speechToTextButton="kendo.aiprompt.speechToTextButton|The aria-label for the Speech to Text button."
speechToTextButton="Voice input">
</ng-container>
<div class="k-prompt-header">
<div class="k-toolbar-flat k-toolbar k-toolbar-md"
role="toolbar">
<button *ngFor="let view of viewsArray; let idx = index"
kendoButton
kendoAIPromptToolbarFocusable
type="button"
fillMode="flat"
rounded="full"
themeColor="primary"
[svgIcon]="view.svgIcon"
[icon]="view.icon"
[selected]="idx === activeView"
(click)="viewChange(idx)">
{{view.buttonText}}
</button>
<ng-template *ngIf="toolbarActionsTemplate"
[ngTemplateOutlet]="toolbarActionsTemplate?.templateRef">
</ng-template>
</div>
</div>
<div class="k-prompt-content">
<kendo-floatingactionbutton #fabButton *ngIf="streaming && selectedView?.viewType === 'output'"
class="k-prompt-stop-fab"
buttonClass="k-generating k-active"
[positionMode]="fabPositionMode"
[align]="fabAlignment"
[svgIcon]="fabStopGenerationSVGIcon"
icon="stop"
(click)="promptRequestCancel.emit()"
>
</kendo-floatingactionbutton>
<div class="k-prompt-view">
<ng-container *ngTemplateOutlet="viewTemplate">
</ng-container>
</div>
</div>
<div class="k-prompt-footer" *ngIf="selectedView?.viewType === 'prompt'">
<div class="k-actions k-actions-start k-actions-horizontal k-prompt-actions">
<button
kendoButton
type="button"
themeColor="primary"
rounded="full"
[attr.title]="messageFor('generateOutput')"
[attr.aria-label]="messageFor('generateOutput')"
[attr.aria-disabled]="disabledGenerateButton"
[svgIcon]="generateButtonSVGIcon"
[icon]="generateButtonIcon"
[disabled]="disabledGenerateButton"
(click)="handleGenerateOutput()">{{messageFor('generateOutput')}}</button>
</div>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective$2, selector: "[kendoAIPromptLocalizedMessages]" }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "directive", type: AIPromptToolbarFocusableDirective, selector: "[kendoAIPromptToolbarFocusable]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FloatingActionButtonComponent, selector: "kendo-floatingactionbutton", inputs: ["themeColor", "size", "rounded", "disabled", "align", "offset", "positionMode", "icon", "svgIcon", "iconClass", "buttonClass", "dialClass", "text", "dialItemAnimation", "tabIndex", "dialItems"], outputs: ["blur", "focus", "dialItemClick", "open", "close"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AIPromptComponent, decorators: [{
type: Component,
args: [{
exportAs: 'kendoAIPrompt',
selector: 'kendo-aiprompt',
providers: [
LocalizationService,
AIPromptService,
ToolbarNavigationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.aiprompt'
}
],
template: `
<ng-container kendoAIPromptLocalizedMessages
i18n-promptView="kendo.aiprompt.promptView|The Toolbar button text for the Prompt view."
promptView="Ask AI"
i18n-outputView="kendo.aiprompt.outputView|The Toolbar button text for the Output view."
outputView="Output"
i18n-generateOutput="kendo.aiprompt.generateOutput|The text for the Generate button in the Prompt view."
generateOutput="Generate"
i18n-promptPlaceholder="kendo.aiprompt.promptPlaceholder|The placeholder text for the Prompt View text area."
promptPlaceholder="Ask or generate content with AI"
i18n-copyOutput="kendo.aiprompt.copyOutput|The Copy button text in each Output view card."
copyOutput="Copy"
i18n-retryGeneration="kendo.aiprompt.retryGeneration|The Retry button text in each Output view card."
retryGeneration="Retry"
i18n-outputTitle="kendo.aiprompt.outputTitle|The title of each Output view card."
outputTitle="Generated with AI"
i18n-outputRetryTitle="kendo.aiprompt.outputRetryTitle|The title of each Output view retry card."
outputRetryTitle="Generated with AI"
i18n-promptSuggestions="kendo.aiprompt.promptSuggestions|The title of the Prompt suggestions button."
promptSuggestions="Prompt suggestions"
i18n-speechToTextButton="kendo.aiprompt.speechToTextButton|The aria-label for the Speech to Text button."
speechToTextButton="Voice input">
</ng-container>
<div class="k-prompt-header">
<div class="k-toolbar-flat k-toolbar k-toolbar-md"
role="toolbar">
<button *ngFor="let view of viewsArray; let idx = index"
kendoButton
kendoAIPromptToolbarFocusable
type="button"
fillMode="flat"
rounded="full"
themeColor="primary"
[svgIcon]="view.svgIcon"
[icon]="view.icon"
[selected]="idx === activeView"
(click)="viewChange(idx)">
{{view.buttonText}}
</button>
<ng-template *ngIf="toolbarActionsTemplate"
[ngTemplateOutlet]="toolbarActionsTemplate?.templateRef">
</ng-template>
</div>
</div>
<div class="k-prompt-content">
<kendo-floatingactionbutton #fabButton *ngIf="streaming && selectedView?.viewType === 'output'"
class="k-prompt-stop-fab"
buttonClass="k-generating k-active"
[positionMode]="fabPositionMode"
[align]="fabAlignment"
[svgIcon]="fabStopGenerationSVGIcon"
icon="stop"
(click)="promptRequestCancel.emit()"
>
</kendo-floatingactionbutton>
<div class="k-prompt-view">
<ng-container *ngTemplateOutlet="viewTemplate">
</ng-container>
</div>
</div>
<div class="k-prompt-footer" *ngIf="selectedView?.viewType === 'prompt'">
<div class="k-actions k-actions-start k-actions-horizontal k-prompt-actions">
<button
kendoButton
type="button"
themeColor="primary"
rounded="full"
[attr.title]="messageFor('generateOutput')"
[attr.aria-label]="messageFor('generateOutput')"
[attr.aria-disabled]="disabledGenerateButton"
[svgIcon]="generateButtonSVGIcon"
[icon]="generateButtonIcon"
[disabled]="disabledGenerateButton"
(click)="handleGenerateOutput()">{{messageFor('generateOutput')}}</button>
</div>
</div>
`,
standalone: true,
imports: [LocalizedMessagesDirective$2, NgFor, ButtonComponent, AIPromptToolbarFocusableDirective, NgIf, NgTemplateOutlet, FloatingActionButtonComponent]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: AIPromptService }, { type: ToolbarNavigationService }, { type: i0.NgZone }, { type: i0.ElementRef }, { type: i0.Renderer2 }]; }, propDecorators: { hostClasses: [{
type: HostBinding,
args: ['class.k-prompt']
}], dirAttr: [{
type: HostBinding,
args: ['attr.dir']
}], fabButton: [{
type: ViewChild,
args: ['fabButton']
}], views: [{
type: ContentChildren,
args: [BaseView]
}], toolbarActionsTemplate: [{
type: ContentChild,
args: [AIPromptToolbarActionsDirective]
}], outputTemplate: [{
type: ContentChild,
args: [AIPromptOutputTemplateDirective]
}], outputBodyTemplate: [{
type: ContentChild,
args: [AIPromptOutputBodyTemplateDirective]
}], activeView: [{
type: Input
}], promptCommands: [{
type: Input
}], promptSuggestions: [{
type: Input
}], promptOutputs: [{
type: Input
}], showOutputRating: [{
type: Input
}], streaming: [{
type: Input
}], speechToTextButton: [{
type: Input
}], textAreaSettings: [{
type: Input
}], generateButtonSVGIcon: [{
type: Input
}], generateButtonIcon: [{
type: Input
}], disabledGenerateButton: [{
type: Input
}], activeViewChange: [{
type: Output
}], promptRequest: [{
type: Output
}], commandExecute: [{
type: Output
}], outputCopy: [{
type: Output
}], outputRatingChange: [{
type: Output
}], promptRequestCancel: [{
type: Output
}] } });
/**
* Represents the component that renders the **Command** view of the AIPrompt.
*
* @example
* ```html
* <kendo-aiprompt-command-view
* buttonText="My command view">
* </kendo-aiprompt-command-view>
* ```
*/
class CommandViewComponent extends BaseView {
service;
constructor(localization, service) {
super('command', localization);
this.service = service;
}
/**
* @hidden
*/
panelBarItems = [];
ngOnInit() {
if (this.service.promptCommands) {
this.panelBarItems = this.getPanelBarItems(this.service.promptCommands);
}
}
/**
* @hidden
*/
itemClickHandler(ev) {
if (ev.item.children) {
return;
}
const selectedCommand = this.service.getFlattenPromptCommands().find(c => c.id == ev.item.id);
if (selectedCommand) {
const eventArgs = {
command: selectedCommand,
sender: this.service.aiPrompt,
isRetry: false
};
this.service.executeEvent.next(eventArgs);
}
}
getPanelBarItems(commands) {
return commands.map(c => ({
title: c.text,
id: c.id,
icon: c.icon,
svgIcon: c.svgIcon,
children: c.children ? this.getPanelBarItems(c.children) : null
}));
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CommandViewComponent, deps: [{ token: i1.LocalizationService }, { token: AIPromptService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: CommandViewComponent, isStandalone: true, selector: "kendo-aiprompt-command-view", providers: [{
provide: BaseView,
useExisting: forwardRef(() => CommandViewComponent)
}], usesInheritance: true, ngImport: i0, template: `
<ng-template #content>
<kendo-panelbar
[items]="panelBarItems"
[animate]="false"
[selectable]="false"
(itemClick)="itemClickHandler($event)"
></kendo-panelbar>
</ng-template>
`, isInline: true, dependencies: [{ kind: "component", type: PanelBarComponent, selector: "kendo-panelbar", inputs: ["expandMode", "selectable", "animate", "height", "keepItemContent", "items"], outputs: ["stateChange", "select", "expand", "collapse", "itemClick"], exportAs: ["kendoPanelbar"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CommandViewComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-aiprompt-command-view',
providers: [{
provide: BaseView,
useExisting: forwardRef(() => CommandViewComponent)
}],
template: `
<ng-template #content>
<kendo-panelbar
[items]="panelBarItems"
[animate]="false"
[selectable]="false"
(itemClick)="itemClickHandler($event)"
></kendo-panelbar>
</ng-template>
`,
standalone: true,
imports: [PanelBarComponent]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: AIPromptService }]; } });
/**
* Represents the custom messages component of the AIPrompt.
*
* Use this component to override default messages for the AIPrompt
* ([see example](slug:globalization_chat#custom-messages)).
*
* @example
* ```html
* <kendo-aiprompt-messages
* promptView="My prompt view"
* outputView="My output view">
* </kendo-aiprompt-messages>
* ```
*/
class AIPromptCustomMessagesComponent extends Messages$2 {
service;
constructor(service) {
super();
this.service = service;
}
get override() {
return true;
}
static ɵfac = i0.