@progress/kendo-angular-conversational-ui
Version:
Kendo UI for Angular Conversational UI components
387 lines (384 loc) • 17.4 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 { Component, ContentChild, ContentChildren, EventEmitter, HostBinding, Input, NgZone, Output, QueryList } from "@angular/core";
import { NgFor, NgIf, NgTemplateOutlet } from "@angular/common";
import { Subscription } from "rxjs";
import { sparklesIcon, commentIcon } from "@progress/kendo-svg-icons";
import { L10N_PREFIX, LocalizationService } from '@progress/kendo-angular-l10n';
import { validatePackage } from "@progress/kendo-licensing";
import { ButtonComponent } from "@progress/kendo-angular-buttons";
import { BaseView } from "./views/base-view";
import { packageMetadata } from "../package-metadata";
import { AIPromptService } from "./common/aiprompt.service";
import { AIPromptToolbarActionsDirective } from "./templates/toolbar-actions.template";
import { ToolbarNavigationService } from "./common/toolbar-navigation.service";
import { AIPromptToolbarFocusableDirective } from "./common/toolbar-focusable.directive";
import { LocalizedMessagesDirective } from "./localization/localized-messages.directive";
import * as i0 from "@angular/core";
import * as i1 from "@progress/kendo-angular-l10n";
import * as i2 from "./common/aiprompt.service";
import * as i3 from "./common/toolbar-navigation.service";
/**
* 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}.
*/
export class AIPromptComponent {
localization;
service;
navigationService;
ngZone;
hostClasses = true;
get dirAttr() {
return this.direction;
}
constructor(localization, service, navigationService, ngZone) {
this.localization = localization;
this.service = service;
this.navigationService = navigationService;
this.ngZone = ngZone;
validatePackage(packageMetadata);
this.direction = localization.rtl ? 'rtl' : 'ltr';
this.subs.add(localization.changes.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
}));
}
/**
* @hidden
*/
views;
/**
* @hidden
*/
toolbarActionsTemplate;
/**
* 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 if the rating buttons appear in each **Output** view card.
* By default, the rating buttons do not appear.
* @default false
*/
set showOutputRating(value) {
this.service.showOutputRating = value;
}
/**
* Fires when the `activeView` property is updated.
* Use this event for two-way binding of the `activeView` property.
*/
activeViewChange = new EventEmitter();
/**
* Fires when the user clicks 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 the user clicks a **Command** view command.
* The event data contains the selected command.
*/
commandExecute = new EventEmitter();
/**
* Fires when the user clicks a **Copy** button in any **Output** view card.
*/
outputCopy = new EventEmitter();
/**
* Fires when the user clicks a rating button in any **Output** view card.
*/
outputRatingChange = new EventEmitter();
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
*/
get viewsArray() {
return this.views?.toArray();
}
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: i2.AIPromptService }, { token: i3.ToolbarNavigationService }, { token: i0.NgZone }], 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" }, outputs: { activeViewChange: "activeViewChange", promptRequest: "promptRequest", commandExecute: "commandExecute", outputCopy: "outputCopy", outputRatingChange: "outputRatingChange" }, 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: "views", predicate: BaseView }], exportAs: ["kendoAIPrompt"], 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">
</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">
<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"
[svgIcon]="sparklesIcon"
icon="sparkles"
(click)="handleGenerateOutput()">{{messageFor('generateOutput')}}</button>
</div>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, 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"] }] });
}
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">
</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">
<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"
[svgIcon]="sparklesIcon"
icon="sparkles"
(click)="handleGenerateOutput()">{{messageFor('generateOutput')}}</button>
</div>
</div>
`,
standalone: true,
imports: [LocalizedMessagesDirective, NgFor, ButtonComponent, AIPromptToolbarFocusableDirective, NgIf, NgTemplateOutlet]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i2.AIPromptService }, { type: i3.ToolbarNavigationService }, { type: i0.NgZone }]; }, propDecorators: { hostClasses: [{
type: HostBinding,
args: ['class.k-prompt']
}], dirAttr: [{
type: HostBinding,
args: ['attr.dir']
}], views: [{
type: ContentChildren,
args: [BaseView]
}], toolbarActionsTemplate: [{
type: ContentChild,
args: [AIPromptToolbarActionsDirective]
}], activeView: [{
type: Input
}], promptCommands: [{
type: Input
}], promptSuggestions: [{
type: Input
}], promptOutputs: [{
type: Input
}], showOutputRating: [{
type: Input
}], activeViewChange: [{
type: Output
}], promptRequest: [{
type: Output
}], commandExecute: [{
type: Output
}], outputCopy: [{
type: Output
}], outputRatingChange: [{
type: Output
}] } });