UNPKG

@progress/kendo-angular-conversational-ui

Version:

Kendo UI for Angular Conversational UI components

1,224 lines (1,205 loc) 309 kB
/**----------------------------------------------------------------------------------------- * 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.