@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
1,606 lines • 57.8 kB
JavaScript
require("./kendo.core-kmRaf_Lg.js");
require("./kendo.icons.js");
require("./kendo.button.js");
require("./kendo.data-T0mqWOrQ.js");
require("./kendo.toolbar.js");
require("./kendo.textarea.js");
require("./kendo.speechtotextbutton.js");
require("./kendo.skeletoncontainer.js");
require("./kendo.panelbar.js");
require("./kendo.floatingactionbutton.js");
//#region ../src/aiprompt/output-action-manager.js
(function($) {
const messageTypes = {
"ai": "assistant",
"system": "system",
"user": "user",
"tool": "tool"
};
class AIPromptOutputActionManager {
constructor(aiprompt, options = {}) {
this.aiprompt = aiprompt;
this.options = options;
this.buttonDefinitions = this._createButtonDefinitions();
}
static getBuiltInActionDefinitions() {
return {
copy: {
command: "copy",
icon: "copy",
fillMode: "flat",
themeColor: "primary",
text: null
},
retry: {
command: "retry",
icon: "arrow-rotate-cw",
fillMode: "flat",
text: null
},
ratePositive: {
command: "ratePositive",
icon: "thumb-up",
fillMode: "flat",
iconButton: true,
text: null
},
rateNegative: {
command: "rateNegative",
icon: "thumb-down",
fillMode: "flat",
iconButton: true,
text: null
},
stop: {
command: "stop",
icon: "stop",
fillMode: "flat",
text: null
}
};
}
static processOutputActions(actions) {
if (!actions) return null;
const builtInActions = AIPromptOutputActionManager.getBuiltInActionDefinitions();
return actions.map((action) => {
if (typeof action === "string") {
if (action === "rating") return [builtInActions.ratePositive, builtInActions.rateNegative];
else if (action === "spacer") return { type: "spacer" };
return builtInActions[action] || {
command: action,
type: "button"
};
}
if (kendo.isPresent(action.command) && action.command == "rating") return [builtInActions.ratePositive, builtInActions.rateNegative];
return action;
}).flat();
}
_createButtonDefinitions() {
const that = this;
const baseDefinitions = AIPromptOutputActionManager.getBuiltInActionDefinitions();
return {
copy: {
...baseDefinitions.copy,
getMessage: () => that.view.options.messages.copyOutput,
handler: (e, promptOutput) => that._handleCopyAction(e, promptOutput)
},
retry: {
...baseDefinitions.retry,
getMessage: () => that.view.options.messages.retryGeneration,
handler: (e, promptOutput) => that._handleRetryAction(e, promptOutput)
},
ratePositive: {
...baseDefinitions.ratePositive,
getMessage: () => that.view.options.messages.ratePositive,
handler: (e, promptOutput) => that._handleRatePositiveAction(e, promptOutput)
},
rateNegative: {
...baseDefinitions.rateNegative,
getMessage: () => that.view.options.messages.rateNegative,
handler: (e, promptOutput) => that._handleRateNegativeAction(e, promptOutput)
},
stop: {
...baseDefinitions.stop,
getMessage: () => that.view.options.messages.stopGeneration,
handler: (e, promptOutput) => that._handleStopAction(e, promptOutput)
}
};
}
initializeButtons(container, actions = null) {
const that = this;
if (actions) actions.forEach((action) => {
if (action.type === "spacer") return;
const selector = `[data-action-command="${action.command}"]`;
that._initializeButton(container, selector, action);
});
}
_initializeButton(container, selector, action) {
const that = this;
const definition = that.buttonDefinitions[action.command];
container.find(selector).kendoButton({
icon: action.icon || definition?.icon,
fillMode: action.fillMode || definition?.fillMode || "flat",
themeColor: action.themeColor || definition?.themeColor,
rounded: action.rounded,
click: function(e) {
const promptOutput = that.aiprompt.outputManager.getOutputFromElement(e.target);
const eventArgs = {
command: action.command,
outputId: promptOutput.id,
output: promptOutput.output || promptOutput.text || promptOutput || "",
prompt: promptOutput.prompt || "",
button: e.sender.element
};
if (definition?.handler && !that.aiprompt.trigger("outputAction", eventArgs)) definition.handler(e, promptOutput);
else if (!definition) that.aiprompt.trigger("outputAction", eventArgs);
}
});
}
_handleCopyAction(e, promptOutput) {
const hasCopyHandler = this.aiprompt._events && this.aiprompt._events.outputCopy && this.aiprompt._events.outputCopy.length > 0;
if (hasCopyHandler) kendo.logToConsole("The outputCopy event is deprecated. Use the outputAction event instead.", "warn");
const copyEventArgs = { output: promptOutput };
if (hasCopyHandler && this.aiprompt.trigger("outputCopy", copyEventArgs)) return;
if (navigator.clipboard && typeof navigator.clipboard.writeText === "function") navigator.clipboard.writeText(promptOutput.output || promptOutput.text || promptOutput || "");
}
_handleRetryAction(e, promptOutput) {
const { prompt, output } = this.aiprompt.outputManager.extractOutputData(promptOutput);
const that = this;
const retryEventArgs = {
prompt,
output: promptOutput,
isRetry: true,
history: [{
role: messageTypes.ai,
contents: [{
$type: "text",
text: output
}]
}]
};
const service = that.aiprompt?._selectedView?.service;
if (service) retryEventArgs.service = service;
if (that.aiprompt.trigger("promptRequest", retryEventArgs)) return;
if (that.aiprompt.options.service) that.aiprompt.transport?.read({
prompt,
history: retryEventArgs.history,
isRetry: true,
service: retryEventArgs.service
});
}
_handleRatePositiveAction(e, promptOutput) {
if (this.aiprompt._events && this.aiprompt._events.outputRating && this.aiprompt._events.outputRating.length > 0) kendo.logToConsole("The outputRating event is deprecated. Use the outputAction event instead.", "warn");
this.aiprompt.trigger("outputRating", {
rateType: "positive",
output: promptOutput
});
kendo.ui.icon(e.sender.element.find(".k-icon"), "thumb-up");
const negativeButton = $(e.target).siblings("[data-action-command='rateNegative'], [ref-rate-negative]");
kendo.ui.icon(negativeButton.find(".k-icon"), "thumb-down");
}
_handleRateNegativeAction(e, promptOutput) {
if (this.aiprompt._events && this.aiprompt._events.outputRating && this.aiprompt._events.outputRating.length > 0) kendo.logToConsole("The outputRating event is deprecated. Use the outputAction event instead.", "warn");
this.aiprompt.trigger("outputRating", {
rateType: "negative",
output: promptOutput
});
kendo.ui.icon(e.sender.element.find(".k-icon"), "thumb-down");
const positiveButton = $(e.target).siblings("[data-action-command='ratePositive'], [ref-rate-positive]");
kendo.ui.icon(positiveButton.find(".k-icon"), "thumb-up");
}
_handleStopAction(e, promptOutput) {
this.aiprompt.trigger("promptRequestCancel", { output: promptOutput });
$(e.target).siblings(".k-hidden").removeClass("k-hidden");
$(e.target).addClass("k-hidden");
}
destroy() {
this.aiprompt = null;
this.options = null;
this.buttonDefinitions = null;
}
}
kendo.ui.AIPromptOutputActionManager = AIPromptOutputActionManager;
})(window.kendo.jQuery);
//#endregion
//#region ../src/aiprompt/template-builder.js
(function($) {
const CSS_CLASSES = {
PROMPT_VIEW: "k-prompt-view",
PROMPT_EXPANDER: "k-prompt-expander",
SUGGESTION_GROUP: "k-suggestion-group",
SUGGESTION: "k-suggestion",
CARD: "k-card",
CARD_LIST: "k-card-list",
CARD_HEADER: "k-card-header",
CARD_TITLE: "k-card-title",
CARD_SUBTITLE: "k-card-subtitle",
CARD_BODY: "k-card-body",
CARD_ACTIONS: "k-card-actions",
ACTIONS: "k-actions k-actions-start k-actions-horizontal",
SPACER: "k-spacer",
HIDDEN: "k-hidden"
};
const REFS = {
PROMPT_INPUT: "ref-prompt-input",
SUGGESTIONS_BUTTON: "ref-prompt-suggestions-button",
GENERATE_BUTTON: "ref-generate-output-button",
OUTPUT_BODY: "ref-output-body",
COPY_BUTTON: "ref-copy-button",
RETRY_BUTTON: "ref-retry-button",
RATE_POSITIVE: "ref-rate-positive",
RATE_NEGATIVE: "ref-rate-negative",
STOP_GENERATION: "ref-stop-generation"
};
class AIPromptTemplateBuilder {
static createPromptView({ suggestions, promptSuggestionItemTemplate, messages }) {
const suggestionsHtml = suggestions?.length ? AIPromptTemplateBuilder._createSuggestionsSection(suggestions, promptSuggestionItemTemplate, messages) : "";
return `<div class="${CSS_CLASSES.PROMPT_VIEW}">
<textarea ${REFS.PROMPT_INPUT}></textarea>
${suggestionsHtml}
</div>`;
}
static createPromptFooter({ messages }) {
return `<div class="${CSS_CLASSES.ACTIONS} k-prompt-actions">
<button ${REFS.GENERATE_BUTTON}>${messages.generateOutput}</button>
</div>`;
}
static createSuggestionItem({ suggestion }) {
const encodedSuggestion = kendo.htmlEncode(suggestion);
return `<span role="button" aria-label="${encodedSuggestion}" class="${CSS_CLASSES.SUGGESTION}">${encodedSuggestion}</span>`;
}
static createOutputCard({ output, showOutputRating, messages, showOutputSubtitleTooltip, encodedPromptOutputs, isStreaming, outputActions, outputTemplate }) {
const contentHtml = AIPromptTemplateBuilder._generateContentHtml({
output,
outputTemplate,
encodedPromptOutputs
});
const actionsHtml = AIPromptTemplateBuilder._generateActionsHtml({
outputActions,
showOutputRating,
messages,
isStreaming
});
const dataIdAttr = output.id ? ` data-id="${output.id}"` : "";
return `<div role="listitem" tabindex="0" class="${CSS_CLASSES.CARD}"${dataIdAttr}>
${output.skipHeader ? "" : AIPromptTemplateBuilder._createCardHeader(output, messages, showOutputSubtitleTooltip)}
${output.skipBody ? "" : AIPromptTemplateBuilder._createCardBody(contentHtml, output.isLoading)}
${output.skipActions ? "" : actionsHtml}
</div>`;
}
static createOutputView({ promptOutputs, showOutputRating, messages, showOutputSubtitleTooltip, encodedPromptOutputs, outputActions, outputTemplate }) {
const cardsHtml = promptOutputs ? promptOutputs.map((output) => AIPromptTemplateBuilder.createOutputCard({
output,
showOutputRating,
messages,
showOutputSubtitleTooltip,
encodedPromptOutputs,
outputActions,
outputTemplate
})).join("") : "";
return `<div class="${CSS_CLASSES.PROMPT_VIEW}">
<div role="list" class="${CSS_CLASSES.CARD_LIST}">
${cardsHtml}
</div>
</div>`;
}
static _createSuggestionsSection(suggestions, promptSuggestionItemTemplate, messages) {
const suggestionItems = suggestions.map((suggestion) => promptSuggestionItemTemplate({ suggestion })).join("");
return `<div class="${CSS_CLASSES.PROMPT_EXPANDER}">
<button ${REFS.SUGGESTIONS_BUTTON} aria-expanded="true">${messages.promptSuggestions}</button>
<div class="k-prompt-expander-content">
<div class="${CSS_CLASSES.SUGGESTION_GROUP}" role="group">
${suggestionItems}
</div>
</div>
</div>`;
}
static _createCardHeader(output, messages, showOutputSubtitleTooltip) {
const tooltipAttr = showOutputSubtitleTooltip ? `title="${kendo.htmlEncode(output.prompt)}"` : "";
return `<div class="${CSS_CLASSES.CARD_HEADER}">
<div class="${CSS_CLASSES.CARD_TITLE}">${messages.outputTitle}</div>
<div class="${CSS_CLASSES.CARD_SUBTITLE}" ${tooltipAttr}>${kendo.htmlEncode(output.prompt)}</div>
</div>`;
}
static _createCardBody(contentHtml, isLoading) {
return `<div class="${CSS_CLASSES.CARD_BODY}" ${REFS.OUTPUT_BODY}>
${contentHtml}
</div>`;
}
static _generateContentHtml({ output, outputTemplate, encodedPromptOutputs }) {
if (outputTemplate && typeof outputTemplate === "function" && !output.isLoading && output.output) return outputTemplate({
output,
content: output.output
});
const content = output.output || "";
return `<p ref-output-content${output.isLoading ? " data-loading=\"true\"" : " data-loading=\"false\""}>${encodedPromptOutputs ? kendo.htmlEncode(content) : content}</p>`;
}
static _generateActionsHtml({ outputActions, showOutputRating, messages, isStreaming }) {
if (!outputActions) outputActions = showOutputRating ? [
"copy",
"retry",
"spacer",
"rating"
] : ["copy", "retry"];
return AIPromptTemplateBuilder._createCustomActions(outputActions, showOutputRating, messages, isStreaming);
}
static _createCustomActions(outputActions, showOutputRating, messages, isStreaming) {
const filteredActions = outputActions.filter((action) => action.command !== "stop");
const hasRatingButtons = filteredActions.some((action) => action.command === "ratePositive" || action.command === "rateNegative");
let actionsToRender = [...filteredActions];
if (showOutputRating && !hasRatingButtons) {
if (!actionsToRender.some((action) => action.type === "spacer")) actionsToRender.push({ type: "spacer" });
actionsToRender.push({
command: "ratePositive",
text: messages.ratePositive,
type: "button"
}, {
command: "rateNegative",
text: messages.rateNegative,
type: "button"
});
}
const actionsHtml = actionsToRender.map((action) => AIPromptTemplateBuilder._createActionButton(action, messages, isStreaming)).join("");
return `<div class="${CSS_CLASSES.ACTIONS} ${CSS_CLASSES.CARD_ACTIONS}">
${actionsHtml}
</div>`;
}
static _createActionButton(action, messages, isStreaming) {
if (action.type === "spacer") return `<span class="${CSS_CLASSES.SPACER}"></span>`;
const text = action.text || AIPromptTemplateBuilder._getActionText(action.command, messages);
const title = action.title || text;
return `<button data-action-command="${action.command}" title="${title}">${action.iconButton ? "" : text}</button>`;
}
static _getActionText(command, messages) {
return {
"copy": messages.copyOutput,
"retry": messages.retryGeneration,
"ratePositive": messages.ratePositive,
"rateNegative": messages.rateNegative
}[command] || command;
}
}
kendo.ui.AIPromptTemplateBuilder = AIPromptTemplateBuilder;
})(window.kendo.jQuery);
//#endregion
//#region ../src/aiprompt/speech-manager.js
(function($) {
class AIPromptSpeechManager {
constructor(view, options = {}) {
this.view = view;
this.aiprompt = view.aiprompt;
this.options = this._processSettings(options);
this._speechButton = null;
}
_processSettings(speechToTextConfig) {
const defaultOptions = {
integrationMode: "webSpeech",
lang: "en-US",
continuous: false,
interimResults: false,
maxAlternatives: 1
};
if (speechToTextConfig === false || speechToTextConfig === null) return {
enabled: false,
options: null
};
else if (speechToTextConfig === true) return {
enabled: true,
options: defaultOptions
};
else if (typeof speechToTextConfig === "object") return {
enabled: true,
options: $.extend({}, defaultOptions, speechToTextConfig)
};
return {
enabled: true,
options: defaultOptions
};
}
isEnabled() {
return this.options.enabled;
}
getTextAreaSuffixOptions() {
if (!this.isEnabled()) return {};
return { suffixOptions: {
template: function() {
return "<button ref-speech-to-text-button title=\"Speech to Text\"></button>";
},
separator: false
} };
}
initialize(textareaWidget) {
if (!this.isEnabled() || !textareaWidget) return false;
const speechButton = textareaWidget.wrapper.find("button[ref-speech-to-text-button]");
if (speechButton.length === 0) return false;
this._speechButton = speechButton.kendoSpeechToTextButton({
...this.options.options,
fillMode: "flat"
}).getKendoSpeechToTextButton();
this._speechButton.bind("result", (e) => this._handleResult(e, textareaWidget));
this.aiprompt.speechToTextButton = this._speechButton;
return true;
}
_handleResult(e, textareaWidget) {
if (e.isFinal || !this.options.options.interimResults) {
const transcript = e.alternatives[0]?.transcript || "";
const currentValue = textareaWidget.value();
let newValue = currentValue ? currentValue + " " + transcript : transcript;
const maxLength = textareaWidget.options.maxlength;
if (maxLength && newValue.length > maxLength) newValue = newValue.substring(0, maxLength);
textareaWidget.value(newValue);
}
}
startRecognition() {
if (this._speechButton) this._speechButton.startRecognition();
}
stopRecognition() {
if (this._speechButton) this._speechButton.stopRecognition();
}
abortRecognition() {
if (this._speechButton) this._speechButton.abortRecognition();
}
isListening() {
return this._speechButton ? this._speechButton.isListening() : false;
}
destroy() {
if (this._speechButton) {
this._speechButton.destroy();
this._speechButton = null;
}
}
}
kendo.ui.AIPromptSpeechManager = AIPromptSpeechManager;
})(window.kendo.jQuery);
//#endregion
//#region ../src/aiprompt/output-manager.js
(function($) {
class AIPromptOutputObject {
constructor(outputData, outputManager) {
this.id = outputData.id;
this.data = outputData;
this._element = null;
this._bodyElement = null;
this._aiprompt = outputManager.aiprompt;
this._isLoading = outputData.isLoading || false;
}
get isLoading() {
return this._isLoading;
}
set isLoading(value) {
const wasLoading = this._isLoading;
this._isLoading = value;
this.data.isLoading = value;
if (value === true) this.showSkeleton();
else if (value === false) {
this.hideSkeleton();
if (wasLoading || this.data.output) this.applyFinalTemplate();
}
}
getElement() {
return this._element;
}
setElement(element) {
this._element = element;
return this;
}
updateContent(newContent) {
if (!this._element || this._element.length === 0) return this;
this.data.content = newContent;
this.data.output = newContent;
const bodyElement = this._element.find(".k-card-body");
const contentElement = bodyElement.find("[ref-output-content]");
if (newContent && newContent.trim() && contentElement.length > 0) {
bodyElement.find(".k-skeleton").remove();
contentElement.attr("data-loading", "false").show();
const encodedPromptOutputs = this._aiprompt.options.encodedPromptOutputs;
contentElement.html(encodedPromptOutputs ? kendo.htmlEncode(newContent) : newContent);
}
return this;
}
showSkeleton() {
this.showHeaderSkeleton();
this.showBodySkeleton();
this.showActionSkeleton();
return this;
}
hideSkeleton() {
this.hideHeaderSkeleton();
this.hideBodySkeleton();
this.hideActionSkeleton();
return this;
}
applyFinalTemplate() {
if (!this._element || this._element.length === 0) return this;
const bodyElement = this._element.find(".k-card-body");
const contentElement = bodyElement.find("[ref-output-content]");
let outputTemplate = this._aiprompt?.options?.outputTemplate;
if (!outputTemplate) return this;
else if (typeof outputTemplate === "string") outputTemplate = kendo.template(outputTemplate);
if (outputTemplate && typeof outputTemplate === "function" && this.data.output) {
const customContent = outputTemplate({
output: this.data,
content: this.data.output
});
bodyElement.html(customContent);
} else if (contentElement.length > 0) contentElement.attr("data-loading", "false").show();
return this;
}
showHeaderSkeleton() {
if (!this._element || this._element.length === 0) return this;
const headerElement = this._element.find(".k-card-header");
if (headerElement.length === 0) return this;
headerElement.children().hide();
if (headerElement.find(".k-skeleton").length === 0) {
const skeleton = $(`<span class="k-skeleton k-skeleton-text k-skeleton-pulse"></span>`);
skeleton.css("width", "60%").css("height", "24px");
headerElement.prepend(skeleton);
}
return this;
}
hideHeaderSkeleton() {
if (!this._element || this._element.length === 0) return this;
const headerElement = this._element.find(".k-card-header");
if (headerElement.length === 0) return this;
headerElement.find(".k-skeleton").remove();
headerElement.children().removeClass("k-hidden").show();
return this;
}
showBodySkeleton() {
if (!this._element || this._element.length === 0) return this;
const bodyElement = this._element.find(".k-card-body");
bodyElement.find("[ref-output-content]").attr("data-loading", "true").hide();
if (bodyElement.find(".k-skeleton").length === 0) {
const skeleton = $(`<span class="k-skeleton k-skeleton-rect k-skeleton-pulse"></span>`);
skeleton.css("height", "80px");
bodyElement.prepend(skeleton);
}
return this;
}
hideBodySkeleton() {
if (!this._element || this._element.length === 0) return this;
this._element.find(".k-card-body").find(".k-skeleton").remove();
this.applyFinalTemplate();
return this;
}
showActionSkeleton() {
if (!this._element || this._element.length === 0) return this;
const actionsElement = this._element.find(".k-card-actions");
if (actionsElement.length > 0) {
actionsElement.children().hide();
if (actionsElement.find(".k-skeleton").length === 0) {
const skeleton = $(`<span class="k-skeleton k-skeleton-text k-skeleton-pulse"></span>`);
skeleton.css("width", "100%").css("height", "32px");
actionsElement.prepend(skeleton);
}
}
return this;
}
hideActionSkeleton() {
if (!this._element || this._element.length === 0) return this;
const actionsElement = this._element.find(".k-card-actions");
if (actionsElement.length > 0) {
actionsElement.find(".k-skeleton").remove();
actionsElement.children().removeClass("k-hidden").show();
}
return this;
}
toggleActionButtons(isStreaming, outputActions) {
if (!this._element || this._element.length === 0) return this;
if (outputActions) {
const allActions = this._element.find("[data-action-command]");
if (isStreaming) allActions.addClass("k-hidden");
else allActions.removeClass("k-hidden");
} else {
const actionButtons = this._element.find("[ref-copy-button], [ref-retry-button]");
if (isStreaming) actionButtons.addClass("k-hidden");
else actionButtons.removeClass("k-hidden");
}
return this;
}
destroy() {
this._element = null;
this._bodyElement = null;
this._aiprompt = null;
this.data = null;
this.id = null;
this._isLoading = false;
}
}
class AIPromptOutputManager {
constructor(aiprompt) {
this.aiprompt = aiprompt;
}
createOutputObject(outputData) {
return new AIPromptOutputObject(outputData, this);
}
getLastOutputObject() {
if (this.aiprompt.promptOutputs.length > 0) {
const lastOutput = this.aiprompt.promptOutputs[0];
return this.aiprompt.outputObjects.get(lastOutput.id);
}
return null;
}
updatePromptOutputContent(content, outputId) {
let outputObj;
if (outputId) outputObj = this.aiprompt.outputObjects.get(outputId);
else outputObj = this.getLastOutputObject();
if (outputObj) {
outputObj.updateContent(content);
return outputObj;
} else return null;
}
stopLoading(objectId) {
let outputObj = this.aiprompt.outputObjects.get(objectId);
if (outputObj) outputObj.isLoading = false;
else {
outputObj = this.getLastOutputObject();
if (outputObj) outputObj.isLoading = false;
}
}
stopAllLoading() {
this.aiprompt.outputObjects.forEach((outputObj) => {
outputObj.isLoading = false;
});
}
getOutputFromElement(element) {
let id = $(element).closest(".k-card").data("id");
let promptOutput = this.aiprompt.promptOutputs.find((output) => output.id == id);
if (!promptOutput && this.aiprompt.outputObjects) promptOutput = this.aiprompt.outputObjects.get(id);
return promptOutput;
}
extractOutputData(promptOutput) {
if (!promptOutput) return {
prompt: null,
output: null
};
if (promptOutput.data) return {
prompt: promptOutput.data.prompt,
output: promptOutput.data.output
};
return {
prompt: promptOutput.prompt,
output: promptOutput.output
};
}
destroy() {
if (this.aiprompt && this.aiprompt.outputObjects) {
this.aiprompt.outputObjects.forEach((outputObj) => {
if (outputObj) {
outputObj._element = null;
outputObj._bodyElement = null;
outputObj._aiprompt = null;
outputObj.data = null;
}
});
this.aiprompt.outputObjects.clear();
}
this.aiprompt = null;
}
}
kendo.ui.AIPromptOutputObject = AIPromptOutputObject;
kendo.ui.AIPromptOutputManager = AIPromptOutputManager;
})(window.kendo.jQuery);
//#endregion
//#region ../src/aiprompt/views.js
(function($) {
let Widget = kendo.ui.Widget;
const messageTypes = {
"ai": "assistant",
"system": "system",
"user": "user",
"tool": "tool"
};
const KDISABLED = "k-disabled";
const CSS_CLASSES = {
PROMPT_VIEW: "k-prompt-view",
PROMPT_EXPANDER: "k-prompt-expander",
SUGGESTION_GROUP: "k-suggestion-group",
SUGGESTION: "k-suggestion",
CARD: "k-card",
CARD_LIST: "k-card-list"
};
const REFERENCE_ATTRIBUTES = {
PROMPT_SUGGESTIONS_BUTTON: "ref-prompt-suggestions-button",
PROMPT_INPUT: "ref-prompt-input",
GENERATE_OUTPUT_BUTTON: "ref-generate-output-button",
OUTPUT_CONTENT: "ref-output-content",
STOP_GENERATION_BUTTON: "ref-stop-generation-button"
};
let AIPromptBaseView = kendo.ui.AIPromptBaseView = Widget.extend({
init: function(element, options) {
let that = this;
Widget.fn.init.call(that, element, options);
that.aiprompt = element.getKendoAIPrompt();
that.contentElement = that.options.contentElement;
that.footerElement = that.options.footerElement;
that.buttonText = that.options.buttonText;
that.buttonIcon = that.options.buttonIcon;
that.service = that.options.service;
Widget.fn.endInit.call(that);
},
options: {
name: "AIPromptBaseView",
buttonText: "",
buttonIcon: ""
},
render: function() {
let that = this;
that._renderContent();
that._renderFooter();
},
_renderContentElement: function() {
let that = this;
let content = $("<div></div>").addClass("k-prompt-content");
that.contentElement = content;
that.element.append(content);
return that.contentElement;
},
_renderFooterElement: function() {
let that = this;
let footer = $("<div></div>").addClass("k-prompt-footer");
that.footerElement = footer;
that.element.append(footer);
return that.footerElement;
},
_ajaxRequest: function(prompt, isRetry, history) {
let that = this;
let service = that.service;
let data = that._getAjaxData(prompt, isRetry, history);
const requestOptions = {
url: typeof service === "string" ? service : service.url,
type: "POST",
contentType: "application/json",
data: JSON.stringify(data),
success: (response) => that._ajaxSuccessHandler(response, isRetry, prompt)
};
if (service.headers) requestOptions.headers = service.headers;
kendo.ui.progress(that.contentElement, true);
return $.ajax(requestOptions);
},
_ajaxSuccessHandler: function(response, isRetry, prompt) {
const that = this;
const outputGetter = that.service?.outputGetter || that._getResponseMessageText;
const output = {
id: kendo.guid(),
output: outputGetter(response),
prompt,
isRetry,
activeView: 1
};
that.aiprompt.trigger("promptResponse", {
output: output.output,
prompt: output.prompt,
outputId: output.id,
isRetry: output.isRetry,
response: output.response
});
that.aiprompt.addPromptOutput(output);
that.aiprompt.activeView(output.activeView);
if (!isRetry) (that.footerElement?.find(`button[${REFERENCE_ATTRIBUTES.GENERATE_OUTPUT_BUTTON}]`))?.removeClass(KDISABLED);
kendo.ui.progress(that.contentElement, false);
},
_getResponseMessageText: function(response) {
return response?.Message?.Text || "An error occurred while processing the request.";
},
_getAjaxData: function(prompt, isRetry, history) {
const service = this.service;
let defaultData = [{
role: { value: messageTypes.user },
text: prompt
}];
if (history?.length) defaultData = history.concat(defaultData);
if (typeof service === "string") return defaultData;
if (kendo.isPresent(service.data) && Object.keys(service.data).length) {
service.data.messages = defaultData;
return service.data;
}
if (kendo.isFunction(service.data)) return service.data(prompt, isRetry, history);
if ($.isPlainObject(service) && kendo.isPresent(service.url)) return defaultData;
throw new Error("Invalid AIPrompt service configuration.");
},
destroy: function() {
let that = this;
Widget.fn.destroy.call(that);
if (that.contentElement) {
that.contentElement.off();
kendo.destroy(that.contentElement);
that.contentElement.remove();
}
if (that.footerElement) {
that.footerElement.off();
kendo.destroy(that.footerElement);
that.footerElement.remove();
}
that.aiprompt.speechToTextButton = null;
}
});
kendo.ui.AIPromptPromptView = AIPromptBaseView.extend({
init: function(element, options) {
let that = this;
AIPromptBaseView.fn.init.call(that, element, options);
that.promptSuggestions = that.options.promptSuggestions;
that.promptSuggestionItemTemplate = that.options.promptSuggestionItemTemplate ? kendo.template(that.options.promptSuggestionItemTemplate) : kendo.ui.AIPromptTemplateBuilder.createSuggestionItem;
that.speechManager = new kendo.ui.AIPromptSpeechManager(that, that.options.speechToText);
Widget.fn.endInit.call(this);
},
options: {
name: "AIPromptPromptView",
buttonIcon: "sparkles"
},
_renderContent: function() {
let that = this;
let suggestions = that.promptSuggestions;
let promptSuggestionItemTemplate = that.promptSuggestionItemTemplate;
let content;
if (that.options.viewTemplate) content = kendo.template(that.options.viewTemplate)({
suggestions,
promptSuggestionItemTemplate,
messages: that.options.messages
});
else content = kendo.ui.AIPromptTemplateBuilder.createPromptView({
suggestions,
promptSuggestionItemTemplate,
messages: that.options.messages
});
that._renderContentElement();
that.contentElement.append(content);
},
_renderFooter: function() {
let that = this;
let footer;
if (that.options.footerTemplate) footer = kendo.template(that.options.footerTemplate)({ messages: that.options.messages });
else footer = kendo.ui.AIPromptTemplateBuilder.createPromptFooter({ messages: that.options.messages });
that._renderFooterElement();
that.footerElement.append(footer);
},
setTextAreaValue: function(value) {
let that = this;
const textareaWidget = that.contentElement.find(`textarea[${REFERENCE_ATTRIBUTES.PROMPT_INPUT}]`).getKendoTextArea();
if (textareaWidget) textareaWidget.value(value);
else that.contentElement.find(`textarea[${REFERENCE_ATTRIBUTES.PROMPT_INPUT}]`).val(value);
},
_focusSuggestion(element) {
let that = this;
if (!element || !element.length) return;
that.contentElement.find(`.${CSS_CLASSES.SUGGESTION_GROUP} .${CSS_CLASSES.SUGGESTION}[tabindex=0]`).attr("tabindex", "-1");
element.attr("tabindex", "0").trigger("focus");
},
startSpeechRecognition: function() {
this.speechManager.startRecognition();
},
stopSpeechRecognition: function() {
this.speechManager.stopRecognition();
},
abortSpeechRecognition: function() {
this.speechManager.abortRecognition();
},
isSpeechListening: function() {
return this.speechManager.isListening();
},
initializeComponents: function() {
let that = this;
let suggestions = that.promptSuggestions;
const generateButton = that.footerElement.find(`button[${REFERENCE_ATTRIBUTES.GENERATE_OUTPUT_BUTTON}]`);
let textAreaOptions = $.extend({
resize: "vertical",
placeholder: that.options.messages.promptPlaceholder
}, that.options.promptTextArea || {});
if (that.speechManager.isEnabled()) textAreaOptions = $.extend(true, textAreaOptions, that.speechManager.getTextAreaSuffixOptions());
const textareaWidget = that.contentElement.find(`textarea[${REFERENCE_ATTRIBUTES.PROMPT_INPUT}]`).kendoTextArea(textAreaOptions).getKendoTextArea();
if (textareaWidget && textareaWidget.element) textareaWidget.element.attr("aria-label", that.options.messages.promptPlaceholder);
if (that.speechManager.isEnabled()) that.speechManager.initialize(textareaWidget);
generateButton.kendoButton({
icon: "sparkles",
themeColor: "primary",
rounded: "full",
click: function(e) {
const textareaWidget = that.contentElement.find(`textarea[${REFERENCE_ATTRIBUTES.PROMPT_INPUT}]`).getKendoTextArea();
const eventArgs = {
prompt: textareaWidget ? textareaWidget.value() : that.contentElement.find(`textarea[${REFERENCE_ATTRIBUTES.PROMPT_INPUT}]`).val(),
isRetry: false,
history: []
};
if (that.service) eventArgs.service = that.service;
if (that.aiprompt.trigger("promptRequest", eventArgs)) return;
if (that.service) that.aiprompt.transport.read({
prompt: eventArgs.prompt,
history: eventArgs.history,
isRetry: false,
service: that.service
});
}
});
if (suggestions?.length) {
that.contentElement.find(`.${CSS_CLASSES.SUGGESTION_GROUP} .${CSS_CLASSES.SUGGESTION}`).first().attr("tabindex", "0");
let nextExpanderContentId = kendo.guid();
let expanderButton = that.contentElement.find(`.${CSS_CLASSES.PROMPT_EXPANDER} button[${REFERENCE_ATTRIBUTES.PROMPT_SUGGESTIONS_BUTTON}]`);
that.contentElement.find(`.${CSS_CLASSES.PROMPT_EXPANDER} button[${REFERENCE_ATTRIBUTES.PROMPT_SUGGESTIONS_BUTTON}]`).attr("aria-controls", nextExpanderContentId);
expanderButton.next(`.${CSS_CLASSES.PROMPT_EXPANDER_CONTENT}`).attr("id", nextExpanderContentId);
that.contentElement.find(`.${CSS_CLASSES.PROMPT_EXPANDER} button[${REFERENCE_ATTRIBUTES.PROMPT_SUGGESTIONS_BUTTON}]`).kendoButton({
icon: "chevron-up",
fillMode: "flat",
click: function(e) {
let content = $(e.target).closest(".k-prompt-expander").find(".k-prompt-expander-content");
let iconEl = e.sender.element.find(".k-icon");
kendo.ui.icon(iconEl, content.is(":visible") ? "chevron-down" : "chevron-up");
content.toggle();
e.sender.element.attr("aria-expanded", content.is(":visible"));
}
});
that.contentElement.on("click", ".k-suggestion-group .k-suggestion", function(e) {
that.setTextAreaValue($(e.target).text());
});
that.contentElement.on("keydown", ".k-suggestion-group .k-suggestion", function(e) {
if (e.keyCode === 40 || e.keyCode === 38 || e.keyCode === 36 || e.keyCode === 35 || e.keyCode === 13 || e.keyCode === 32) {
e.preventDefault();
let target = $(e.target);
let siblings = target.siblings();
let next, prev;
if (e.keyCode === 40) {
next = target.next();
that._focusSuggestion(next);
}
if (e.keyCode === 38) {
prev = target.prev();
that._focusSuggestion(prev);
}
if (e.keyCode === 36) {
prev = siblings.first();
that._focusSuggestion(prev);
}
if (e.keyCode === 35) {
next = siblings.last();
that._focusSuggestion(next);
}
if (e.keyCode === 13 || e.keyCode === 32) that.setTextAreaValue($(e.target).text());
}
});
}
if (kendo.isFunction(that.options.initializeComponents)) that.options.initializeComponents({ view: that });
},
render: function() {
let that = this;
that._renderContent();
that._renderFooter();
that.initializeComponents();
},
destroy: function() {
let that = this;
if (that.speechManager) {
that.speechManager.destroy();
that.speechManager = null;
}
AIPromptBaseView.fn.destroy.call(that);
}
});
kendo.ui.AIPromptOutputView = AIPromptBaseView.extend({
init: function(element, options) {
let that = this;
AIPromptBaseView.fn.init.call(that, element, options);
that.promptOutputs = that.aiprompt && that.aiprompt.promptOutputs ? that.aiprompt.promptOutputs : [];
that.showOutputRating = that.options.showOutputRating;
that.isStreaming = that.options.isStreaming || false;
that.outputActions = that.options.outputActions;
that.outputTemplate = that.options.outputTemplate;
that.outputActionManager = that.options.outputActionManager;
Widget.fn.endInit.call(this);
},
options: {
name: "AIPromptOutputView",
buttonIcon: "comment",
isStreaming: false,
promptOutputs: []
},
startStreaming: function() {
let that = this;
that.isStreaming = true;
that._showStopButton();
},
stopStreaming: function() {
let that = this;
that.isStreaming = false;
that._hideStopButton();
},
_showStopButton: function() {
let that = this;
if (!that.stopGenerationButton) {
if (that._initStopGenerationButton()) that.stopGenerationButton.show();
} else that.stopGenerationButton.show();
},
_hideStopButton: function() {
let that = this;
if (that.stopGenerationButton) that.stopGenerationButton.hide();
},
renderPromptOutput: function(output) {
let that = this;
let showOutputRating = that.options.showOutputRating;
let encodedPromptOutputs = that.options.encodedPromptOutputs;
let messages = that.options.messages;
let isStreaming = that.isStreaming || false;
let outputActions = that.outputActions;
if (!that.cardListContainer || that.cardListContainer.length === 0) {
if (that.outputsContainer) that.cardListContainer = that.outputsContainer.find(".k-card-list");
if (!that.cardListContainer || that.cardListContainer.length === 0) return;
}
if (isStreaming && !that.stopGenerationButton) that._initStopGenerationButton();
const outputObj = that.aiprompt.outputObjects.get(output.id);
if (outputObj) {
const card = $(kendo.ui.AIPromptTemplateBuilder.createOutputCard({
output,
showOutputRating,
messages,
showOutputSubtitleTooltip: true,
encodedPromptOutputs,
isStreaming,
outputActions,
outputTemplate: that.outputTemplate
}));
outputObj._element = card;
outputObj._bodyElement = card.find(`.k-card-body`);
that.cardListContainer.prepend(card);
if (output.isLoading) outputObj.showSkeleton();
else if (output.output) outputObj.applyFinalTemplate();
that.initializeComponents(card);
} else {
let card = $(kendo.ui.AIPromptTemplateBuilder.createOutputCard({
output,
showOutputRating,
messages,
showOutputSubtitleTooltip: true,
encodedPromptOutputs,
isStreaming,
outputActions,
outputTemplate: that.outputTemplate
}));
that.cardListContainer.prepend(card);
that.initializeComponents(card);
}
},
updatePromptOutputContent: function(outputId, content) {
const outputObj = this.aiprompt.outputObjects.get(outputId);
if (outputObj) outputObj.updateContent(content);
},
_initStopGenerationButton: function() {
let that = this;
let contentElement = that.contentElement;
if (!contentElement || contentElement.length === 0) return false;
if (that.stopGenerationButton) return true;
let stopFab = $("<button class='k-prompt-stop-fab k-generating'></button>");
stopFab.attr({
"aria-label": that.options.messages.stopGeneration,
"title": that.options.messages.stopGeneration
});
contentElement.prepend(stopFab);
that.stopGenerationButton = stopFab.kendoFloatingActionButton({
_classNames: ["k-prompt-stop-fab", "k-generating"],
icon: "stop",
positionMode: "absolute",
align: "bottom end",
rounded: "full",
click: function(e) {
that.stopStreaming();
that.aiprompt.trigger("promptRequestCancel", {});
}
}).getKendoFloatingActionButton();
that.stopGenerationButton.hide();
return true;
},
_renderContent: function() {
let that = this;
let promptOutputs = that.promptOutputs;
let showOutputRating = that.options.showOutputRating;
let showOutputSubtitleTooltip = that.options.showOutputSubtitleTooltip;
let messages = that.options.messages;
let encodedPromptOutputs = that.options.encodedPromptOutputs;
let outputActions = that.outputActions;
let outputsContainer;
if (that.viewTemplate) outputsContainer = kendo.template(that.viewTemplate)({
promptOutputs,
showOutputRating,
messages,
showOutputSubtitleTooltip,
encodedPromptOutputs,
outputActions,
outputTemplate: that.outputTemplate
});
else outputsContainer = kendo.ui.AIPromptTemplateBuilder.createOutputView({
promptOutputs,
showOutputRating,
messages,
showOutputSubtitleTooltip,
encodedPromptOutputs,
outputActions,
outputTemplate: that.outputTemplate
});
that.outputsContainer = $(outputsContainer);
that.cardListContainer = that.outputsContainer.find(".k-card-list");
that._renderContentElement();
that.contentElement.append(that.outputsContainer);
that._initStopGenerationButton();
},
initializeComponents: function(parentElement) {
let that = this;
parentElement = parentElement || that.contentElement;
that.outputActionManager.initializeButtons(parentElement, that.outputActions);
parentElement.find("[data-loading=\"true\"]").hide();
parentElement.find("[data-loading=\"false\"]").show();
if (that.aiprompt && that.aiprompt.outputObjects) that.aiprompt.outputObjects.forEach((outputObj, outputId) => {
const cardElement = parentElement.find(`.k-card[data-id="${outputId}"]`);
if (cardElement.length > 0) {
outputObj._element = cardElement;
outputObj._bodyElement = cardElement.find(".k-card-body");
if (that.outputTemplate && typeof that.outputTemplate === "function" && outputObj.data && outputObj.data.output && !outputObj.data.isLoading) {
const customContent = that.outputTemplate({
output: outputObj.data,
content: outputObj.data.output
});
outputObj._bodyElement.html(customContent);
}
const buttons = cardElement.find(".k-button");
if (!(buttons.length > 0 && buttons.first().data("kendoButton")) && buttons.length > 0) that.outputActionManager.initializeButtons(cardElement, that.outputActions);
}
});
},
_initializeCardButtons: function(cardElement) {
let that = this;
that.outputActionManager.initializeButtons(cardElement, that.outputActions);
},
render: function() {
let that = this;
that._renderContent();
that.initializeComponents();
that.contentElement.on("keydown", ".k-card", function(e) {
let target = $(e.target);
if (e.keyCode === 40 || e.keyCode === 38 || e.keyCode === 36 || e.keyCode === 35) {
e.preventDefault();
if (e.keyCode === 40) target.next(".k-card").trigger("focus");
if (e.keyCode === 38) target.prev(".k-card").trigger("focus");
if (e.keyCode === 36) that.contentElement.find(".k-card").first().trigger("focus");
if (e.keyCode === 35) that.contentElement.find(".k-card").last().trigger("focus");
}
});
},
destroy: function() {
let that = this;
AIPromptBaseView.fn.destroy.call(that);
}
});
kendo.ui.AIPromptCommandsView = AIPromptBaseView.extend({
options: {
name: "AIPromptCommandsView",
buttonText: "",
buttonIcon: "more-horizontal",
promptCommands: []
},
initializeComponents: function() {
let that = this;
let commandItems = that.options.promptCommands;
let panelBarEl = $("<div></div>").kendoPanelBar({
animation: false,
dataSource: commandItems,
selectable: false,
select: function(ev) {
let item = $(ev.item);
let dataItem = this.dataItem(item);
if (dataItem.hasChildren) return;
that.aiprompt.trigger("commandExecute", {
sender: that.aiprompt,
item: dataItem
});
}
});
const promptViewWrapper = $("<div class='k-prompt-view'>");
promptViewWrapper.append(panelBarEl);
that.contentElement.append(promptViewWrapper);
},
render: function() {
let that = this;
that._renderContentElement();
that.initializeComponents();
}
});
let EMPTY_TEMPLATE = () => "";
kendo.ui.AIPromptCustomView = AIPromptBaseView.extend({
options: {
name: "AIPromptCustomView",
buttonText: "",
buttonIcon: "",
viewTemplate: EMPTY_TEMPLATE,
footerTemplate: EMPTY_TEMPLATE
},
initializeComponents: function() {
let that = this;
if (typeof that.options.initializeComponents === "function") that.options.initializeComponents.call(that);
},
_renderContent: function() {
let that = this;
let content = kendo.template(that.options.viewTemplate)({ aiprompt: that });
that._renderContentElement();
that.contentElement.append(content);
},
_renderFooter: function() {
let that = this;
if (that.options.footerTemplate === EMPTY_TEMPLATE) return;
let footer = kendo.template(that.options.footerTemplate)({ messages: that.options.messages });
that._renderFooterElement();
that.footerElement.append(footer);
},
render: function() {
let that = this;
that._renderContent();
that._renderFooter();
that.initializeComponents();
}
});
})(window.kendo.jQuery);
kendo;
//#endregion
//#region ../src/kendo.aiprompt.js
const __meta__ = {
id: "aiprompt",
name: "AIPrompt",
category: "web",
description: "The AIPrompt component simplifies the incorporation of external AI services into apps.",
depends: [
"core",
"icons",
"textarea",
"button",
"toolbar",
"panelbar",
"data",
"floatingactionbutton",
"skeletoncontainer",
"speechtotextbutton"
]
};
(function($) {
let kendo = window.kendo, Widget = kendo.ui.Widget, NS = ".kendoAIPrompt", ui = kendo.ui, extend = $.extend, COMMAND_EXECUTE = "commandExecute", PROMPT_REQUEST = "promptRequest", PROMPT_RESPONSE = "promptResponse", OUTPUT_RATING = "outputRating", OUTPUT_COPY = "outputCopy", OUTPUT_VIEW = "output", OUTPUT_ACTION = "outputAction", PROMPT_REQUEST_CANCEL = "promptRequestCancel", DEFAULT_OUTPUT_ACTIONS = [
"copy",
"retry",
"spacer",
"rating"
], DEFAULT_OUTPUT_ACTIONS_WITHOUT_RATING = ["copy", "retry"], FOCUS = "focus", KENDO_KEYDOWN = "kendoKeydown";
let cssClasses = {
menuButton: "k-menu-button",
aIPrompt: "k-prompt"
};
let defaultViews = {
prompt: {
type: "kendo.ui.AIPromptPromptView",
name: "prompt",
buttonIcon: "sparkles"
},
output: {
type: "kendo.ui.AIPromptOutputView",
name: "output",
buttonIcon: "comment"
},
commands: {
type: "kendo.ui.AIPromptCommandsView",
name: "commands",
buttonIcon: "more-horizontal"
},
custom: {
type: "kendo.ui.AIPromptCustomView",
name: "custom"
}
};
let AIPrompt = Widget.extend({
init: function(element, options) {
let that = this;
options = options || {};
Widget.fn.init.call(that, element, options);
if (that.options.views.length == 0) {
that.options.views = ["prompt", "output"];
if (this.options.promptCommands && this.options.promptCommands.length) this.options.views.push("commands");
}
that.options.outputActions = options.outputActions && options.outputActions.length > 0 ? options.outputActions : DEFAULT_OUTPUT_ACTIONS_WITHOUT_RATING;
that.promptOutputs = that.options.promptOutputs || [];
that.outputObjects = /* @__PURE__ */ new Map();
that.outputManager = new kendo.ui.AIPromptOutputManager(that);
that.outputActions = kendo.ui.AIPromptOutputActionManager.processOutputActions(that.options.outputActions);
that.outputActionManager = new kendo.ui.AIPromptOutputActionManager(that, { outputActions: that.outputActions });
if (Array.isArray(that.promptOutputs) && that.promptOutputs.length > 0) that.promptOutputs.forEach((output) => {
if (!output.id) output.id = kendo.guid();
const outputObj = that.outputManager.createOutputObject(output);
that.outputObjects.set(output.id, outputObj);
});
that._initLayout();
that._initViews();
that._initToolbar();
that.activeView(that.options.activeView);
if (that.options.service) that.transport = new kendo.data.AiTransport({
service: that.options.service,
success: that._serviceSuccess.bind(that),
requestStart: () => kendo.ui.progress(that.element, true)
});
kendo.notify(that);
Widget.fn.endInit.call(this);
},
options: {
name: "AIPrompt",
enabled: true,
toolbarItems: [],
promptOutputs: [],
encodedPromptOutputs: true,
activeView: 0,
views: [],
popup: null,
speechToText: false,
promptTextArea: null,
messages: {
promptView: "Ask AI",
outputView: "Output",
commandsView: "",
customView: "Custom View",
promptPlaceholder: "Ask or generate content with AI",
promptSuggestions: "Prompt Suggestions",
generateOutput: "Generate",
outputTitle: "Generated with AI",
outputRetryTitle: "Generated with AI",
copyOutput: "Copy",
retryGeneration: "Retry",
ratePositive: "",
rateNegative: "",
stopGeneration: "Stop Generation"
},
showOutputRating: true,
service: null,
suffixTemplate: null,
outputTemplate: null,
outputActions: DEFAULT_OUTPUT_ACTIONS
},
events: [
COMMAND_EXECUTE,
PROMPT_REQUEST,
PROMPT_RESPONSE,
PROMPT_REQUEST_CANCEL,
OUTPUT_RATING,
OUTPUT_COPY,
OUTPUT_ACTION,
KENDO_KEYDOWN
],
_serviceSuccess: function(output) {
const that = this;
output.activeView = that.viewsArray.findIndex((v) => v.name === OUTPUT_VIEW);
if (!that.trigger(PROMPT_RESPONSE, {
output: output.output,
prompt: output.prompt,
outputId: output.id,
isRetry: output.isRetry || false,
response: output.response
})) {
that.addPromptOutput(output);
that.activeView(output.activeView);
kendo.ui.progress(that.element, false);
}
},
_initializeView: function(name) {
let viewConfig = this.views[name];
let view;
if (viewConfig) {
let type = viewConfig.type;
if (typeof type === "string") type = kendo.getter(viewConfig.type)(window);
if (type) view = new type(this.element, extend(true, {
promptSuggestions: this.options.promptSuggestions,
promptCommands: this.options.promptCommands,
promptOutputs: this.promptOutputs,
showOutputRating: this.showOutputRating,
messages: this.options.messages,
showOutputSubtitleTooltip: this.options.showOutputSubtitleTooltip,
encodedPromptOutputs: this.options.encodedPromptOutputs,
promptSuggestionItemTemplate: this.options.promptSuggestionItemTemplate,
service: this.options.service,
speechToText: this.options.speechToText,
promptTextArea: this.options.promptTextArea,
outputActions: this.outputActions,
outputActionManager: this.outputActionManager,
outputTemplate: this.options.outputTemplate
}, viewConfig));
else throw new Error("There is no such view");
}
return view;
},
_unbindView: function(view) {
if (view) view.destroy();
},
_initViews: function() {
let that = this, views = that.options.views;
that.views = {};
that.viewsArray = [];
for (let i = 0, l = views.length; i < l; i++) {
let view = views[i];
let isSettings = typeof view === "object";
let name = view;
if (isSettings) {
view = { ...view };
name = typeof view.type !== "string" ? view.name : view.type;
}
let defaultView = defaultViews[name];
if (defaultView) {
if (isSettings) view.type = defaultView.type;
defaultView.buttonText = that.options.messages[`${name}View`];
}
view = Object.assign({
title: view.title,
name,
index: i
}, defaultView, isSettings ? view : {});
that.viewsArray.push(view);
if (name) that.views[name] = view;
}
},
getViews: function() {
return this.viewsArray;
},
activeView: function(name) {
let that = this;
if (name === void 0) return that._activeViewIndex;
if (Number.isInteger(name)) name = that.viewsArray[name].name;
if (name && that.views[name]) {
if (that._selectedView) that._unbindView(that._selectedView);
that._selectedView = that._initializeView(name);
that._activeViewIndex = that.viewsArray.findIndex((v) => v.name === name);
that._selectedView.render();
that._updateToolbarState(that._activeViewIndex);
let toolItem = $(that.toolbar._getAllItems()[that._activeViewIndex]);
that.toolbar._resetTabIndex(toolItem);
toolItem.trigger(FOCUS);
}
},
addPromptOutput: function(output) {
if (typeof output === "string") output = { output };
output.id = output.id || kendo.guid();
const outputObj = this.outputManager.createOutputObject(output);
this.promptOutputs.unshift(output);
this.outputObjects.set(output.id, outputObj);
if (this._selectedView && typeof this._selectedView.renderPromptOutput === "function") {
this._selectedView.renderPromptOutput(output);
if (output.isLoading) this.startStreaming();
}
},
removePromptOutput: function(output) {
const that = this;
let outputId = output;
const removeOutput = (id) => {
if (that.promptOutputs.find((el) => el.id === id)) that.promptOutputs = that.promptOutputs.filter((item) => item.id !== id);
that.outputObjects.delete(id);
};
if (outputId instanceof jQuery) {
outputId = output.data("id");
output.remove();
removeOutput(outputId);
} else {
that.element.find("[data-id='" + outputId + "']").remove();
removeOutput(outputId);
}
},
clearOutput: function() {
const that = this;
const elements = that.element.find("[data-id]");
elements.each(function() {
const id = $(this).data("id");
that.outputObjects.delete(id);
});
elements.remove();
that.promptOutputs = [];
},
_updateToolbarState: function(activeToolIndex) {
let toolbar = this.toolbar;
toolbar.element.find(".k-toolbar-toggle-button").each(function(index, elm) {
toolbar.toggle($(elm), index == activeToolIndex);
});
},
_initLayout: function() {
let that = this, header = $("<div></div>").addClass("k-prompt-header");
that.header = header;
that.element.addClass(cssClasses.aIPrompt);
that.element.append(header);
const popupWrapper = that.element.closest(".k-popup");
if (popupWrapper.length) $(popupWrapper).addClass("k-prompt-popup");
},
_getViewTools: function() {
let that = this;
return that.viewsArray.map((v) => {
if (v.name === "commands") if (v.buttonText) v.title = v.buttonText;
else v.title = "More actions";
return {
type: "button",
text: v.buttonText,
icon: v.buttonIcon,
fillMode: "flat",
themeColor: v.themeColor || "primary",
rounded: "full",
togglable: true,
attributes: {
title: v.title,
"aria-label": v.title
},
toggle: function() {
that.activeView(v.name);
}
};
});
},
_initToolbar: function() {
let that = this;
let items = that.options.toolbarItems;
items = Array.isArray(items) ? items : [items];
const closeButton = items.find((item) => item.icon === "x");
if (closeButton) closeButton.themeColor = "base";
that.toolbar = $("<div></div>").kendoToolBar({
resizable: false,
fillMode: "flat",
items: that._getViewTools().concat(items)
}).appendTo(that.header).data("kendoToolBar");
},
focus: function() {
this.element.trigger(FOCUS);
},
updatePromptOutputContent: function(content, outputId) {
return this.outputManager.updatePromptOutputContent(content, outputId);
},
startStreaming: function() {
let that = this;
if (that._selectedView && typeof that._selectedView.startStreaming === "function") that._selectedView.startStreaming();
},
stopStreaming: function() {
let that = this;
if (that._selectedView && typeof that._selectedView.stopStreaming === "function") that._selectedView.stopStreaming();
if (that.outputManager) that.outputManager.stopAllLoading();
},
setOptions: function(options) {
let that = this;
let el = that.element;
let originalOptions = that.options;
let newOptions = extend({}, originalOptions, options);
kendo.destroy(el);
$(el).empty();
that.init(el, newOptions);
},
destroy: function() {
let that = this;
if (that.toolbar) {
that.toolbar.destroy();
that.toolbar = null;
}
if (that._selectedView) {
that._selectedView.destroy();
that._selectedView = null;
}
if (that.outputManager) {
that.outputManager.destroy();
that.outputManager = null;
}
if (that.outputActionManager) {
that.outputActionManager.destroy();
that.outputActionManager = null;
}
that.promptOutputs = null;
if (that.outputObjects) {
that.outputObjects.clear();
that.outputObjects = null;
}
if (that.transport) that.transport = null;
that.element.off(NS);
Widget.fn.destroy.call(that);
}
});
ui.plugin(AIPrompt);
})(window.kendo.jQuery);
var kendo_aiprompt_default = kendo;
//#endregion
Object.defineProperty(exports, "__meta__", {
enumerable: true,
get: function() {
return __meta__;
}
});
Object.defineProperty(exports, "kendo_aiprompt_default", {
enumerable: true,
get: function() {
return kendo_aiprompt_default;
}
});