UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,195 lines (1,193 loc) 36.5 kB
const require_prefix_suffix_containers = require('./prefix-suffix-containers-DnpogsKh.js'); //#region ../src/kendo.smartbox.js const __meta__ = { id: "smartbox", name: "SmartBox", category: "web", description: "The SmartBox is a new AI-powered capability designed to enhance standard search fields across key UI components.", depends: [ "list", "speechtotextbutton", "textbox", "segmentedcontrol" ] }; (function($, undefined) { const kendo = window.kendo; const encode = kendo.htmlEncode; const ui = kendo.ui; const List = kendo.ui.List; const DataSource = kendo.data.DataSource; const keys = kendo.keys; const ns = ".kendoSmartBox"; const FOCUSED = "k-focus"; const DISABLED = "k-disabled"; const FOCUS = "focus"; const BLUR = "blur"; const OPEN = "open"; const CLOSE = "close"; const INPUT = "input"; const KEYDOWN = "keydown"; const CLICK = "click"; const AI_ASSISTANT_PROMPT_REQUEST = "aiAssistantPromptRequest"; const AI_ASSISTANT_RESPONSE_SUCCESS = "aiAssistantResponseSuccess"; const AI_ASSISTANT_RESPONSE_ERROR = "aiAssistantResponseError"; const AI_ASSISTANT_CANCEL_REQUEST = "aiAssistantCancelRequest"; const STREAMING_UPDATE = "streamingUpdate"; const SEARCH = "search"; const SEMANTIC_SEARCH = "semanticSearch"; const MODES = { search: "Search", semanticSearch: "SemanticSearch", aiAssistant: "AIAssistant" }; const HISTORY_MAP = { [MODES.search]: "_searchHistory", [MODES.semanticSearch]: "_semanticSearchHistory", [MODES.aiAssistant]: "_aiAssistantHistory" }; const DEFAULT_ITEM_FIELD = "value"; const SEARCH_MODE_OPTIONS_ROLE = "_searchModeOptions"; const DEFAULT_POPUP_MAX_HEIGHT = "320px"; const DEFAULT_INPUT_WIDTH = "450px"; const DEFAULT_INPUT_MIN_WIDTH = "350px"; const getFirstValidActivatedMode = (activeModeOption, enabledModes) => { const includesDefaultMode = enabledModes.indexOf(MODES.search) > -1; const isIncluded = enabledModes.indexOf(activeModeOption) > -1; if (enabledModes.length > 1) { if (!activeModeOption) { return includesDefaultMode ? MODES.search : enabledModes[0]; } if (isIncluded) { return activeModeOption; } else if (includesDefaultMode) { return MODES.search; } else { return enabledModes[0]; } } return isIncluded ? activeModeOption : enabledModes[0]; }; const SmartBox = List.extend({ init: function(element, options) { var that = this; that.ns = ns; List.fn.init.call(that, element, options); options = that.options; that._enabledModes = that._getEnabledModes(); that._activeMode = getFirstValidActivatedMode(options.activeMode, that._enabledModes); that._input(); that._wrapper(); that._popup(); that._dataSource(); that._initList(); that._setHeaderTemplate(); that._header(); that._aiTransport(); that._addPromptSuggestions(); that._addPrefixSuffix(); if (!that._enabledModes.length && that.options.searchSettings?.enabled === false) { that._textBox.enable(false); } ; that._bindEvents(); kendo.notify(that); }, options: { name: "SmartBox", activeMode: "Search", placeholder: "", size: undefined, rounded: undefined, fillMode: undefined, history: { size: 5, timestampFormat: "h:mm" }, searchSettings: { delay: 300, enabled: true }, semanticSearchSettings: null, aiAssistantSettings: null, suggestionTemplate: null, historyItemTemplate: null, messages: { noPreviousSearches: "No previous searches", noPreviousPrompts: "No previous prompts", previousSearches: "Previously Searched", previousPrompts: "Previously Asked", suggestedPrompts: "Suggested Prompts", searchModeLabel: "Search", searchModeDescription: "Looks for exact word matches across your data", searchPlaceholder: "Search", semanticSearchModeLabel: "Semantic Search", semanticSearchModeDescription: "Understands context to surface the most relevant results.", semanticSearchPlaceholder: "Semantic Search", semanticSearchButtonText: "Search", aiAssistantPlaceholder: "Sort, filter or group with AI", speechToText: "Speech to text", speechToTextAriaLabel: "Start speech recognition", cancel: "Cancel", send: "Send", searchButtonText: "Search", aiAssistantButtonText: "AI Assistant" } }, events: [ OPEN, CLOSE, FOCUS, BLUR, AI_ASSISTANT_PROMPT_REQUEST, AI_ASSISTANT_RESPONSE_SUCCESS, AI_ASSISTANT_RESPONSE_ERROR, AI_ASSISTANT_CANCEL_REQUEST, STREAMING_UPDATE, SEARCH, SEMANTIC_SEARCH ], _dataSource: function() { const that = this; if (that.dataSource && that._refreshHandler) { that.dataSource.off(); that.dataSource = null; } that.dataSource = DataSource.create({ data: [], group: { field: "role", compare: that._compareGroups } }); }, _compareGroups: function(a, b) { const aOrder = a.items?.[0]?._groupOrder ?? 99; const bOrder = b.items?.[0]?._groupOrder ?? 99; return aOrder - bOrder; }, _aiTransport: function() { const that = this; that.transport = new kendo.data.AiTransport({ service: that._getAIServiceConfig(), success: that._aiServiceSuccess.bind(that), error: that._aiServiceError.bind(that), requestStart: () => that._aiRequestStart() }); }, _addPromptSuggestions: function() { const that = this; const options = that.options; const aiSettings = options.aiAssistantSettings; if (!aiSettings || !aiSettings.promptSuggestions) { return; } that._suggestions = aiSettings?.promptSuggestions?.map((item) => ({ value: item, suggestion: item, role: options.messages.suggestedPrompts, groupIcon: "clock-arrow-rotate", _isSuggestion: true, _groupOrder: 1 })) || []; }, _aiRequestStart: function() { const that = this; that._isLoading = true; that._addPrefixSuffix(); }, _aiServiceSuccess: function(output) { const that = this; that._currentRequest = null; that._isLoading = false; that._addPrefixSuffix(); const eventArgs = { prompt: output.prompt, response: output.response }; if (!that.trigger(AI_ASSISTANT_RESPONSE_SUCCESS, eventArgs)) { that._pushValueToHistory(output.prompt); } }, _aiServiceError: function(output) { const that = this; that._currentRequest = null; if (output.response && output.response.statusText === "abort") { return; } that._isLoading = false; that._addPrefixSuffix(); const eventArgs = { output: output.output, prompt: output.prompt, response: output.response }; that.trigger(AI_ASSISTANT_RESPONSE_ERROR, eventArgs); }, cancelAIRequest: function() { const that = this; if (that._isLoading) { if (that._currentRequest && that._currentRequest.abort) { that._currentRequest.abort(); that._currentRequest = null; } that._isLoading = false; that._addPrefixSuffix(); that.trigger(AI_ASSISTANT_CANCEL_REQUEST); } }, sendAIPrompt: function(prompt, options) { const that = this; if (!that.transport) { return; } options = options || {}; const history = that._aiAssistantHistory || []; const service = that._getAIServiceConfig(); const request = that.transport.read({ prompt, history: options.history || history.map((item) => ({ role: "user", contents: [{ $type: "text", text: item.value }] })), service }); that._currentRequest = request; if (request && typeof request.always === "function") { request.always(() => that.value("")); } else if (request && typeof request.finally === "function") { request.finally(() => that.value("")); } }, startStreaming: function() { const that = this; that._isLoading = true; that._addPrefixSuffix(); }, stopStreaming: function() { const that = this; that._isLoading = false; that._addPrefixSuffix(); }, _wrapper: function() { let wrapper = this.element.parent(); this.wrapper = wrapper.addClass("k-smart-box").removeClass("k-textbox"); this._focused = this.element; }, _input: function() { const that = this; const options = that.options; that.element.attr({ placeholder: that._getPlaceholder(), autocomplete: "off", "aria-expanded": false }).css({ width: DEFAULT_INPUT_WIDTH, minWidth: DEFAULT_INPUT_MIN_WIDTH }); that._textBox = that.element.kendoTextBox({ size: options.size, rounded: options.rounded, fillMode: options.fillMode, clearButton: that._isSearchMode() }).data("kendoTextBox"); if (that._textBox._clear) { that._textBox._clear.off(CLICK); that._textBox._clear.on(CLICK + ns, function(e) { e.preventDefault(); that._onClearClick(); }); } }, _onClearClick: function() { const that = this; that.value(""); that._executeSearch(""); that._textBox._hideClear(); that.focus(); }, _addPrefixSuffix: function() { const that = this; const mode = that._activeMode; const isLoading = that._isLoading; const clearButton = that._textBox?._clear; if (clearButton && clearButton.length) { clearButton.detach(); } that.wrapper.find(".k-input-prefix, .k-input-suffix").remove(); if (that._speechToTextButton) { that._speechToTextButton.destroy(); that._speechToTextButton = null; } let prefixOptions = {}; let suffixOptions = {}; const modeSettings = that._getModeSettings(mode); const hasSpeechToText = modeSettings.speechToTextButton; if (mode === MODES.search) { prefixOptions = { icon: "search" }; } else if (mode === MODES.semanticSearch) { prefixOptions = { icon: "zoom-sparkle", iconClass: "k-accent-icon" }; } else if (mode === MODES.aiAssistant) { prefixOptions = { icon: "sparkles", iconClass: "k-accent-icon" }; suffixOptions = { template: () => that._renderAISuffixTemplate(isLoading, hasSpeechToText, that.options.messages) }; } require_prefix_suffix_containers.addInputPrefixSuffixContainers({ widget: that, wrapper: that.wrapper, options: { prefixOptions, suffixOptions }, prefixInsertBefore: that.element }); if (that._isSearchMode() && clearButton && clearButton.length) { let suffix = that.wrapper.find(".k-input-suffix"); if (!suffix.length) { suffix = $("<span class=\"k-input-suffix\"></span>"); that.wrapper.append(suffix); } suffix.append(clearButton); } if (mode === MODES.aiAssistant && hasSpeechToText) { that._initSpeechToTextButton(); } that._toggleClearButtonPerMode(); }, _toggleClearButtonPerMode: function() { const that = this; const mode = that._activeMode; const isLoading = that._isLoading; if (mode === MODES.aiAssistant) { that._bindSuffixEvents(isLoading); if (that._textBox && that._textBox._clear) { that._textBox._clear.hide(); } } else if (that._textBox && that._textBox._clear) { that._textBox._clear.show(); if (that.value()) { that._textBox._showClear(); } else { that._textBox._hideClear(); } } }, _renderAISuffixTemplate: function(isLoading, hasSpeechToText, messages) { const that = this; let template = ""; if (hasSpeechToText) { template += `<button title="${encode(messages.speechToText)}" aria-label="${encode(messages.speechToTextAriaLabel)}" ref='smartbox-speech-to-text'></button>`; } if (isLoading) { template += kendo.html.renderButton(`<button class='k-smart-box-send' ref='smartbox-cancel' title='${encode(messages.cancel)}'></button>`, { icon: "stop-sm", fillMode: "solid", themeColor: "base", size: that.options.size, rounded: "full" }); } else { template += kendo.html.renderButton(`<button class='k-smart-box-send${!that.value() ? ` ${DISABLED}` : ""}' ref='smartbox-send' title='${encode(messages.send)}'></button>`, { icon: "arrow-up-outline", fillMode: "solid", size: that.options.size, themeColor: "base", rounded: "full" }); } return template; }, _initSpeechToTextButton: function() { const that = this; const modeSettings = that._getModeSettings(); const speechToTextOptions = modeSettings.speechToTextButton; const SpeechToTextButton = kendo.ui.SpeechToTextButton; if (!SpeechToTextButton || !speechToTextOptions) { return; } const element = that.wrapper.find("[ref='smartbox-speech-to-text']"); if (!element.length) { return; } const options = $.extend({}, { themeColor: "base", fillMode: "clear", size: that.options.size, integrationMode: speechToTextOptions.integrationMode || "webSpeech", lang: speechToTextOptions.lang || "en-US", continuous: speechToTextOptions.continuous || false, interimResults: speechToTextOptions.interimResults || false, maxAlternatives: speechToTextOptions.maxAlternatives || 1, result: function(ev) { if (ev.isFinal && ev.alternatives && ev.alternatives.length > 0) { const currentValue = that.value() || ""; const newValue = currentValue + (currentValue ? " " : "") + ev.alternatives[0].transcript; that.value(newValue); that.element.trigger("input"); } } }, speechToTextOptions); that._speechToTextButton = new SpeechToTextButton(element, options); }, _bindSuffixEvents: function(isLoading) { const that = this; that.wrapper.find("[ref='smartbox-send'], [ref='smartbox-cancel']").off(ns); if (isLoading) { that.wrapper.find("[ref='smartbox-cancel']").on(CLICK + ns, function(e) { e.preventDefault(); that.cancelAIRequest(); }); } else { that.wrapper.find("[ref='smartbox-send']").on(CLICK + ns, function(e) { e.preventDefault(); const value = that.value(); if (value) { that._triggerAIAssistantRequest(value); } }); } }, _getModeSettings: function(mode) { const that = this; const options = that.options; const getMode = mode || that._activeMode; if (getMode === MODES.search) { return options.searchSettings || {}; } else if (getMode === MODES.semanticSearch) { return options.semanticSearchSettings || {}; } else if (getMode === MODES.aiAssistant) { return options.aiAssistantSettings || {}; } return {}; }, _getPlaceholder: function() { const that = this; const options = that.options; const mode = that._activeMode; const messages = options.messages; const settings = that._getModeSettings(mode); let defaultPlaceholder = ""; switch (mode) { case MODES.search: defaultPlaceholder = messages.searchPlaceholder; break; case MODES.semanticSearch: defaultPlaceholder = messages.semanticSearchPlaceholder; break; case MODES.aiAssistant: defaultPlaceholder = messages.aiAssistantPlaceholder; break; } return settings?.placeholder || options.placeholder || defaultPlaceholder; }, _popup: function() { this.options.popup = $.extend(this.options.popup, { copyAnchorStyles: true }); List.fn._popup.call(this); }, value: function(val) { var that = this; if (val === undefined) { return that._textBox ? that._textBox.value() : that.element.val(); } if (that._textBox) { that._textBox.value(val); } else { that.element.val(val); } }, enable: function(enable) { var that = this; if (that._textBox) { that._textBox.enable(enable); } that.wrapper.toggleClass(DISABLED, enable === false); }, readonly: function(readonly) { var that = this; if (that._textBox) { that._textBox.readonly(readonly); } }, focus: function() { var that = this; if (that._textBox) { that._textBox.focus(); } else { that.element[0].focus(); } }, _isSearchMode: function() { const that = this; const mode = that._activeMode; return mode === MODES.search || mode === MODES.semanticSearch; }, _handleItemClick: function(item) { const that = this; const mode = that._activeMode; if (!item) { return; } const textEl = item.find(".k-list-item-text"); const value = textEl.length ? textEl.first().text() : item.text(); that.value(value); that._oldValue = value; if (mode === MODES.search) { that._executeSearch(value); } if (that._textBox && that._isSearchMode()) { that._textBox._showClear(); } const aiSendButton = that.wrapper.find("[ref='smartbox-send']"); if (mode === MODES.aiAssistant && aiSendButton.length) { aiSendButton.removeClass(DISABLED); } that.close(); }, _handleActionItem: function(e) { const that = this; const action = e.action; if (action && action.indexOf("switchMode:") === 0) { const mode = action.replace("switchMode:", ""); that._switchMode(mode); } }, _listBound: function() { const that = this; const data = that.dataSource.flatView(); const length = data.length; const groupsLength = that.dataSource._group ? that.dataSource._group.length : 0; that._renderNoData(); that._toggleNoData(!length && that._shouldRenderModeButton()); that._toggleHeader(!!groupsLength && !!length); that._removeSearchModeOptionsGroupHeader(); that._applyListItemTooltips(); that._applyCheckIconClass(); }, _applyCheckIconClass: function() { const that = this; if (!that.listView || !that.listView.content) { return; } that.listView.content.find("[data-action^='switchMode:'] .k-list-item-icon-wrapper .k-list-item-icon").addClass("k-smart-box-check-icon"); }, _applyListItemTooltips: function() { const that = this; if (!that.list) { return; } const listItems = that.list.find(".k-list-item:not(.k-list-group-item):not([data-action])"); listItems.each(function() { const item = $(this); const textEl = item.find(".k-list-item-text"); const text = textEl.length ? textEl.text() : item.text(); item.attr("title", text.trim()); }); }, _renderNoData: function() { const that = this; const noData = that.noData; if (!noData) { return; } const messages = that.options.messages; const isAIMode = that._activeMode === MODES.aiAssistant; const icon = "file-report"; const text = isAIMode ? messages.noPreviousPrompts : messages.noPreviousSearches; const html = kendo.ui.icon({ icon, iconClass: "k-icon-xxxl" }) + "<span>" + encode(text) + "</span>"; noData.addClass("k-smart-box-no-data").html(html); }, _removeSearchModeOptionsGroupHeader: function() { const that = this; if (!that.listView || !that.listView.content || !that._shouldRenderSearchModeOptions() || !that._isSearchMode()) { return; } that.listView.content.find(".k-list-group-item").each(function() { const $groupItem = $(this); if ($groupItem.text().trim() === "") { $groupItem.remove(); } }); }, _updateCssClasses: function() { const that = this; const popup = that.popup; popup.element.removeClass("k-list-container").addClass("k-smart-box-popup"); that.list.find(".k-list-content").removeClass("k-list-scroller"); }, _listOptions: function(options) { const that = this; return $.extend({ autoBind: false, selectable: false, dataSource: that.dataSource, click: function(e) { that._handleItemClick(e.item); }, action: function(e) { that._handleActionItem(e); }, dataBound: that._listBound.bind(that), dataValueField: DEFAULT_ITEM_FIELD, dataTextField: DEFAULT_ITEM_FIELD, iconField: "icon", descriptionField: "description", actionField: "action", groupIconField: "groupIcon", fixedGroupHeader: false, template: that._getItemTemplate(), groupTemplate: function(group) { if (group === SEARCH_MODE_OPTIONS_ROLE) { return ""; } return encode(group); } }, options); }, _getItemTemplate: function() { const that = this; const suggestionTemplate = that.options.suggestionTemplate; const historyItemTemplate = that.options.historyItemTemplate; if (!suggestionTemplate && !historyItemTemplate) { return null; } const compiledSuggestionTemplate = suggestionTemplate ? kendo.template(suggestionTemplate) : null; const compiledHistoryItemTemplate = historyItemTemplate ? kendo.template(historyItemTemplate) : null; return function(dataItem) { if (dataItem._isSuggestion && compiledSuggestionTemplate) { return compiledSuggestionTemplate(dataItem); } if (dataItem._isHistoryItem && compiledHistoryItemTemplate) { return compiledHistoryItemTemplate(dataItem); } return encode(dataItem.value || ""); }; }, _setHeaderTemplate: function() { const that = this; if (!that._shouldRenderModeButton()) { return; } that.options.headerTemplate = function() { return `<div ref="modeSwitcher"></div>`; }; }, _initModeButton: function() { const that = this; const messages = that.options.messages; if (!that._shouldRenderModeButton() || !that.header) { return; } const container = that.header; let selectedValue = that._isSearchMode() ? MODES.search : MODES.aiAssistant; let searchModeButton = { value: MODES.search, text: messages.searchButtonText, icon: "search" }; if (that._enabledModes.indexOf(MODES.search) < 0) { searchModeButton = { value: MODES.semanticSearch, text: messages.semanticSearchButtonText, icon: "zoom-sparkle", iconClassOnSelection: "k-accent-icon" }; selectedValue = that._activeMode; } that._segmentedControl = container.kendoSegmentedControl({ size: "small", selectedValue, layoutMode: "stretch", items: [searchModeButton, { value: MODES.aiAssistant, text: messages.aiAssistantButtonText, icon: "sparkles", iconClassOnSelection: "k-accent-icon" }], change: function(e) { that._switchMode(e.value); } }).data("kendoSegmentedControl"); }, _switchMode: function(mode) { const that = this; const currentMode = that._activeMode; if (that._isSearchMode() && mode === MODES.aiAssistant) { that._lastSearchMode = currentMode; } if (mode === MODES.search && currentMode === MODES.aiAssistant && that._lastSearchMode) { mode = that._lastSearchMode; } that._activeMode = mode; that.element.attr("placeholder", that._getPlaceholder()); that.value(""); that._addPrefixSuffix(); that._updateHeaderActiveState(); that._showViewPopup(); }, _updateHeaderActiveState: function() { const that = this; if (!that._segmentedControl) { return; } if (that._isSearchMode()) { const firstItemValue = that._segmentedControl._items[0].value; that._segmentedControl.value(firstItemValue); that._updateSearchModeIcon(); } else { that._removeSearchModeAccent(); that._segmentedControl.value(MODES.aiAssistant); } }, _updateSearchModeIcon: function() { const that = this; if (!that._segmentedControl) { return; } const mode = that._activeMode; const iconName = mode === MODES.semanticSearch ? "zoom-sparkle" : "search"; const firstButton = that._segmentedControl.element.find("button[data-value]").first(); const iconEl = firstButton.find(".k-icon,.k-svg-icon").first(); if (!iconEl.length) { return; } const currentIconClass = iconEl[0].className.split(" ").find((c) => c.indexOf("k-svg-i-") === 0 || c.indexOf("k-i-") === 0); if (currentIconClass) { iconEl.removeClass(currentIconClass); } const isSvg = iconEl.hasClass("k-svg-icon"); iconEl.addClass(isSvg ? "k-svg-i-" + iconName : "k-i-" + iconName); iconEl.toggleClass("k-accent-icon", mode === MODES.semanticSearch); if (isSvg) { const svgContent = kendo.ui.icon({ icon: iconName }); const tempEl = $(svgContent); const newSvg = tempEl.find("svg").addBack("svg"); if (newSvg.length) { iconEl.find("svg").replaceWith(newSvg); } } }, _removeSearchModeAccent: function() { const that = this; if (!that._segmentedControl) { return; } const firstButton = that._segmentedControl.element.find("button[data-value]").first(); firstButton.find(".k-icon,.k-svg-icon").first().removeClass("k-accent-icon"); }, _shouldRenderSearchModeOptions: function() { const enabledModes = this._enabledModes; return enabledModes.includes(MODES.search) && enabledModes.includes(MODES.semanticSearch); }, _getSearchModeOptions: function() { const that = this; const messages = that.options.messages; const enabledModes = that._enabledModes; const options = []; if (enabledModes.includes(MODES.search)) { const isActive = that._activeMode === MODES.search; options.push({ value: messages.searchModeLabel, description: messages.searchModeDescription, icon: isActive ? "check" : null, action: "switchMode:" + MODES.search, mode: MODES.search, role: SEARCH_MODE_OPTIONS_ROLE, _groupOrder: 2 }); } if (enabledModes.includes(MODES.semanticSearch)) { const isActive = that._activeMode === MODES.semanticSearch; options.push({ value: messages.semanticSearchModeLabel, description: messages.semanticSearchModeDescription, icon: isActive ? "check" : null, action: "switchMode:" + MODES.semanticSearch, mode: MODES.semanticSearch, role: SEARCH_MODE_OPTIONS_ROLE, _groupOrder: 2 }); } return options; }, _shouldRenderModeButton: function() { const enabledModes = this._enabledModes; const hasSearchMode = enabledModes.includes(MODES.search) || enabledModes.includes(MODES.semanticSearch); const hasAIAssistant = enabledModes.includes(MODES.aiAssistant); return hasSearchMode && hasAIAssistant; }, _shouldRenderNoData: function() { const that = this; return that._shouldRenderModeButton() && that.dataSource.data().length === 0; }, _getEnabledModes: function() { const that = this; const options = that.options; const modes = []; if (options.searchSettings && options.searchSettings.enabled !== false) { modes.push(MODES.search); } if (options.semanticSearchSettings && options.semanticSearchSettings.enabled !== false) { modes.push(MODES.semanticSearch); } if (options.aiAssistantSettings && options.aiAssistantSettings.enabled !== false) { modes.push(MODES.aiAssistant); } return modes; }, _bindEvents: function() { const that = this; that.element.on(`${FOCUS}${ns}`, () => that._onFocus()).on(`${BLUR}${ns}`, () => that._onBlur()).on(`${KEYDOWN}${ns}`, (e) => that._onKeydown(e)).on(`${INPUT}${ns}`, (e) => that._onInput(e)); that.wrapper.on(`${CLICK}${ns}`, ".k-input-prefix", () => { if (that.popup.visible()) { that.close(); } that.element.trigger(FOCUS + ns); }); that.popup.one(OPEN, () => { that._updateCssClasses(); that.popup.element.css({ "margin-top": "2px" }); that.popup.element.find(".k-list").css({ "max-height": DEFAULT_POPUP_MAX_HEIGHT }); that._initModeButton(); }); that.popup.bind("activate", () => { if (that.listView) { that.listView.select([]); that.current(-1); } if (that._segmentedControl) { that._segmentedControl._calculateThumbPosition(); } }); }, _unbindEvents: function() { const that = this; that.element.off(ns); that.wrapper.off(ns); }, _onFocus: function() { const that = this; const mode = that._activeMode; const hasHistory = that[HISTORY_MAP[mode]]?.length > 0; const hasSuggestions = mode === MODES.aiAssistant && that._suggestions?.length > 0; const shouldRenderModeButton = that._shouldRenderModeButton(); const shouldRenderSearchModeOptions = that._shouldRenderSearchModeOptions() && that._isSearchMode(); const shouldShowPopup = hasHistory || hasSuggestions || shouldRenderModeButton || shouldRenderSearchModeOptions; that.wrapper.addClass(FOCUSED); if (shouldShowPopup) { that._showViewPopup(); } that.trigger(FOCUS); }, _onBlur: function() { if (!this.trigger(BLUR)) { this.wrapper.removeClass(FOCUSED); this.close(); } }, _onKeydown: function(e) { const that = this; const key = e.keyCode; const mode = that._activeMode; const value = that.element.val(); if (key === keys.ENTER) { if (value) { that.close(); if (mode === MODES.aiAssistant) { that._triggerAIAssistantRequest(value); } else { clearTimeout(that._searchTimeout); that._executeSearch(value); } } e.preventDefault(); } else if (key === keys.ESC) { that.close(); } }, _executeSearch: function(value) { const that = this; const mode = that._activeMode; if (!value && value !== "") { return; } if (mode === MODES.search) { if (!that.trigger(SEARCH, { searchValue: value })) { that._search(value); that._pushValueToHistory(value); } } else if (mode === MODES.semanticSearch) { that.trigger("semanticSearch", { searchValue: value }); that._pushValueToHistory(value); } }, _onInput: function(e) { const that = this; const options = that.options; const mode = that._activeMode; const value = that.element.val(); const isDeleting = that._oldValue && value.length < that._oldValue.length; that.wrapper.find("[ref='smartbox-send']")?.toggleClass(DISABLED, !value); if (isDeleting && value === "") { that._showViewPopup(); } else { that.close(); } if (that._isSearchMode()) { let delay; if (mode === MODES.search) { delay = options.searchSettings?.delay || 300; } if (mode === MODES.semanticSearch) { delay = options.semanticSearchSettings?.delay || 900; } clearTimeout(that._searchTimeout); that._searchTimeout = setTimeout(() => { that._executeSearch(value); }, delay); } that.value(value); that._oldValue = value; }, _showViewPopup: function() { const that = this; const mode = that._activeMode; const hasSuggestions = that._suggestions?.length > 0; const shouldRenderModeButton = that._shouldRenderModeButton(); const shouldRenderSearchModeOptions = that._shouldRenderSearchModeOptions(); const isSearchMode = that._isSearchMode(); const historySettings = that._getHistorySettings(mode); const historyEnabled = historySettings.enabled !== false; let history = historyEnabled ? that[HISTORY_MAP[mode]] || [] : []; const hasHistory = history.length > 0; if (!hasHistory && !hasSuggestions && !shouldRenderModeButton && !(shouldRenderSearchModeOptions && isSearchMode)) { return; } if (shouldRenderSearchModeOptions && isSearchMode) { const searchModeOptions = that._getSearchModeOptions(); history = [...searchModeOptions, ...history]; } if (mode === MODES.aiAssistant && hasSuggestions) { history = [...that._suggestions, ...history]; } that._setListData(history); that.open(); }, _setListData: function(data) { var that = this; if (!data) { data = []; } data.sort((a, b) => (a._groupOrder || 0) - (b._groupOrder || 0)); that.dataSource.data(data); }, _getHistorySettings: function(mode) { const that = this; const options = that.options; const getMode = mode || that._activeMode; const modeSettings = that._getModeSettings(getMode); const componentHistory = options.history; const modeHistory = modeSettings?.history; if (modeHistory === false) { return { enabled: false, size: 0, timestampFormat: null }; } if (componentHistory === false) { return { enabled: false, size: 0, timestampFormat: null }; } const globalSettings = componentHistory || {}; const modeHistorySettings = modeHistory || {}; let size, timestampFormat; if (modeHistorySettings.size !== undefined) { size = modeHistorySettings.size; } else if (globalSettings.size !== undefined) { size = globalSettings.size; } if (modeHistorySettings.timestampFormat !== undefined) { timestampFormat = modeHistorySettings.timestampFormat; } else if (globalSettings.timestampFormat !== undefined) { timestampFormat = globalSettings.timestampFormat; } return { enabled: true, size, timestampFormat }; }, _pushValueToHistory: function(value) { const that = this; const mode = that._activeMode; const historySettings = that._getHistorySettings(mode); if (!value) { return; } if (historySettings.enabled === false) { return; } const size = historySettings.size; const timestampFormat = historySettings.timestampFormat; if (size <= 0) { return; } let history = that[HISTORY_MAP[mode]] || []; if (history.length >= size) { history.pop(); } const timestamp = new Date(); history.unshift({ value, role: that._isSearchMode() ? that.options.messages.previousSearches : that.options.messages.previousPrompts, groupIcon: "clock", timestamp, timestampFormat, description: kendo.toString(timestamp, timestampFormat), _groupOrder: 3, _isHistoryItem: true }); that[HISTORY_MAP[mode]] = history; that.close(); }, _search: function(value) { const that = this; const options = that.options; const searchSettings = options.searchSettings || {}; const dataSourceReference = searchSettings.dataSource || null; if (!dataSourceReference) { return; } const searchFields = searchSettings.fields || dataSourceReference.options?.search?.fields || null; let expression = { filters: [], logic: "or" }; if (that.dataSourceReference.options.endless) { that.dataSourceReference.options.endless = null; that._endlessPageSize = that.dataSourceReference.options.pageSize; } if (value) { for (let i = 0; i < searchFields.length; i++) { that._pushExpression(expression.filters, searchFields[i], value); } } else { expression = {}; } dataSourceReference.filter(expression); }, _getAIServiceConfig: function() { const that = this; const aiOptions = that.options.aiAssistantSettings || {}; const serviceIsString = typeof aiOptions.service === "string"; if (!aiOptions.service) { return {}; } const url = serviceIsString ? aiOptions.service : aiOptions.service.url; if (url) { return { ...!serviceIsString ? aiOptions.service : {}, url }; } return {}; }, _triggerAIAssistantRequest: function(prompt) { const that = this; if (!prompt) { return; } const history = that._aiAssistantHistory || []; const eventArgs = { prompt, history: history.map((item) => ({ role: "user", contents: [{ $type: "text", text: item.value }] })), service: that._getAIServiceConfig() }; if (that.trigger(AI_ASSISTANT_PROMPT_REQUEST, eventArgs)) { return; } if (that.transport) { that.sendAIPrompt(prompt, eventArgs); } that.close(); }, open: function() { const that = this; that.popup.open(); }, close: function() { const that = this; that.popup.close(); }, activeMode: function(mode) { if (mode === undefined) { return this._activeMode; } if (mode !== this._activeMode && this._getEnabledModes().indexOf(mode) > -1) { this._activeMode = mode; this.element.attr("placeholder", this._getPlaceholder()); } }, destroy: function() { const that = this; clearTimeout(that._searchTimeout); if (that.popup) { that.popup.unbind(); } if (that.transport) { that.transport = null; } if (that._speechToTextButton) { that._speechToTextButton.destroy(); that._speechToTextButton = null; } if (that._textBox) { that._textBox.destroy(); that._textBox = null; } if (that._segmentedControl) { that._segmentedControl.destroy(); that._segmentedControl = null; } that.wrapper.find("[ref='smartbox-send'], [ref='smartbox-cancel']").off(ns); that.element.off(ns); that.wrapper.off(ns); List.fn.destroy.call(that); } }); ui.plugin(SmartBox); })(window.kendo.jQuery); var kendo_smartbox_default = kendo; //#endregion Object.defineProperty(exports, '__meta__', { enumerable: true, get: function () { return __meta__; } }); Object.defineProperty(exports, 'kendo_smartbox_default', { enumerable: true, get: function () { return kendo_smartbox_default; } });