@crestapps/ai-chat-ui 1.0.0-preview.9 → 1.0.0-preview.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/ai-chat-widget.js +962 -0
  2. package/dist/ai-chat-widget.js.map +1 -0
  3. package/dist/ai-chat-widget.min.js +2 -0
  4. package/dist/ai-chat-widget.min.js.map +1 -0
  5. package/dist/ai-chat.css +45 -14
  6. package/dist/ai-chat.css.map +1 -1
  7. package/dist/ai-chat.js +1076 -1019
  8. package/dist/ai-chat.js.map +1 -1
  9. package/dist/ai-chat.min.css +1 -1
  10. package/dist/ai-chat.min.js +1 -1
  11. package/dist/ai-chat.min.js.map +1 -1
  12. package/dist/chat-interaction-settings.js +297 -0
  13. package/dist/chat-interaction-settings.js.map +1 -0
  14. package/dist/chat-interaction-settings.min.js +2 -0
  15. package/dist/chat-interaction-settings.min.js.map +1 -0
  16. package/dist/chat-interaction.js +1224 -325
  17. package/dist/chat-interaction.js.map +1 -1
  18. package/dist/chat-interaction.min.js +1 -1
  19. package/dist/chat-interaction.min.js.map +1 -1
  20. package/dist/chat-widget.css +48 -26
  21. package/dist/chat-widget.css.map +1 -1
  22. package/dist/chat-widget.min.css +1 -1
  23. package/dist/document-drop-zone.css +10 -10
  24. package/dist/document-drop-zone.css.map +1 -1
  25. package/dist/document-drop-zone.js +92 -14
  26. package/dist/document-drop-zone.js.map +1 -1
  27. package/dist/document-drop-zone.min.css +1 -1
  28. package/dist/document-drop-zone.min.js +1 -1
  29. package/dist/document-drop-zone.min.js.map +1 -1
  30. package/dist/technical-name-generator.js +36 -8
  31. package/dist/technical-name-generator.js.map +1 -1
  32. package/dist/technical-name-generator.min.js +1 -1
  33. package/dist/technical-name-generator.min.js.map +1 -1
  34. package/package.json +9 -1
  35. package/README.md +0 -145
@@ -3,22 +3,25 @@
3
3
  ** Any changes made directly to this file will be overwritten next time its asset group is processed by Gulp.
4
4
  */
5
5
 
6
- function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
7
- function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
8
- function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
9
- function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
10
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
6
+ var _excluded = ["placeholder"];
11
7
  function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
12
8
  function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
13
9
  function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
14
10
  function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
15
- function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
16
11
  function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
17
12
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
18
- function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
19
13
  function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
20
14
  function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
15
+ function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
16
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
17
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
18
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
19
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
20
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
21
21
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
22
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
23
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
24
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
22
25
  window.chatInteractionManager = function () {
23
26
  // Defaults (can be overridden by instanceConfig)
24
27
  var defaultConfig = {
@@ -29,9 +32,12 @@ window.chatInteractionManager = function () {
29
32
  downloadChartTitle: 'Download chart as image',
30
33
  downloadChartButtonText: 'Download',
31
34
  codeCopiedText: 'Copied!',
35
+ copyTitle: 'Click here to copy response to clipboard.',
36
+ copiedTitle: 'Response copied to clipboard.',
37
+ copyResetDelayMs: 2000,
32
38
  assistantLabel: 'Assistant',
33
- messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">You</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><span :class=\"getAssistantIcon(message)\"></span></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <span :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></span>\n </button>\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" title=\"Click here to copy response to clipboard.\">\n <span class=\"fa-solid fa-copy\"></span>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <span v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></span>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <span class=\"fa-solid fa-xmark\"></span>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <span v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></span>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n ",
34
- indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><span class=\"fa fa-robot\" style=\"display: inline-block;\"></span></span>\n Assistant\n </div>\n ",
39
+ messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">You</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <ol v-if=\"message.citationReferences && message.citationReferences.length\" class=\"ai-chat-citation-list\">\n <li v-for=\"citation in message.citationReferences\" :key=\"'citation-' + (citation.referenceKey || citation.displayIndex)\" class=\"ai-chat-citation-item\">\n <a v-if=\"citation.link\" :href=\"citation.link\" :target=\"citation.isDownload ? null : '_blank'\" :rel=\"citation.isDownload ? null : 'noopener noreferrer'\">{{ citation.label }}</a>\n <span v-else>{{ citation.label }}</span>\n </li>\n </ol>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" :data-tts-message-index=\"index\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <i :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-link p-0 button-message-toolbox ai-response-copy-btn\" :class=\"copiedMessageIndex === index ? 'text-success' : 'text-secondary'\" :data-copy-message-index=\"index\" @click=\"copyResponse(message, index, $event)\" :title=\"copiedMessageIndex === index ? copiedTitle : copyTitle\">\n <i :class=\"copiedMessageIndex === index ? 'fa-solid fa-check' : 'fa-solid fa-copy'\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <i v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></i>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <i v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></i>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n ",
40
+ indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><i class=\"fa fa-robot\" style=\"display: inline-block;\"></i></span>\n Assistant\n </div>\n ",
35
41
  // Localizable strings
36
42
  untitledText: 'Untitled',
37
43
  clearHistoryTitle: 'Clear History',
@@ -56,6 +62,240 @@ window.chatInteractionManager = function () {
56
62
  span.textContent = text;
57
63
  return span.innerHTML;
58
64
  }
65
+ function containsFontAwesomePlaceholders(root) {
66
+ if (!root || root.nodeType !== 1) {
67
+ return false;
68
+ }
69
+ var selector = 'i[class*="fa-"],i.fa,i.fas,i.far,i.fab';
70
+ if (typeof root.matches === 'function' && root.matches(selector)) {
71
+ return true;
72
+ }
73
+ return typeof root.querySelector === 'function' && !!root.querySelector(selector);
74
+ }
75
+ function refreshFontAwesomeIcons(root) {
76
+ var fontAwesome = window.FontAwesome;
77
+ if (!containsFontAwesomePlaceholders(root) || !fontAwesome || !fontAwesome.dom || typeof fontAwesome.dom.i2svg !== 'function') {
78
+ return;
79
+ }
80
+ fontAwesome.dom.i2svg({
81
+ node: root
82
+ });
83
+ }
84
+ function observeFontAwesomeIcons(root) {
85
+ if (!root || typeof MutationObserver === 'undefined') {
86
+ return null;
87
+ }
88
+ var observer = new MutationObserver(function (mutations) {
89
+ mutations.forEach(function (mutation) {
90
+ mutation.addedNodes.forEach(function (node) {
91
+ refreshFontAwesomeIcons(node);
92
+ });
93
+ });
94
+ });
95
+ observer.observe(root, {
96
+ childList: true,
97
+ subtree: true
98
+ });
99
+ return observer;
100
+ }
101
+ function normalizeReference(reference) {
102
+ var _ref, _normalized$index, _ref2, _normalized$text, _ref3, _normalized$title, _ref4, _normalized$link, _ref5, _normalized$reference, _normalized$isGenerat;
103
+ if (!reference || _typeof(reference) !== 'object') {
104
+ return null;
105
+ }
106
+ var normalized = Object.assign({}, reference);
107
+ normalized.index = (_ref = (_normalized$index = normalized.index) !== null && _normalized$index !== void 0 ? _normalized$index : normalized.Index) !== null && _ref !== void 0 ? _ref : 0;
108
+ normalized.text = (_ref2 = (_normalized$text = normalized.text) !== null && _normalized$text !== void 0 ? _normalized$text : normalized.Text) !== null && _ref2 !== void 0 ? _ref2 : null;
109
+ normalized.title = (_ref3 = (_normalized$title = normalized.title) !== null && _normalized$title !== void 0 ? _normalized$title : normalized.Title) !== null && _ref3 !== void 0 ? _ref3 : null;
110
+ normalized.link = sanitizeUrl((_ref4 = (_normalized$link = normalized.link) !== null && _normalized$link !== void 0 ? _normalized$link : normalized.Link) !== null && _ref4 !== void 0 ? _ref4 : null);
111
+ normalized.referenceType = (_ref5 = (_normalized$reference = normalized.referenceType) !== null && _normalized$reference !== void 0 ? _normalized$reference : normalized.ReferenceType) !== null && _ref5 !== void 0 ? _ref5 : null;
112
+ normalized.isGenerated = ((_normalized$isGenerat = normalized.isGenerated) !== null && _normalized$isGenerat !== void 0 ? _normalized$isGenerat : normalized.IsGenerated) === true;
113
+ return normalized;
114
+ }
115
+ function isDownloadCitationReference(reference) {
116
+ if (!reference || _typeof(reference) !== 'object') {
117
+ return false;
118
+ }
119
+ if (typeof reference.referenceType === 'string' && reference.referenceType.toLowerCase() === 'document') {
120
+ return true;
121
+ }
122
+ if (typeof reference.link === 'string' && /\/ai\/documents\/.+\/download(?:$|\?)/i.test(reference.link)) {
123
+ return true;
124
+ }
125
+ return false;
126
+ }
127
+ function normalizeReferences(references) {
128
+ if (!references || _typeof(references) !== 'object') {
129
+ return {};
130
+ }
131
+ var normalized = {};
132
+ for (var _i = 0, _Object$entries = Object.entries(references); _i < _Object$entries.length; _i++) {
133
+ var _normalizeReference;
134
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
135
+ key = _Object$entries$_i[0],
136
+ value = _Object$entries$_i[1];
137
+ normalized[key] = (_normalizeReference = normalizeReference(value)) !== null && _normalizeReference !== void 0 ? _normalizeReference : {};
138
+ }
139
+ return normalized;
140
+ }
141
+ function getCitationLabel(reference, key) {
142
+ return reference.title || reference.text || key;
143
+ }
144
+ function buildCitationDisplay(content, references) {
145
+ var processedContent = (content || '').trim();
146
+ var messageReferences = normalizeReferences(references);
147
+ var referenceEntries = Object.entries(messageReferences);
148
+ if (!referenceEntries.length) {
149
+ return {
150
+ content: processedContent,
151
+ citations: []
152
+ };
153
+ }
154
+ var citedRefs = referenceEntries.filter(function (_ref6) {
155
+ var _ref7 = _slicedToArray(_ref6, 1),
156
+ key = _ref7[0];
157
+ return processedContent.includes(key);
158
+ });
159
+ var generatedRefs = referenceEntries.filter(function (_ref8) {
160
+ var _ref9 = _slicedToArray(_ref8, 2),
161
+ key = _ref9[0],
162
+ value = _ref9[1];
163
+ return value.isGenerated && !processedContent.includes(key);
164
+ });
165
+ if (!citedRefs.length && !generatedRefs.length) {
166
+ return {
167
+ content: processedContent,
168
+ citations: []
169
+ };
170
+ }
171
+ citedRefs.sort(function (_ref0, _ref1) {
172
+ var _ref10 = _slicedToArray(_ref0, 2),
173
+ a = _ref10[1];
174
+ var _ref11 = _slicedToArray(_ref1, 2),
175
+ b = _ref11[1];
176
+ return a.index - b.index;
177
+ });
178
+ generatedRefs.sort(function (_ref12, _ref13) {
179
+ var _ref14 = _slicedToArray(_ref12, 2),
180
+ a = _ref14[1];
181
+ var _ref15 = _slicedToArray(_ref13, 2),
182
+ b = _ref15[1];
183
+ return a.index - b.index;
184
+ });
185
+ var citations = [];
186
+ var displayIndex = 1;
187
+ var _iterator = _createForOfIteratorHelper(citedRefs),
188
+ _step;
189
+ try {
190
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
191
+ var _step$value = _slicedToArray(_step.value, 2),
192
+ key = _step$value[0],
193
+ value = _step$value[1];
194
+ var placeholder = "__CITE_".concat(displayIndex, "_").concat(value.index || displayIndex, "__");
195
+ processedContent = processedContent.replaceAll(key, placeholder);
196
+ citations.push({
197
+ referenceKey: key,
198
+ displayIndex: displayIndex,
199
+ label: getCitationLabel(value, key),
200
+ link: value.link || null,
201
+ isDownload: isDownloadCitationReference(value),
202
+ placeholder: placeholder
203
+ });
204
+ displayIndex++;
205
+ }
206
+ } catch (err) {
207
+ _iterator.e(err);
208
+ } finally {
209
+ _iterator.f();
210
+ }
211
+ for (var _i2 = 0, _citations = citations; _i2 < _citations.length; _i2++) {
212
+ var citation = _citations[_i2];
213
+ processedContent = processedContent.replaceAll(citation.placeholder, "<sup>".concat(citation.displayIndex, "</sup>"));
214
+ }
215
+ processedContent = processedContent.replaceAll('</sup><sup>', '</sup><sup>,</sup><sup>');
216
+
217
+ // Generated files (such as exported tabular data) are always offered as a download even when
218
+ // the model does not cite them inline, so the user never loses access to the produced file.
219
+ var _iterator2 = _createForOfIteratorHelper(generatedRefs),
220
+ _step2;
221
+ try {
222
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
223
+ var _step2$value = _slicedToArray(_step2.value, 2),
224
+ _key = _step2$value[0],
225
+ _value = _step2$value[1];
226
+ citations.push({
227
+ referenceKey: _key,
228
+ displayIndex: displayIndex,
229
+ label: getCitationLabel(_value, _key),
230
+ link: _value.link || null,
231
+ isDownload: true,
232
+ placeholder: null
233
+ });
234
+ displayIndex++;
235
+ }
236
+ } catch (err) {
237
+ _iterator2.e(err);
238
+ } finally {
239
+ _iterator2.f();
240
+ }
241
+ return {
242
+ content: processedContent,
243
+ citations: citations.map(function (_ref16) {
244
+ var placeholder = _ref16.placeholder,
245
+ citation = _objectWithoutProperties(_ref16, _excluded);
246
+ return citation;
247
+ })
248
+ };
249
+ }
250
+ function buildCopyContent(content, citations) {
251
+ var copyContent = (content || '').trim();
252
+ if (!copyContent || !Array.isArray(citations) || citations.length === 0) {
253
+ return copyContent;
254
+ }
255
+ var _iterator3 = _createForOfIteratorHelper(citations),
256
+ _step3;
257
+ try {
258
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
259
+ var citation = _step3.value;
260
+ copyContent = copyContent.replaceAll(citation.referenceKey, "[".concat(citation.displayIndex, "]"));
261
+ }
262
+ } catch (err) {
263
+ _iterator3.e(err);
264
+ } finally {
265
+ _iterator3.f();
266
+ }
267
+ copyContent += '\n\nReferences:\n';
268
+ var _iterator4 = _createForOfIteratorHelper(citations),
269
+ _step4;
270
+ try {
271
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
272
+ var _citation = _step4.value;
273
+ copyContent += "".concat(_citation.displayIndex, ". ").concat(_citation.label);
274
+ if (_citation.link) {
275
+ copyContent += " - ".concat(_citation.link);
276
+ }
277
+ copyContent += '\n';
278
+ }
279
+ } catch (err) {
280
+ _iterator4.e(err);
281
+ } finally {
282
+ _iterator4.f();
283
+ }
284
+ return copyContent.trimEnd();
285
+ }
286
+ function updateMessagePresentation(message, references) {
287
+ var messageReferences = normalizeReferences(references !== null && references !== void 0 ? references : message.references);
288
+ var rawContent = typeof message.rawContent === 'string' ? message.rawContent : typeof message.content === 'string' ? message.content : '';
289
+ var citationDisplay = buildCitationDisplay(rawContent, messageReferences);
290
+ message.rawContent = rawContent;
291
+ message.content = rawContent;
292
+ message.displayContent = citationDisplay.content;
293
+ message.references = messageReferences;
294
+ message.citationReferences = citationDisplay.citations;
295
+ message.copyContent = buildCopyContent(rawContent, citationDisplay.citations);
296
+ message.htmlContent = parseMarkdownContent(citationDisplay.content, message);
297
+ return message;
298
+ }
59
299
  var renderer = new marked.Renderer();
60
300
 
61
301
  // Modify the link rendering to open in a new tab
@@ -86,7 +326,7 @@ window.chatInteractionManager = function () {
86
326
  highlighted = escapeHtmlEntities(code);
87
327
  }
88
328
  var langDisplay = lang ? escapeHtmlEntities(lang) : 'code';
89
- return "<div class=\"ai-code-block\"><div class=\"ai-code-header\"><span class=\"ai-code-lang\"><span class=\"fa-solid fa-code\"></span> ".concat(langDisplay, "</span><button type=\"button\" class=\"ai-code-copy-btn\" title=\"Copy code\"><span class=\"fa-regular fa-copy\"></span></button></div><pre><code class=\"hljs").concat(lang ? ' language-' + lang : '', "\">").concat(highlighted, "</code></pre></div>");
329
+ return "<div class=\"ai-code-block\"><div class=\"ai-code-header\"><span class=\"ai-code-lang\"><i class=\"fa-solid fa-code\"></i> ".concat(langDisplay, "</span><button type=\"button\" class=\"ai-code-copy-btn\" title=\"Copy code\"><i class=\"fa-regular fa-copy\"></i></button></div><pre><code class=\"hljs").concat(lang ? ' language-' + lang : '', "\">").concat(highlighted, "</code></pre></div>");
90
330
  };
91
331
 
92
332
  // Custom image renderer for generated images with thumbnail styling and download button.
@@ -96,7 +336,7 @@ window.chatInteractionManager = function () {
96
336
  if (!src) return '';
97
337
  var alt = data.text || defaultConfig.generatedImageAltText;
98
338
  var maxWidth = defaultConfig.generatedImageMaxWidth;
99
- return "<div class=\"generated-image-container\">\n <img src=\"".concat(src, "\" alt=\"").concat(alt, "\" class=\"img-thumbnail\" style=\"max-width: ").concat(maxWidth, "px; height: auto;\" />\n <div class=\"mt-2\">\n <a href=\"").concat(src, "\" target=\"_blank\" download=\"").concat(alt, "\" title=\"").concat(defaultConfig.downloadImageTitle, "\" class=\"btn btn-sm btn-outline-secondary ai-download-image\">\n <span class=\"fa-solid fa-download\"></span>\n </a>\n </div>\n </div>");
339
+ return "<div class=\"generated-image-container\">\n <img src=\"".concat(src, "\" alt=\"").concat(alt, "\" class=\"img-thumbnail\" style=\"max-width: ").concat(maxWidth, "px; height: auto;\" />\n <div class=\"mt-2\">\n <a href=\"").concat(src, "\" target=\"_blank\" download=\"").concat(alt, "\" title=\"").concat(defaultConfig.downloadImageTitle, "\" class=\"btn btn-sm btn-outline-secondary ai-download-image\">\n <i class=\"fa-solid fa-download\"></i>\n </a>\n </div>\n </div>");
100
340
  };
101
341
 
102
342
  // Chart counter for unique IDs
@@ -108,7 +348,7 @@ window.chatInteractionManager = function () {
108
348
  // Global chart config map shared with ai-chat.js
109
349
  window.__chartConfigs = window.__chartConfigs || {};
110
350
  function createChartHtml(chartId) {
111
- return "<div class=\"chart-container\" style=\"position: relative; width: 100%; max-width: 560px; min-height: 420px;\">" + "<canvas id=\"".concat(chartId, "\"></canvas>") + "</div>" + "<div class=\"mt-2\">" + "<button type=\"button\" class=\"btn btn-sm btn-outline-secondary download-chart-btn\" data-chart-id=\"".concat(chartId, "\" title=\"").concat(defaultConfig.downloadChartTitle, "\">") + "<span class=\"fa-solid fa-download\"></span> ".concat(defaultConfig.downloadChartButtonText) + "</button>" + "</div>";
351
+ return "<div class=\"chart-container\" style=\"position: relative; width: 100%; max-width: 560px; min-height: 420px;\">" + "<canvas id=\"".concat(chartId, "\"></canvas>") + "</div>" + "<div class=\"mt-2\">" + "<button type=\"button\" class=\"btn btn-sm btn-outline-secondary download-chart-btn\" data-chart-id=\"".concat(chartId, "\" title=\"").concat(defaultConfig.downloadChartTitle, "\">") + "<i class=\"fa-solid fa-download\"></i> ".concat(defaultConfig.downloadChartButtonText) + "</button>" + "</div>";
112
352
  }
113
353
 
114
354
  // Register [chart:{...json...}] as a native marked block extension so the
@@ -219,11 +459,11 @@ window.chatInteractionManager = function () {
219
459
  // Defer to requestAnimationFrame so the browser has fully laid out the
220
460
  // canvas elements before Chart.js reads their dimensions.
221
461
  requestAnimationFrame(function () {
222
- var _iterator = _createForOfIteratorHelper(charts),
223
- _step;
462
+ var _iterator5 = _createForOfIteratorHelper(charts),
463
+ _step5;
224
464
  try {
225
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
226
- var c = _step.value;
465
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
466
+ var c = _step5.value;
227
467
  var canvas = document.getElementById(c.chartId);
228
468
  if (!canvas) {
229
469
  continue;
@@ -256,9 +496,9 @@ window.chatInteractionManager = function () {
256
496
  }
257
497
  }
258
498
  } catch (err) {
259
- _iterator.e(err);
499
+ _iterator5.e(err);
260
500
  } finally {
261
- _iterator.f();
501
+ _iterator5.f();
262
502
  }
263
503
  });
264
504
  }
@@ -277,8 +517,18 @@ window.chatInteractionManager = function () {
277
517
  ADD_ATTR: ['target']
278
518
  });
279
519
  }
520
+ function compactObject(source) {
521
+ if (!source || _typeof(source) !== 'object') {
522
+ return {};
523
+ }
524
+ return Object.fromEntries(Object.entries(source).filter(function (_ref17) {
525
+ var _ref18 = _slicedToArray(_ref17, 2),
526
+ value = _ref18[1];
527
+ return value !== undefined;
528
+ }));
529
+ }
280
530
  var initialize = function initialize(instanceConfig) {
281
- var config = Object.assign({}, defaultConfig, instanceConfig);
531
+ var config = Object.assign({}, defaultConfig, compactObject(instanceConfig));
282
532
  // Keep defaultConfig in sync so renderers use overridden values
283
533
  defaultConfig = config;
284
534
  if (!config.signalRHubUrl) {
@@ -339,7 +589,12 @@ window.chatInteractionManager = function () {
339
589
  conversationButton: null,
340
590
  isConversationMode: false,
341
591
  notifications: [],
342
- notificationDismissTimers: {}
592
+ notificationDismissTimers: {},
593
+ copyTitle: config.copyTitle,
594
+ copiedTitle: config.copiedTitle,
595
+ copiedMessageIndex: -1,
596
+ copyResetTimeoutId: null,
597
+ activeCopyButton: null
343
598
  };
344
599
  },
345
600
  computed: {
@@ -467,7 +722,7 @@ window.chatInteractionManager = function () {
467
722
  _this.scrollToBottom();
468
723
  }
469
724
  });
470
- _this.connection.on("ReceiveConversationAssistantToken", function (itemId, messageId, token, responseId, appearance) {
725
+ _this.connection.on("ReceiveConversationAssistantToken", function (itemId, messageId, token, responseId, references, appearance) {
471
726
  if (!_this._conversationAssistantMessage) {
472
727
  _this.stopAudio();
473
728
  _this.hideTypingIndicator();
@@ -485,7 +740,8 @@ window.chatInteractionManager = function () {
485
740
  content: "",
486
741
  htmlContent: "",
487
742
  isStreaming: true,
488
- appearance: _this.normalizeAssistantAppearance(appearance)
743
+ appearance: _this.normalizeAssistantAppearance(appearance),
744
+ references: {}
489
745
  };
490
746
  _this.messages.push(newMessage);
491
747
  _this._conversationAssistantMessage = {
@@ -499,19 +755,22 @@ window.chatInteractionManager = function () {
499
755
  if (!msg.appearance) {
500
756
  msg.appearance = _this.normalizeAssistantAppearance(appearance);
501
757
  }
502
- msg.content = _this._conversationAssistantMessage.content;
503
- msg.htmlContent = parseMarkdownContent(msg.content, msg);
758
+ msg.rawContent = _this._conversationAssistantMessage.content;
759
+ msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
760
+ updateMessagePresentation(msg, msg.references);
504
761
  _this.$nextTick(function () {
505
762
  renderChartsInMessage(msg);
506
763
  _this.scrollToBottom();
507
764
  });
508
765
  }
509
766
  });
510
- _this.connection.on("ReceiveConversationAssistantComplete", function (itemId, messageId) {
767
+ _this.connection.on("ReceiveConversationAssistantComplete", function (itemId, messageId, references) {
511
768
  if (_this._conversationAssistantMessage) {
512
769
  var msg = _this.messages[_this._conversationAssistantMessage.index];
513
770
  if (msg) {
514
771
  msg.isStreaming = false;
772
+ msg.references = normalizeReferences(Object.assign({}, msg.references || {}, references || {}));
773
+ updateMessagePresentation(msg, msg.references);
515
774
  }
516
775
  _this._conversationAssistantMessage = null;
517
776
  }
@@ -605,79 +864,9 @@ window.chatInteractionManager = function () {
605
864
  addMessage: function addMessage(message) {
606
865
  var _this3 = this;
607
866
  if (message.content) {
608
- var processedContent = message.content.trim();
609
- if (message.references && _typeof(message.references) === "object" && Object.keys(message.references).length) {
610
- // Only include references that were actually cited in the response.
611
- var citedRefs = Object.entries(message.references).filter(function (_ref) {
612
- var _ref2 = _slicedToArray(_ref, 1),
613
- key = _ref2[0];
614
- return processedContent.includes(key);
615
- });
616
- if (citedRefs.length) {
617
- // Sort by original index so display indices follow a natural order.
618
- citedRefs.sort(function (_ref3, _ref4) {
619
- var _ref5 = _slicedToArray(_ref3, 2),
620
- a = _ref5[1];
621
- var _ref6 = _slicedToArray(_ref4, 2),
622
- b = _ref6[1];
623
- return a.index - b.index;
624
- });
625
-
626
- // Phase 1: Replace all markers with unique placeholders.
627
- var displayIndex = 1;
628
- var _iterator2 = _createForOfIteratorHelper(citedRefs),
629
- _step2;
630
- try {
631
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
632
- var _step2$value = _slicedToArray(_step2.value, 2),
633
- key = _step2$value[0],
634
- value = _step2$value[1];
635
- var placeholder = "__CITE_".concat(value.index, "__");
636
- processedContent = processedContent.replaceAll(key, placeholder);
637
- value._displayIndex = displayIndex++;
638
- value._placeholder = placeholder;
639
- }
640
-
641
- // Phase 2: Replace placeholders with sequential display indices.
642
- } catch (err) {
643
- _iterator2.e(err);
644
- } finally {
645
- _iterator2.f();
646
- }
647
- var _iterator3 = _createForOfIteratorHelper(citedRefs),
648
- _step3;
649
- try {
650
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
651
- var _step3$value = _slicedToArray(_step3.value, 2),
652
- _value = _step3$value[1];
653
- processedContent = processedContent.replaceAll(_value._placeholder, "<sup><strong>".concat(_value._displayIndex, "</strong></sup>"));
654
- }
655
- } catch (err) {
656
- _iterator3.e(err);
657
- } finally {
658
- _iterator3.f();
659
- }
660
- processedContent = processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
661
- processedContent += '<br><br>';
662
- var _iterator4 = _createForOfIteratorHelper(citedRefs),
663
- _step4;
664
- try {
665
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
666
- var _step4$value = _slicedToArray(_step4.value, 2),
667
- _key = _step4$value[0],
668
- _value2 = _step4$value[1];
669
- var label = _value2.text || "[doc:".concat(_value2.index, "]");
670
- processedContent += _value2.link ? "**".concat(_value2._displayIndex, "**. [").concat(label, "](").concat(_value2.link, ")<br>") : "**".concat(_value2._displayIndex, "**. ").concat(label, "<br>");
671
- }
672
- } catch (err) {
673
- _iterator4.e(err);
674
- } finally {
675
- _iterator4.f();
676
- }
677
- }
678
- }
679
- message.content = processedContent;
680
- message.htmlContent = parseMarkdownContent(processedContent, message);
867
+ var _message$rawContent;
868
+ message.rawContent = (_message$rawContent = message.rawContent) !== null && _message$rawContent !== void 0 ? _message$rawContent : message.content;
869
+ updateMessagePresentation(message, message.references);
681
870
  }
682
871
  this.addMessageInternal(message);
683
872
  this.hidePlaceholder();
@@ -828,11 +1017,12 @@ window.chatInteractionManager = function () {
828
1017
  message = newMessage;
829
1018
  }
830
1019
  if (chunk.references && _typeof(chunk.references) === "object" && Object.keys(chunk.references).length) {
831
- for (var _i = 0, _Object$entries = Object.entries(chunk.references); _i < _Object$entries.length; _i++) {
832
- var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
833
- key = _Object$entries$_i[0],
834
- value = _Object$entries$_i[1];
835
- references[key] = value;
1020
+ for (var _i3 = 0, _Object$entries2 = Object.entries(chunk.references); _i3 < _Object$entries2.length; _i3++) {
1021
+ var _normalizeReference2;
1022
+ var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i3], 2),
1023
+ key = _Object$entries2$_i[0],
1024
+ value = _Object$entries2$_i[1];
1025
+ references[key] = (_normalizeReference2 = normalizeReference(value)) !== null && _normalizeReference2 !== void 0 ? _normalizeReference2 : {};
836
1026
  }
837
1027
  }
838
1028
  if (chunk.content) {
@@ -844,17 +1034,10 @@ window.chatInteractionManager = function () {
844
1034
  if (chunk.responseId) {
845
1035
  lastResponseId = chunk.responseId;
846
1036
  }
847
- var processedContent = chunk.content;
848
- for (var _i2 = 0, _Object$entries2 = Object.entries(references); _i2 < _Object$entries2.length; _i2++) {
849
- var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
850
- _key2 = _Object$entries2$_i[0],
851
- _value3 = _Object$entries2$_i[1];
852
- processedContent = processedContent.replaceAll(_key2, "<sup><strong>".concat(_value3.index, "</strong></sup>"));
853
- }
854
- content += processedContent.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
1037
+ content += chunk.content;
855
1038
  }
856
- message.content = content;
857
- message.htmlContent = parseMarkdownContent(content, message);
1039
+ message.rawContent = content;
1040
+ updateMessagePresentation(message, references);
858
1041
  _this5.messages[messageIndex] = message;
859
1042
  _this5.$nextTick(function () {
860
1043
  renderChartsInMessage(message);
@@ -908,86 +1091,12 @@ window.chatInteractionManager = function () {
908
1091
  },
909
1092
  processReferences: function processReferences(references, messageIndex) {
910
1093
  var _this6 = this;
1094
+ references = normalizeReferences(references);
911
1095
  if (Object.keys(references).length) {
1096
+ var _ref19, _message$rawContent2;
912
1097
  var message = this.messages[messageIndex];
913
- var content = message.content || '';
914
-
915
- // Only include references that were actually cited in the response.
916
- // Check both raw [doc:N] markers and already-rendered <sup> tags from streaming.
917
- var citedRefs = Object.entries(references).filter(function (_ref7) {
918
- var _ref8 = _slicedToArray(_ref7, 2),
919
- key = _ref8[0],
920
- value = _ref8[1];
921
- return content.includes(key) || content.includes("<sup><strong>".concat(value.index, "</strong></sup>"));
922
- });
923
- if (!citedRefs.length) {
924
- return;
925
- }
926
-
927
- // Sort by original index so display indices follow a natural order.
928
- citedRefs.sort(function (_ref9, _ref0) {
929
- var _ref1 = _slicedToArray(_ref9, 2),
930
- a = _ref1[1];
931
- var _ref10 = _slicedToArray(_ref0, 2),
932
- b = _ref10[1];
933
- return a.index - b.index;
934
- });
935
-
936
- // Phase 1: Replace all markers with unique placeholders to avoid collisions during remapping.
937
- var processed = content.trim();
938
- var displayIndex = 1;
939
- var _iterator5 = _createForOfIteratorHelper(citedRefs),
940
- _step5;
941
- try {
942
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
943
- var _step5$value = _slicedToArray(_step5.value, 2),
944
- key = _step5$value[0],
945
- value = _step5$value[1];
946
- var placeholder = "__CITE_".concat(value.index, "__");
947
- processed = processed.replaceAll(key, placeholder);
948
- processed = processed.replaceAll("<sup><strong>".concat(value.index, "</strong></sup>"), placeholder);
949
- value._displayIndex = displayIndex++;
950
- value._placeholder = placeholder;
951
- }
952
-
953
- // Phase 2: Replace placeholders with sequential display indices.
954
- } catch (err) {
955
- _iterator5.e(err);
956
- } finally {
957
- _iterator5.f();
958
- }
959
- var _iterator6 = _createForOfIteratorHelper(citedRefs),
960
- _step6;
961
- try {
962
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
963
- var _step6$value = _slicedToArray(_step6.value, 2),
964
- _value4 = _step6$value[1];
965
- processed = processed.replaceAll(_value4._placeholder, "<sup><strong>".concat(_value4._displayIndex, "</strong></sup>"));
966
- }
967
- } catch (err) {
968
- _iterator6.e(err);
969
- } finally {
970
- _iterator6.f();
971
- }
972
- processed = processed.replaceAll('</strong></sup><sup>', '</strong></sup><sup>,</sup><sup>');
973
- processed += '<br><br>';
974
- var _iterator7 = _createForOfIteratorHelper(citedRefs),
975
- _step7;
976
- try {
977
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
978
- var _step7$value = _slicedToArray(_step7.value, 2),
979
- _key3 = _step7$value[0],
980
- _value5 = _step7$value[1];
981
- var label = _value5.text || "[doc:".concat(_value5.index, "]");
982
- processed += _value5.link ? "**".concat(_value5._displayIndex, "**. [").concat(label, "](").concat(_value5.link, ")<br>") : "**".concat(_value5._displayIndex, "**. ").concat(label, "<br>");
983
- }
984
- } catch (err) {
985
- _iterator7.e(err);
986
- } finally {
987
- _iterator7.f();
988
- }
989
- message.content = processed;
990
- message.htmlContent = parseMarkdownContent(processed, message);
1098
+ message.rawContent = (_ref19 = (_message$rawContent2 = message.rawContent) !== null && _message$rawContent2 !== void 0 ? _message$rawContent2 : message.content) !== null && _ref19 !== void 0 ? _ref19 : '';
1099
+ updateMessagePresentation(message, references);
991
1100
  this.messages[messageIndex] = message;
992
1101
  this.$nextTick(function () {
993
1102
  renderChartsInMessage(message);
@@ -1039,8 +1148,55 @@ window.chatInteractionManager = function () {
1039
1148
  }
1040
1149
  this.stopAudio(false);
1041
1150
  },
1042
- synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
1151
+ updateTtsPlaybackButtons: function updateTtsPlaybackButtons() {
1043
1152
  var _this7 = this;
1153
+ if (!this.chatContainer) {
1154
+ return;
1155
+ }
1156
+ var buttons = this.chatContainer.querySelectorAll('[data-tts-message-index]');
1157
+ buttons.forEach(function (button) {
1158
+ var buttonIndex = Number(button.getAttribute('data-tts-message-index'));
1159
+ var isPlaying = buttonIndex === _this7.ttsPlayingMessageIndex;
1160
+ var iconHtml = isPlaying ? '<i class="fa-solid fa-circle-pause"></i>' : '<i class="fa-solid fa-circle-play"></i>';
1161
+ button.classList.toggle('tts-playing', isPlaying);
1162
+ button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');
1163
+ button.replaceChildren(DOMPurify.sanitize(iconHtml, {
1164
+ RETURN_DOM_FRAGMENT: true
1165
+ }));
1166
+ });
1167
+ },
1168
+ updateCopyButtons: function updateCopyButtons() {
1169
+ var _this8 = this;
1170
+ if (!this.chatContainer) {
1171
+ return;
1172
+ }
1173
+ var buttons = this.chatContainer.querySelectorAll('[data-copy-message-index]');
1174
+ buttons.forEach(function (button) {
1175
+ var buttonIndex = Number(button.getAttribute('data-copy-message-index'));
1176
+ var isCopied = buttonIndex === _this8.copiedMessageIndex;
1177
+ var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
1178
+ button.classList.toggle('text-success', isCopied);
1179
+ button.classList.toggle('text-secondary', !isCopied);
1180
+ button.setAttribute('title', isCopied ? _this8.copiedTitle : _this8.copyTitle);
1181
+ button.replaceChildren(DOMPurify.sanitize(iconHtml, {
1182
+ RETURN_DOM_FRAGMENT: true
1183
+ }));
1184
+ });
1185
+ },
1186
+ setCopyButtonState: function setCopyButtonState(button, isCopied) {
1187
+ if (!button) {
1188
+ return;
1189
+ }
1190
+ var iconHtml = isCopied ? '<i class="fa-solid fa-check"></i>' : '<i class="fa-solid fa-copy"></i>';
1191
+ button.classList.toggle('text-success', isCopied);
1192
+ button.classList.toggle('text-secondary', !isCopied);
1193
+ button.setAttribute('title', isCopied ? this.copiedTitle : this.copyTitle);
1194
+ button.replaceChildren(DOMPurify.sanitize(iconHtml, {
1195
+ RETURN_DOM_FRAGMENT: true
1196
+ }));
1197
+ },
1198
+ synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
1199
+ var _this9 = this;
1044
1200
  if (!this.textToSpeechEnabled || !text || !this.connection) {
1045
1201
  return;
1046
1202
  }
@@ -1049,12 +1205,16 @@ window.chatInteractionManager = function () {
1049
1205
  this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;
1050
1206
  this.connection.invoke("SynthesizeSpeech", this.getItemId(), text, this.ttsVoiceName)["catch"](function (err) {
1051
1207
  console.error("TTS synthesis error:", err);
1052
- _this7.isPlayingAudio = false;
1053
- _this7.ttsPlayingMessageIndex = -1;
1054
- _this7._ttsCacheIndex = -1;
1208
+ _this9.isPlayingAudio = false;
1209
+ _this9.ttsPlayingMessageIndex = -1;
1210
+ _this9._ttsCacheIndex = -1;
1211
+ _this9.$nextTick(function () {
1212
+ return _this9.updateTtsPlaybackButtons();
1213
+ });
1055
1214
  });
1056
1215
  },
1057
1216
  toggleMessageTts: function toggleMessageTts(message, index) {
1217
+ var _this0 = this;
1058
1218
  if (this.ttsPlayingMessageIndex === index) {
1059
1219
  this.stopAudio();
1060
1220
  return;
@@ -1066,6 +1226,9 @@ window.chatInteractionManager = function () {
1066
1226
  }
1067
1227
  }));
1068
1228
  this.ttsPlayingMessageIndex = index;
1229
+ this.$nextTick(function () {
1230
+ return _this0.updateTtsPlaybackButtons();
1231
+ });
1069
1232
  if (this.ttsAudioCache[index]) {
1070
1233
  this.playAudioBlob(this.ttsAudioCache[index]);
1071
1234
  return;
@@ -1073,10 +1236,14 @@ window.chatInteractionManager = function () {
1073
1236
  this.synthesizeSpeech(message.content, index);
1074
1237
  },
1075
1238
  playCollectedAudio: function playCollectedAudio() {
1239
+ var _this1 = this;
1076
1240
  if (this.audioChunks.length === 0) {
1077
1241
  if (!this.isPlayingAudio && this.audioPlayQueue.length === 0) {
1078
1242
  this.isPlayingAudio = false;
1079
1243
  this.ttsPlayingMessageIndex = -1;
1244
+ this.$nextTick(function () {
1245
+ return _this1.updateTtsPlaybackButtons();
1246
+ });
1080
1247
  }
1081
1248
  return;
1082
1249
  }
@@ -1085,18 +1252,18 @@ window.chatInteractionManager = function () {
1085
1252
  }, 0);
1086
1253
  var combined = new Uint8Array(totalLength);
1087
1254
  var offset = 0;
1088
- var _iterator8 = _createForOfIteratorHelper(this.audioChunks),
1089
- _step8;
1255
+ var _iterator6 = _createForOfIteratorHelper(this.audioChunks),
1256
+ _step6;
1090
1257
  try {
1091
- for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
1092
- var chunk = _step8.value;
1258
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
1259
+ var chunk = _step6.value;
1093
1260
  combined.set(chunk, offset);
1094
1261
  offset += chunk.length;
1095
1262
  }
1096
1263
  } catch (err) {
1097
- _iterator8.e(err);
1264
+ _iterator6.e(err);
1098
1265
  } finally {
1099
- _iterator8.f();
1266
+ _iterator6.f();
1100
1267
  }
1101
1268
  this.audioChunks = [];
1102
1269
  var blob = new Blob([combined], {
@@ -1115,45 +1282,53 @@ window.chatInteractionManager = function () {
1115
1282
  this.playAudioBlob(blob);
1116
1283
  },
1117
1284
  playAudioBlob: function playAudioBlob(blob) {
1118
- var _this8 = this;
1285
+ var _this10 = this;
1119
1286
  var url = URL.createObjectURL(blob);
1120
1287
  var audio = new Audio(url);
1121
1288
  this.currentAudioUrl = url;
1122
1289
  this.currentAudioElement = audio;
1123
1290
  this.isPlayingAudio = true;
1124
1291
  audio.addEventListener('ended', function () {
1125
- _this8.currentAudioElement = null;
1126
- _this8.currentAudioUrl = null;
1292
+ _this10.currentAudioElement = null;
1293
+ _this10.currentAudioUrl = null;
1127
1294
  URL.revokeObjectURL(url);
1128
- _this8.playNextInQueue();
1295
+ _this10.playNextInQueue();
1129
1296
  });
1130
1297
  audio.addEventListener('error', function () {
1131
- _this8.currentAudioElement = null;
1132
- _this8.currentAudioUrl = null;
1298
+ _this10.currentAudioElement = null;
1299
+ _this10.currentAudioUrl = null;
1133
1300
  URL.revokeObjectURL(url);
1134
- _this8.playNextInQueue();
1301
+ _this10.playNextInQueue();
1135
1302
  });
1136
1303
  audio.play()["catch"](function (err) {
1137
1304
  console.error("Audio playback error:", err);
1138
- _this8.currentAudioElement = null;
1139
- _this8.currentAudioUrl = null;
1305
+ _this10.currentAudioElement = null;
1306
+ _this10.currentAudioUrl = null;
1140
1307
  URL.revokeObjectURL(url);
1141
- _this8.audioPlayQueue = [];
1142
- _this8.isPlayingAudio = false;
1143
- _this8.ttsPlayingMessageIndex = -1;
1308
+ _this10.audioPlayQueue = [];
1309
+ _this10.isPlayingAudio = false;
1310
+ _this10.ttsPlayingMessageIndex = -1;
1311
+ _this10.$nextTick(function () {
1312
+ return _this10.updateTtsPlaybackButtons();
1313
+ });
1144
1314
  });
1145
1315
  },
1146
1316
  playNextInQueue: function playNextInQueue() {
1317
+ var _this11 = this;
1147
1318
  if (this.audioPlayQueue.length > 0) {
1148
1319
  var nextBlob = this.audioPlayQueue.shift();
1149
1320
  this.playAudioBlob(nextBlob);
1150
1321
  } else {
1151
1322
  this.isPlayingAudio = false;
1152
1323
  this.ttsPlayingMessageIndex = -1;
1324
+ this.$nextTick(function () {
1325
+ return _this11.updateTtsPlaybackButtons();
1326
+ });
1153
1327
  this.conversationModeOnAudioEnded();
1154
1328
  }
1155
1329
  },
1156
1330
  stopAudio: function stopAudio() {
1331
+ var _this12 = this;
1157
1332
  if (this.currentAudioElement) {
1158
1333
  this.currentAudioElement.pause();
1159
1334
  this.currentAudioElement.currentTime = 0;
@@ -1167,6 +1342,9 @@ window.chatInteractionManager = function () {
1167
1342
  this.audioPlayQueue = [];
1168
1343
  this.isPlayingAudio = false;
1169
1344
  this.ttsPlayingMessageIndex = -1;
1345
+ this.$nextTick(function () {
1346
+ return _this12.updateTtsPlaybackButtons();
1347
+ });
1170
1348
  },
1171
1349
  toggleConversationMode: function toggleConversationMode() {
1172
1350
  if (this.isConversationMode) {
@@ -1176,7 +1354,7 @@ window.chatInteractionManager = function () {
1176
1354
  }
1177
1355
  },
1178
1356
  startConversationMode: function startConversationMode() {
1179
- var _this9 = this;
1357
+ var _this13 = this;
1180
1358
  if (!this.conversationModeEnabled || this.isConversationMode || !this.connection) {
1181
1359
  return;
1182
1360
  }
@@ -1196,30 +1374,30 @@ window.chatInteractionManager = function () {
1196
1374
  }
1197
1375
  }).then(function (stream) {
1198
1376
  var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
1199
- _this9.mediaRecorder = new MediaRecorder(stream, {
1377
+ _this13.mediaRecorder = new MediaRecorder(stream, {
1200
1378
  mimeType: mimeType,
1201
1379
  audioBitsPerSecond: 128000
1202
1380
  });
1203
- _this9._conversationSubject = new signalR.Subject();
1204
- _this9._conversationStream = stream;
1381
+ _this13._conversationSubject = new signalR.Subject();
1382
+ _this13._conversationStream = stream;
1205
1383
 
1206
1384
  // Create an AnalyserNode for volume-based interrupt detection.
1207
1385
  var AudioCtx = window.AudioContext || window.webkitAudioContext;
1208
1386
  if (AudioCtx) {
1209
- _this9._conversationAudioCtx = new AudioCtx();
1210
- _this9._conversationAnalyser = _this9._conversationAudioCtx.createAnalyser();
1211
- _this9._conversationAnalyser.fftSize = 256;
1212
- var micSource = _this9._conversationAudioCtx.createMediaStreamSource(stream);
1213
- micSource.connect(_this9._conversationAnalyser);
1387
+ _this13._conversationAudioCtx = new AudioCtx();
1388
+ _this13._conversationAnalyser = _this13._conversationAudioCtx.createAnalyser();
1389
+ _this13._conversationAnalyser.fftSize = 256;
1390
+ var micSource = _this13._conversationAudioCtx.createMediaStreamSource(stream);
1391
+ micSource.connect(_this13._conversationAnalyser);
1214
1392
  }
1215
1393
  var pendingChunk = Promise.resolve();
1216
- var analyser = _this9._conversationAnalyser;
1394
+ var analyser = _this13._conversationAnalyser;
1217
1395
  var interruptVolumeThreshold = 30;
1218
- _this9.mediaRecorder.addEventListener('dataavailable', function (e) {
1396
+ _this13.mediaRecorder.addEventListener('dataavailable', function (e) {
1219
1397
  if (e.data && e.data.size > 0) {
1220
1398
  // During TTS playback, check mic volume to detect
1221
1399
  // user interruption (speaking above threshold).
1222
- if (_this9.isPlayingAudio && analyser) {
1400
+ if (_this13.isPlayingAudio && analyser) {
1223
1401
  var freqData = new Uint8Array(analyser.frequencyBinCount);
1224
1402
  analyser.getByteFrequencyData(freqData);
1225
1403
  var sum = 0;
@@ -1229,7 +1407,7 @@ window.chatInteractionManager = function () {
1229
1407
  var avg = sum / freqData.length;
1230
1408
  if (avg >= interruptVolumeThreshold) {
1231
1409
  // User is speaking — interrupt TTS playback.
1232
- _this9.stopAudio();
1410
+ _this13.stopAudio();
1233
1411
  }
1234
1412
  }
1235
1413
 
@@ -1251,7 +1429,7 @@ window.chatInteractionManager = function () {
1251
1429
  }, '');
1252
1430
  base64 = btoa(binaryString);
1253
1431
  try {
1254
- _this9._conversationSubject.next(base64);
1432
+ _this13._conversationSubject.next(base64);
1255
1433
  } catch (err) {
1256
1434
  // Subject may have been completed already.
1257
1435
  }
@@ -1262,27 +1440,27 @@ window.chatInteractionManager = function () {
1262
1440
  })));
1263
1441
  }
1264
1442
  });
1265
- _this9.mediaRecorder.addEventListener('stop', function () {
1443
+ _this13.mediaRecorder.addEventListener('stop', function () {
1266
1444
  stream.getTracks().forEach(function (track) {
1267
1445
  return track.stop();
1268
1446
  });
1269
1447
  pendingChunk.then(function () {
1270
1448
  try {
1271
- _this9._conversationSubject.complete();
1449
+ _this13._conversationSubject.complete();
1272
1450
  } catch (err) {
1273
1451
  // Already completed.
1274
1452
  }
1275
1453
  });
1276
1454
  });
1277
- var itemId = _this9.getItemId();
1455
+ var itemId = _this13.getItemId();
1278
1456
  var language = navigator.language || document.documentElement.lang || 'en-US';
1279
- _this9.connection.send("StartConversation", itemId, _this9._conversationSubject, mimeType, language);
1280
- _this9.mediaRecorder.start(250);
1281
- _this9.isRecording = true;
1457
+ _this13.connection.send("StartConversation", itemId, _this13._conversationSubject, mimeType, language);
1458
+ _this13.mediaRecorder.start(250);
1459
+ _this13.isRecording = true;
1282
1460
  })["catch"](function (err) {
1283
1461
  console.error('Microphone access denied:', err);
1284
- _this9.isConversationMode = false;
1285
- _this9.updateConversationButton();
1462
+ _this13.isConversationMode = false;
1463
+ _this13.updateConversationButton();
1286
1464
  });
1287
1465
  },
1288
1466
  stopConversationMode: function stopConversationMode() {
@@ -1386,12 +1564,12 @@ window.chatInteractionManager = function () {
1386
1564
  return removedCount;
1387
1565
  },
1388
1566
  scrollToBottom: function scrollToBottom() {
1389
- var _this0 = this;
1567
+ var _this14 = this;
1390
1568
  if (!this.autoScroll) {
1391
1569
  return;
1392
1570
  }
1393
1571
  setTimeout(function () {
1394
- _this0.chatContainer.scrollTop = _this0.chatContainer.scrollHeight - _this0.chatContainer.clientHeight;
1572
+ _this14.chatContainer.scrollTop = _this14.chatContainer.scrollHeight - _this14.chatContainer.clientHeight;
1395
1573
  }, 50);
1396
1574
  },
1397
1575
  handleUserInput: function handleUserInput(event) {
@@ -1407,7 +1585,7 @@ window.chatInteractionManager = function () {
1407
1585
  return document.querySelector('[data-chat-interaction-save-indicator]');
1408
1586
  },
1409
1587
  showSaveIndicator: function showSaveIndicator(text, className) {
1410
- var _this1 = this;
1588
+ var _this15 = this;
1411
1589
  var indicator = this.getSaveIndicatorElement();
1412
1590
  if (!indicator) {
1413
1591
  return;
@@ -1423,7 +1601,7 @@ window.chatInteractionManager = function () {
1423
1601
  }
1424
1602
  this.saveIndicatorTimeout = setTimeout(function () {
1425
1603
  indicator.textContent = '';
1426
- _this1.saveIndicatorTimeout = null;
1604
+ _this15.saveIndicatorTimeout = null;
1427
1605
  }, 3000);
1428
1606
  },
1429
1607
  clearPendingSettingsSave: function clearPendingSettingsSave() {
@@ -1497,10 +1675,10 @@ window.chatInteractionManager = function () {
1497
1675
  return false;
1498
1676
  },
1499
1677
  validateSettings: function validateSettings() {
1500
- var _this10 = this;
1678
+ var _this16 = this;
1501
1679
  var isValid = true;
1502
1680
  this.getSettingInputs().forEach(function (input) {
1503
- isValid = _this10.validateSettingInput(input) && isValid;
1681
+ isValid = _this16.validateSettingInput(input) && isValid;
1504
1682
  });
1505
1683
  return isValid;
1506
1684
  },
@@ -1523,7 +1701,7 @@ window.chatInteractionManager = function () {
1523
1701
  return document.querySelectorAll('input[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["]), ' + 'select[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["]), ' + 'textarea[name^="ChatInteraction."]:not([name*=".Tools["]):not([name*=".Connections["])');
1524
1702
  },
1525
1703
  getSelectedGroupValues: function getSelectedGroupValues(groupName, fallbackSelector) {
1526
- var explicitSelections = document.querySelectorAll(".capability-checkbox[data-save-group=\"".concat(groupName, "\"]:checked"));
1704
+ var explicitSelections = document.querySelectorAll(".capability-checkbox[data-save-group=\"".concat(groupName, "\"]:checked, .capability-checkbox[data-group=\"").concat(groupName, "\"]:checked"));
1527
1705
  if (explicitSelections.length > 0) {
1528
1706
  var _values = [];
1529
1707
  explicitSelections.forEach(function (checkbox) {
@@ -1596,12 +1774,12 @@ window.chatInteractionManager = function () {
1596
1774
  }
1597
1775
  },
1598
1776
  scheduleNotificationDismiss: function scheduleNotificationDismiss(notification) {
1599
- var _this11 = this;
1777
+ var _this17 = this;
1600
1778
  if (!notification || !notification.type || !notification.autoDismissMs || notification.autoDismissMs <= 0) {
1601
1779
  return;
1602
1780
  }
1603
1781
  this.notificationDismissTimers[notification.type] = setTimeout(function () {
1604
- _this11.removeNotification(notification.type);
1782
+ _this17.removeNotification(notification.type);
1605
1783
  }, notification.autoDismissMs);
1606
1784
  },
1607
1785
  clearNotificationDismiss: function clearNotificationDismiss(notificationType) {
@@ -1641,7 +1819,7 @@ window.chatInteractionManager = function () {
1641
1819
  this.showPlaceholder();
1642
1820
  },
1643
1821
  initializeApp: function initializeApp() {
1644
- var _this12 = this;
1822
+ var _this18 = this;
1645
1823
  this.inputElement = document.querySelector(config.inputElementSelector);
1646
1824
  this.buttonElement = document.querySelector(config.sendButtonElementSelector);
1647
1825
  this.chatContainer = document.querySelector(config.chatContainerElementSelector);
@@ -1653,59 +1831,59 @@ window.chatInteractionManager = function () {
1653
1831
 
1654
1832
  // Pause auto-scroll when the user manually scrolls up during streaming.
1655
1833
  this.chatContainer.addEventListener('scroll', function () {
1656
- if (!_this12.stream) {
1834
+ if (!_this18.stream) {
1657
1835
  return;
1658
1836
  }
1659
1837
  var threshold = 30;
1660
- var atBottom = _this12.chatContainer.scrollHeight - _this12.chatContainer.clientHeight - _this12.chatContainer.scrollTop <= threshold;
1661
- _this12.autoScroll = atBottom;
1838
+ var atBottom = _this18.chatContainer.scrollHeight - _this18.chatContainer.clientHeight - _this18.chatContainer.scrollTop <= threshold;
1839
+ _this18.autoScroll = atBottom;
1662
1840
  });
1663
1841
  this.inputElement.addEventListener('keyup', function (event) {
1664
- if (_this12.stream != null) {
1842
+ if (_this18.stream != null) {
1665
1843
  return;
1666
1844
  }
1667
1845
  if (event.key === "Enter" && !event.shiftKey) {
1668
- _this12.buttonElement.click();
1846
+ _this18.buttonElement.click();
1669
1847
  }
1670
1848
  });
1671
1849
  this.inputElement.addEventListener('input', function (e) {
1672
- _this12.handleUserInput(e);
1850
+ _this18.handleUserInput(e);
1673
1851
  if (e.target.value.trim()) {
1674
- _this12.buttonElement.removeAttribute('disabled');
1852
+ _this18.buttonElement.removeAttribute('disabled');
1675
1853
  } else {
1676
- _this12.buttonElement.setAttribute('disabled', true);
1854
+ _this18.buttonElement.setAttribute('disabled', true);
1677
1855
  }
1678
1856
  });
1679
1857
  this.inputElement.addEventListener('paste', function (e) {
1680
1858
  // Use setTimeout to allow the paste to complete before checking the value
1681
1859
  setTimeout(function () {
1682
- _this12.prompt = _this12.inputElement.value;
1683
- if (_this12.inputElement.value.trim()) {
1684
- _this12.buttonElement.removeAttribute('disabled');
1860
+ _this18.prompt = _this18.inputElement.value;
1861
+ if (_this18.inputElement.value.trim()) {
1862
+ _this18.buttonElement.removeAttribute('disabled');
1685
1863
  } else {
1686
- _this12.buttonElement.setAttribute('disabled', true);
1864
+ _this18.buttonElement.setAttribute('disabled', true);
1687
1865
  }
1688
1866
  }, 0);
1689
1867
  });
1690
1868
  this.buttonElement.addEventListener('click', function () {
1691
- if (_this12.stream != null) {
1692
- _this12.stream.dispose();
1693
- _this12.stream = null;
1694
- _this12.streamingFinished();
1695
- _this12.hideTypingIndicator();
1869
+ if (_this18.stream != null) {
1870
+ _this18.stream.dispose();
1871
+ _this18.stream = null;
1872
+ _this18.streamingFinished();
1873
+ _this18.hideTypingIndicator();
1696
1874
 
1697
1875
  // Clean up: remove empty assistant message or stop streaming animation.
1698
- if (_this12.messages.length > 0) {
1699
- var lastMsg = _this12.messages[_this12.messages.length - 1];
1876
+ if (_this18.messages.length > 0) {
1877
+ var lastMsg = _this18.messages[_this18.messages.length - 1];
1700
1878
  if (lastMsg.role === 'assistant' && !lastMsg.content) {
1701
- _this12.messages.pop();
1879
+ _this18.messages.pop();
1702
1880
  } else if (lastMsg.isStreaming) {
1703
1881
  lastMsg.isStreaming = false;
1704
1882
  }
1705
1883
  }
1706
1884
  return;
1707
1885
  }
1708
- _this12.sendMessage();
1886
+ _this18.sendMessage();
1709
1887
  });
1710
1888
  var chatInteractionItems = document.getElementsByClassName('chat-interaction-history-item');
1711
1889
  for (var i = 0; i < chatInteractionItems.length; i++) {
@@ -1716,11 +1894,12 @@ window.chatInteractionManager = function () {
1716
1894
  console.error('An element with the class chat-interaction-history-item with no data-interaction-id set.');
1717
1895
  return;
1718
1896
  }
1719
- _this12.loadInteraction(itemId);
1897
+ _this18.loadInteraction(itemId);
1720
1898
  });
1721
1899
  }
1722
- for (var _i3 = 0; _i3 < config.messages.length; _i3++) {
1723
- this.addMessage(config.messages[_i3]);
1900
+ var initialMessages = Array.isArray(config.messages) ? config.messages : [];
1901
+ for (var _i4 = 0; _i4 < initialMessages.length; _i4++) {
1902
+ this.addMessage(initialMessages[_i4]);
1724
1903
  }
1725
1904
 
1726
1905
  // Delegate click for code block copy buttons.
@@ -1738,29 +1917,29 @@ window.chatInteractionManager = function () {
1738
1917
  if (codeEl) {
1739
1918
  navigator.clipboard.writeText(codeEl.textContent);
1740
1919
  var copiedText = config.codeCopiedText || 'Copied!';
1741
- btn.innerHTML = '<span class="fa-solid fa-check"></span> ' + copiedText;
1920
+ btn.innerHTML = '<i class="fa-solid fa-check"></i> ' + copiedText;
1742
1921
  setTimeout(function () {
1743
- btn.innerHTML = '<span class="fa-regular fa-copy"></span>';
1922
+ btn.innerHTML = '<i class="fa-regular fa-copy"></i>';
1744
1923
  }, 2000);
1745
1924
  }
1746
1925
  });
1747
1926
  }
1748
1927
  document.addEventListener('input', function (event) {
1749
1928
  if (event.target.matches('.setting-input[data-setting]')) {
1750
- _this12.validateSettingInput(event.target);
1751
- _this12.queueSettingsSave();
1929
+ _this18.validateSettingInput(event.target);
1930
+ _this18.queueSettingsSave();
1752
1931
  }
1753
1932
  });
1754
1933
  document.addEventListener('change', function (event) {
1755
- if (event.target.matches('.setting-input[data-setting], .capability-checkbox[data-save-group], .group-toggle, .ci-agent-global-toggle')) {
1934
+ if (event.target.matches('.setting-input[data-setting], .capability-checkbox[data-save-group], .capability-checkbox[data-group], .group-toggle, .ci-agent-global-toggle')) {
1756
1935
  if (event.target.matches('.setting-input[data-setting]')) {
1757
- _this12.validateSettingInput(event.target);
1936
+ _this18.validateSettingInput(event.target);
1758
1937
  }
1759
- _this12.queueSettingsSave();
1938
+ _this18.queueSettingsSave();
1760
1939
  return;
1761
1940
  }
1762
1941
  if (event.target.closest('.prompt-template-parameters-input, .prompt-template-id-input')) {
1763
- _this12.queueSettingsSave();
1942
+ _this18.queueSettingsSave();
1764
1943
  }
1765
1944
  });
1766
1945
  document.addEventListener('click', function (event) {
@@ -1768,7 +1947,7 @@ window.chatInteractionManager = function () {
1768
1947
  return;
1769
1948
  }
1770
1949
  setTimeout(function () {
1771
- _this12.queueSettingsSave();
1950
+ _this18.queueSettingsSave();
1772
1951
  }, 0);
1773
1952
  });
1774
1953
 
@@ -1778,7 +1957,7 @@ window.chatInteractionManager = function () {
1778
1957
  clearHistoryBtn.addEventListener('click', function () {
1779
1958
  var itemId = clearHistoryBtn.getAttribute('data-interaction-id');
1780
1959
  if (itemId) {
1781
- _this12.clearHistory(itemId);
1960
+ _this18.clearHistory(itemId);
1782
1961
  }
1783
1962
  });
1784
1963
  }
@@ -1789,7 +1968,7 @@ window.chatInteractionManager = function () {
1789
1968
  if (this.micButton) {
1790
1969
  this.micButton.style.display = '';
1791
1970
  this.micButton.addEventListener('click', function () {
1792
- _this12.toggleRecording();
1971
+ _this18.toggleRecording();
1793
1972
  });
1794
1973
  }
1795
1974
  }
@@ -1799,7 +1978,7 @@ window.chatInteractionManager = function () {
1799
1978
  this.conversationButton = document.querySelector(config.conversationButtonElementSelector);
1800
1979
  if (this.conversationButton) {
1801
1980
  this.conversationButton.addEventListener('click', function () {
1802
- _this12.toggleConversationMode();
1981
+ _this18.toggleConversationMode();
1803
1982
  });
1804
1983
  }
1805
1984
  }
@@ -1817,29 +1996,38 @@ window.chatInteractionManager = function () {
1817
1996
  },
1818
1997
  clearHistory: function clearHistory(itemId) {
1819
1998
  var self = this;
1820
- confirmDialog({
1821
- title: config.clearHistoryTitle,
1822
- message: config.clearHistoryMessage,
1823
- okText: config.clearHistoryOkText,
1824
- cancelText: config.clearHistoryCancelText,
1825
- callback: function callback(confirmed) {
1826
- if (confirmed) {
1827
- // Cancel any active stream before clearing history.
1828
- if (self.stream) {
1829
- self.stream.dispose();
1830
- self.stream = null;
1831
- self.hideTypingIndicator();
1832
- self.streamingFinished();
1999
+ var clearHistoryConfirmed = function clearHistoryConfirmed() {
2000
+ // Cancel any active stream before clearing history.
2001
+ if (self.stream) {
2002
+ self.stream.dispose();
2003
+ self.stream = null;
2004
+ self.hideTypingIndicator();
2005
+ self.streamingFinished();
2006
+ }
2007
+ self.connection.invoke("ClearHistory", itemId)["catch"](function (err) {
2008
+ return console.error('Error clearing history:', err);
2009
+ });
2010
+ };
2011
+ if (typeof confirmDialog === 'function') {
2012
+ confirmDialog({
2013
+ title: config.clearHistoryTitle,
2014
+ message: config.clearHistoryMessage,
2015
+ okText: config.clearHistoryOkText,
2016
+ cancelText: config.clearHistoryCancelText,
2017
+ callback: function callback(confirmed) {
2018
+ if (confirmed) {
2019
+ clearHistoryConfirmed();
1833
2020
  }
1834
- self.connection.invoke("ClearHistory", itemId)["catch"](function (err) {
1835
- return console.error('Error clearing history:', err);
1836
- });
1837
2021
  }
1838
- }
1839
- });
2022
+ });
2023
+ return;
2024
+ }
2025
+ if (window.confirm(config.clearHistoryMessage || 'Clear all messages?')) {
2026
+ clearHistoryConfirmed();
2027
+ }
1840
2028
  },
1841
2029
  debouncedSaveSettings: function debouncedSaveSettings() {
1842
- var _this13 = this;
2030
+ var _this19 = this;
1843
2031
  // Clear any existing timeout to reset the debounce timer
1844
2032
  this.clearPendingSettingsSave();
1845
2033
 
@@ -1850,11 +2038,11 @@ window.chatInteractionManager = function () {
1850
2038
 
1851
2039
  // Set a new timeout to save after 850ms of no changes
1852
2040
  this.saveSettingsTimeout = setTimeout(function () {
1853
- if (_this13.settingsDirty) {
1854
- _this13.saveSettings();
1855
- _this13.settingsDirty = false;
2041
+ if (_this19.settingsDirty) {
2042
+ _this19.saveSettings();
2043
+ _this19.settingsDirty = false;
1856
2044
  }
1857
- _this13.saveSettingsTimeout = null;
2045
+ _this19.saveSettingsTimeout = null;
1858
2046
  }, 850);
1859
2047
  },
1860
2048
  getSelectedToolNames: function getSelectedToolNames() {
@@ -1870,7 +2058,7 @@ window.chatInteractionManager = function () {
1870
2058
  return this.getSelectedGroupValues('agentNames', 'input[type="checkbox"][name$="].IsSelected"][name^="ChatInteraction.Agents["]:checked');
1871
2059
  },
1872
2060
  saveSettings: function saveSettings() {
1873
- var _this14 = this;
2061
+ var _this20 = this;
1874
2062
  var itemId = this.getItemId();
1875
2063
  if (!itemId) {
1876
2064
  return Promise.resolve();
@@ -1915,7 +2103,7 @@ window.chatInteractionManager = function () {
1915
2103
  }
1916
2104
  return this.connection.invoke("SaveSettings", itemId, settings)["catch"](function (err) {
1917
2105
  console.error('Error saving settings:', err);
1918
- _this14.showSaveIndicator('Save failed', 'text-danger');
2106
+ _this20.showSaveIndicator('Save failed', 'text-danger');
1919
2107
  });
1920
2108
  },
1921
2109
  flushPendingSave: function flushPendingSave() {
@@ -1941,11 +2129,48 @@ window.chatInteractionManager = function () {
1941
2129
  this.setItemId(itemId);
1942
2130
  this.isInteractionStarted = true;
1943
2131
  },
1944
- copyResponse: function copyResponse(message) {
1945
- navigator.clipboard.writeText(message);
2132
+ clearCopiedMessageState: function clearCopiedMessageState() {
2133
+ if (this.copyResetTimeoutId) {
2134
+ window.clearTimeout(this.copyResetTimeoutId);
2135
+ this.copyResetTimeoutId = null;
2136
+ }
2137
+ if (this.activeCopyButton) {
2138
+ this.setCopyButtonState(this.activeCopyButton, false);
2139
+ this.activeCopyButton = null;
2140
+ }
2141
+ this.copiedMessageIndex = -1;
2142
+ },
2143
+ copyResponse: function copyResponse(message, index, event) {
2144
+ var _ref21,
2145
+ _message$copyContent,
2146
+ _event$target,
2147
+ _event$target$closest,
2148
+ _this21 = this;
2149
+ var text = message && _typeof(message) === 'object' ? (_ref21 = (_message$copyContent = message.copyContent) !== null && _message$copyContent !== void 0 ? _message$copyContent : message.content) !== null && _ref21 !== void 0 ? _ref21 : '' : message !== null && message !== void 0 ? message : '';
2150
+ var button = (event === null || event === void 0 ? void 0 : event.currentTarget) || (event === null || event === void 0 || (_event$target = event.target) === null || _event$target === void 0 || (_event$target$closest = _event$target.closest) === null || _event$target$closest === void 0 ? void 0 : _event$target$closest.call(_event$target, '[data-copy-message-index]')) || null;
2151
+ navigator.clipboard.writeText(text).then(function () {
2152
+ _this21.clearCopiedMessageState();
2153
+ _this21.copiedMessageIndex = typeof index === 'number' ? index : -1;
2154
+ _this21.activeCopyButton = button;
2155
+ if (button) {
2156
+ _this21.setCopyButtonState(button, true);
2157
+ } else {
2158
+ _this21.$nextTick(function () {
2159
+ return _this21.updateCopyButtons();
2160
+ });
2161
+ }
2162
+ _this21.copyResetTimeoutId = window.setTimeout(function () {
2163
+ _this21.clearCopiedMessageState();
2164
+ _this21.$nextTick(function () {
2165
+ return _this21.updateCopyButtons();
2166
+ });
2167
+ }, Number(config.copyResetDelayMs) || 2000);
2168
+ })["catch"](function (err) {
2169
+ return console.error('Failed to copy response:', err);
2170
+ });
1946
2171
  },
1947
2172
  startRecording: function startRecording() {
1948
- var _this15 = this;
2173
+ var _this22 = this;
1949
2174
  if (this.isRecording || !this.connection) {
1950
2175
  return;
1951
2176
  }
@@ -1957,16 +2182,16 @@ window.chatInteractionManager = function () {
1957
2182
  }
1958
2183
  }).then(function (stream) {
1959
2184
  var mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : 'audio/webm';
1960
- _this15.mediaRecorder = new MediaRecorder(stream, {
2185
+ _this22.mediaRecorder = new MediaRecorder(stream, {
1961
2186
  mimeType: mimeType,
1962
2187
  audioBitsPerSecond: 128000
1963
2188
  });
1964
- _this15.preRecordingPrompt = _this15.prompt;
1965
- _this15._audioInputSent = false;
2189
+ _this22.preRecordingPrompt = _this22.prompt;
2190
+ _this22._audioInputSent = false;
1966
2191
  var subject = new signalR.Subject();
1967
- var itemId = _this15.getItemId();
2192
+ var itemId = _this22.getItemId();
1968
2193
  var pendingChunk = Promise.resolve();
1969
- _this15.mediaRecorder.addEventListener('dataavailable', function (e) {
2194
+ _this22.mediaRecorder.addEventListener('dataavailable', function (e) {
1970
2195
  if (e.data && e.data.size > 0) {
1971
2196
  pendingChunk = pendingChunk.then(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
1972
2197
  var data, uint8Array, binaryString, base64;
@@ -1990,7 +2215,7 @@ window.chatInteractionManager = function () {
1990
2215
  })));
1991
2216
  }
1992
2217
  });
1993
- _this15.mediaRecorder.addEventListener('stop', function () {
2218
+ _this22.mediaRecorder.addEventListener('stop', function () {
1994
2219
  stream.getTracks().forEach(function (track) {
1995
2220
  return track.stop();
1996
2221
  });
@@ -1999,10 +2224,10 @@ window.chatInteractionManager = function () {
1999
2224
  });
2000
2225
  });
2001
2226
  var language = navigator.language || document.documentElement.lang || 'en-US';
2002
- _this15.connection.send("SendAudioStream", itemId, subject, mimeType, language);
2003
- _this15.mediaRecorder.start(250);
2004
- _this15.isRecording = true;
2005
- _this15.updateMicButton();
2227
+ _this22.connection.send("SendAudioStream", itemId, subject, mimeType, language);
2228
+ _this22.mediaRecorder.start(250);
2229
+ _this22.isRecording = true;
2230
+ _this22.updateMicButton();
2006
2231
  })["catch"](function (err) {
2007
2232
  console.error('Microphone access denied:', err);
2008
2233
  });
@@ -2028,10 +2253,10 @@ window.chatInteractionManager = function () {
2028
2253
  }
2029
2254
  if (this.isRecording) {
2030
2255
  this.micButton.classList.add('stt-recording');
2031
- this.micButton.innerHTML = '<span class="fa-solid fa-stop"></span>';
2256
+ this.micButton.innerHTML = '<i class="fa-solid fa-stop"></i>';
2032
2257
  } else {
2033
2258
  this.micButton.classList.remove('stt-recording');
2034
- this.micButton.innerHTML = '<span class="fa-solid fa-microphone"></span>';
2259
+ this.micButton.innerHTML = '<i class="fa-solid fa-microphone"></i>';
2035
2260
  }
2036
2261
  }
2037
2262
  },
@@ -2053,18 +2278,29 @@ window.chatInteractionManager = function () {
2053
2278
  this.inputElement.placeholder = '';
2054
2279
  }
2055
2280
  }
2281
+ },
2282
+ copiedMessageIndex: function copiedMessageIndex() {
2283
+ var _this23 = this;
2284
+ this.$nextTick(function () {
2285
+ return _this23.updateCopyButtons();
2286
+ });
2056
2287
  }
2057
2288
  },
2058
2289
  mounted: function mounted() {
2059
- var _this16 = this;
2290
+ var _this24 = this;
2060
2291
  _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
2061
2292
  return _regenerator().w(function (_context5) {
2062
2293
  while (1) switch (_context5.n) {
2063
2294
  case 0:
2064
2295
  _context5.n = 1;
2065
- return _this16.startConnection();
2296
+ return _this24.startConnection();
2066
2297
  case 1:
2067
- _this16.initializeApp();
2298
+ _this24.initializeApp();
2299
+ _this24.$nextTick(function () {
2300
+ _this24.updateCopyButtons();
2301
+ refreshFontAwesomeIcons(_this24.$el);
2302
+ _this24.fontAwesomeObserver = observeFontAwesomeIcons(_this24.$el);
2303
+ });
2068
2304
  case 2:
2069
2305
  return _context5.a(2);
2070
2306
  }
@@ -2076,6 +2312,11 @@ window.chatInteractionManager = function () {
2076
2312
  beforeUnmount: function beforeUnmount() {
2077
2313
  window.removeEventListener('beforeunload', this.handleBeforeUnload);
2078
2314
  window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
2315
+ if (this.fontAwesomeObserver) {
2316
+ this.fontAwesomeObserver.disconnect();
2317
+ this.fontAwesomeObserver = null;
2318
+ }
2319
+ this.clearCopiedMessageState();
2079
2320
  this.stopAudio(false);
2080
2321
  if (this.stream) {
2081
2322
  this.stream.dispose();
@@ -2089,8 +2330,666 @@ window.chatInteractionManager = function () {
2089
2330
  }).mount(config.appElementSelector);
2090
2331
  return app;
2091
2332
  };
2333
+ var autoInitializeSelector = '[data-chat-interaction-config]';
2334
+ function parseJsonAttribute(element, attributeName, description) {
2335
+ var rawValue = element.getAttribute(attributeName);
2336
+ if (!rawValue) {
2337
+ return null;
2338
+ }
2339
+ try {
2340
+ return JSON.parse(rawValue);
2341
+ } catch (error) {
2342
+ console.error('Failed to parse ' + description + ' JSON.', error);
2343
+ return null;
2344
+ }
2345
+ }
2346
+ function initializeFromElement(element) {
2347
+ if (!element || element.dataset.chatInteractionInitialized === 'true') {
2348
+ return element ? element.__chatInteractionApp || null : null;
2349
+ }
2350
+ var config = parseJsonAttribute(element, 'data-chat-interaction-config', 'chat interaction config');
2351
+ if (!config) {
2352
+ return null;
2353
+ }
2354
+ var app = initialize(config);
2355
+ if (!app) {
2356
+ return null;
2357
+ }
2358
+ element.dataset.chatInteractionInitialized = 'true';
2359
+ element.__chatInteractionApp = app;
2360
+ return app;
2361
+ }
2362
+ function scanForAutoInitialization(root) {
2363
+ if (!root || typeof root.querySelectorAll !== 'function') {
2364
+ return;
2365
+ }
2366
+ if (typeof root.matches === 'function' && root.matches(autoInitializeSelector)) {
2367
+ initializeFromElement(root);
2368
+ }
2369
+ root.querySelectorAll(autoInitializeSelector).forEach(initializeFromElement);
2370
+ }
2371
+ function startAutoInitialization() {
2372
+ scanForAutoInitialization(document);
2373
+ if (typeof MutationObserver === 'undefined') {
2374
+ return;
2375
+ }
2376
+ var observer = new MutationObserver(function (mutations) {
2377
+ mutations.forEach(function (mutation) {
2378
+ mutation.addedNodes.forEach(function (node) {
2379
+ if (node && node.nodeType === 1) {
2380
+ scanForAutoInitialization(node);
2381
+ }
2382
+ });
2383
+ });
2384
+ });
2385
+ observer.observe(document.body, {
2386
+ childList: true,
2387
+ subtree: true
2388
+ });
2389
+ }
2390
+ if (document.readyState === 'loading') {
2391
+ document.addEventListener('DOMContentLoaded', startAutoInitialization, {
2392
+ once: true
2393
+ });
2394
+ } else {
2395
+ startAutoInitialization();
2396
+ }
2397
+ return {
2398
+ initialize: initialize,
2399
+ initializeFromElement: initializeFromElement
2400
+ };
2401
+ }();
2402
+ window.chatInteractionDocumentManager = function () {
2403
+ var managerStateKey = '__chatInteractionDocumentManagerState';
2404
+ function normalizeDocumentInfo(document) {
2405
+ if (!document || _typeof(document) !== 'object') {
2406
+ return null;
2407
+ }
2408
+ return {
2409
+ documentId: document.documentId || document.DocumentId || '',
2410
+ fileName: document.fileName || document.FileName || '',
2411
+ fileSize: document.fileSize || document.FileSize || 0
2412
+ };
2413
+ }
2414
+ function formatFileSize(bytes) {
2415
+ if (!bytes || bytes < 1024) {
2416
+ return (bytes || 0) + ' B';
2417
+ }
2418
+ if (bytes < 1024 * 1024) {
2419
+ return (bytes / 1024).toFixed(1) + ' KB';
2420
+ }
2421
+ return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
2422
+ }
2423
+ function getDocumentKey(fileName, fileSize) {
2424
+ return (fileName || '').trim().toLowerCase() + '::' + (fileSize || 0);
2425
+ }
2426
+ function isDuplicateFile(file, knownKeys) {
2427
+ return knownKeys.has(getDocumentKey(file.name, file.size));
2428
+ }
2429
+ function getDocumentsFromDom(container) {
2430
+ if (!container) {
2431
+ return [];
2432
+ }
2433
+ return Array.from(container.querySelectorAll('[data-chat-document-id]')).map(function (element) {
2434
+ return normalizeDocumentInfo({
2435
+ documentId: element.dataset.chatDocumentId,
2436
+ fileName: element.dataset.chatDocumentName,
2437
+ fileSize: Number(element.dataset.chatDocumentSize || 0)
2438
+ });
2439
+ }).filter(function (document) {
2440
+ return document && document.documentId;
2441
+ });
2442
+ }
2443
+ function initialize(config) {
2444
+ if (!config || !config.itemId) {
2445
+ return;
2446
+ }
2447
+ var fileInput = document.getElementById('chat-doc-upload');
2448
+ var documentsList = document.getElementById('chat-documents-list');
2449
+ var status = document.getElementById('chat-doc-upload-status');
2450
+ var progressContainer = document.getElementById('chat-doc-upload-progress');
2451
+ var progressBar = document.getElementById('chat-doc-upload-progress-bar');
2452
+ var uploadQueue = document.getElementById('chat-doc-upload-queue');
2453
+ if (!fileInput || !documentsList || !status || !progressContainer || !progressBar || !uploadQueue) {
2454
+ return;
2455
+ }
2456
+ var previousState = fileInput[managerStateKey];
2457
+ if (previousState && typeof previousState.dispose === 'function') {
2458
+ previousState.dispose();
2459
+ }
2460
+ var interactionDocuments = (Array.isArray(config.existingDocuments) ? config.existingDocuments : []).map(normalizeDocumentInfo).filter(function (document) {
2461
+ return document && document.documentId;
2462
+ });
2463
+ if (interactionDocuments.length === 0) {
2464
+ interactionDocuments = getDocumentsFromDom(documentsList);
2465
+ }
2466
+ var uploadItems = [];
2467
+ var isUploadingDocuments = false;
2468
+ function createTextElement(tagName, className, text) {
2469
+ var element = document.createElement(tagName);
2470
+ if (className) {
2471
+ element.className = className;
2472
+ }
2473
+ element.textContent = text;
2474
+ return element;
2475
+ }
2476
+ function renderDocuments() {
2477
+ documentsList.innerHTML = '';
2478
+ if (interactionDocuments.length === 0) {
2479
+ documentsList.appendChild(createTextElement('div', 'text-muted small', 'No documents uploaded yet.'));
2480
+ return;
2481
+ }
2482
+ interactionDocuments.forEach(function (documentInfo) {
2483
+ var row = window.document.createElement('div');
2484
+ row.className = 'd-flex justify-content-between align-items-start gap-2 border rounded px-2 py-2 bg-white chat-document-row';
2485
+ row.dataset.chatDocumentId = documentInfo.documentId;
2486
+ row.dataset.chatDocumentName = documentInfo.fileName;
2487
+ row.dataset.chatDocumentSize = documentInfo.fileSize;
2488
+ var details = window.document.createElement('div');
2489
+ details.className = 'me-2 min-w-0';
2490
+ var name = createTextElement('div', 'fw-semibold small', documentInfo.fileName || 'Document');
2491
+ var icon = window.document.createElement('i');
2492
+ icon.className = 'bi bi-file-earmark-text me-1';
2493
+ name.prepend(icon);
2494
+ var size = createTextElement('div', 'text-muted small', formatFileSize(documentInfo.fileSize));
2495
+ details.appendChild(name);
2496
+ details.appendChild(size);
2497
+ var removeButton = createTextElement('button', 'btn btn-sm btn-outline-danger remove-chat-document-btn', ' Remove');
2498
+ removeButton.type = 'button';
2499
+ removeButton.dataset.documentId = documentInfo.documentId;
2500
+ var removeIcon = window.document.createElement('i');
2501
+ removeIcon.className = 'bi bi-trash';
2502
+ removeButton.prepend(removeIcon);
2503
+ removeButton.addEventListener('click', function () {
2504
+ return removeDocument(documentInfo.documentId);
2505
+ });
2506
+ row.appendChild(details);
2507
+ row.appendChild(removeButton);
2508
+ documentsList.appendChild(row);
2509
+ });
2510
+ }
2511
+ function showUploadStatus(message, cssClass) {
2512
+ if (!message) {
2513
+ status.textContent = '';
2514
+ status.className = 'small mt-2 d-none';
2515
+ return;
2516
+ }
2517
+ status.textContent = message;
2518
+ status.className = 'small mt-2 ' + (cssClass || 'text-muted');
2519
+ }
2520
+ function showUploadProgress(progress, message, cssClass) {
2521
+ if (progress === null || progress === undefined) {
2522
+ progressContainer.className = 'progress mt-2 d-none';
2523
+ progressContainer.setAttribute('aria-valuenow', '0');
2524
+ progressBar.className = 'progress-bar progress-bar-striped progress-bar-animated';
2525
+ progressBar.style.width = '0%';
2526
+ progressBar.textContent = '0%';
2527
+ return;
2528
+ }
2529
+ var roundedProgress = Math.max(0, Math.min(100, Math.round(progress)));
2530
+ progressContainer.className = 'progress mt-2';
2531
+ progressContainer.setAttribute('aria-valuenow', roundedProgress.toString());
2532
+ progressBar.className = 'progress-bar ' + (cssClass || 'progress-bar-striped progress-bar-animated');
2533
+ progressBar.style.width = roundedProgress + '%';
2534
+ progressBar.textContent = message || roundedProgress + '%';
2535
+ }
2536
+ function getUploadStatePresentation(state) {
2537
+ switch (state) {
2538
+ case 'uploaded':
2539
+ return {
2540
+ label: 'Uploaded',
2541
+ badgeClass: 'text-bg-success',
2542
+ progressClass: 'bg-success'
2543
+ };
2544
+ case 'failed':
2545
+ return {
2546
+ label: 'Failed',
2547
+ badgeClass: 'text-bg-danger',
2548
+ progressClass: 'bg-danger'
2549
+ };
2550
+ case 'uploading':
2551
+ return {
2552
+ label: 'Uploading',
2553
+ badgeClass: 'text-bg-warning',
2554
+ progressClass: 'bg-warning progress-bar-striped progress-bar-animated'
2555
+ };
2556
+ default:
2557
+ return {
2558
+ label: 'Queued',
2559
+ badgeClass: 'text-bg-secondary',
2560
+ progressClass: 'bg-secondary progress-bar-striped progress-bar-animated'
2561
+ };
2562
+ }
2563
+ }
2564
+ function formatUploadMessage(item) {
2565
+ if (item.status === 'failed' && item.error) {
2566
+ return item.error;
2567
+ }
2568
+ if (item.status === 'uploaded') {
2569
+ return 'Upload completed successfully.';
2570
+ }
2571
+ if (item.status === 'uploading') {
2572
+ return item.progress + '% uploaded';
2573
+ }
2574
+ return 'Waiting to upload...';
2575
+ }
2576
+ function renderUploadQueue() {
2577
+ uploadQueue.innerHTML = '';
2578
+ uploadItems.forEach(function (item) {
2579
+ var presentation = getUploadStatePresentation(item.status);
2580
+ var card = document.createElement('div');
2581
+ card.className = 'border rounded px-2 py-2 bg-white';
2582
+ var header = document.createElement('div');
2583
+ header.className = 'd-flex justify-content-between align-items-start gap-2';
2584
+ var fileDetails = document.createElement('div');
2585
+ fileDetails.className = 'flex-grow-1 min-w-0';
2586
+ fileDetails.appendChild(createTextElement('div', 'fw-semibold small', item.fileName));
2587
+ fileDetails.appendChild(createTextElement('div', 'text-muted small', formatFileSize(item.fileSize)));
2588
+ var badge = createTextElement('span', 'badge ' + presentation.badgeClass, presentation.label);
2589
+ header.appendChild(fileDetails);
2590
+ header.appendChild(badge);
2591
+ var progress = document.createElement('div');
2592
+ progress.className = 'progress mt-2';
2593
+ progress.setAttribute('role', 'progressbar');
2594
+ progress.setAttribute('aria-valuemin', '0');
2595
+ progress.setAttribute('aria-valuemax', '100');
2596
+ progress.setAttribute('aria-valuenow', item.progress.toString());
2597
+ var progressState = document.createElement('div');
2598
+ progressState.className = 'progress-bar ' + presentation.progressClass;
2599
+ progressState.style.width = item.progress + '%';
2600
+ progressState.textContent = item.progress + '%';
2601
+ progress.appendChild(progressState);
2602
+ var message = createTextElement('div', item.status === 'failed' ? 'small text-danger mt-2' : 'small text-muted mt-2', formatUploadMessage(item));
2603
+ card.appendChild(header);
2604
+ card.appendChild(progress);
2605
+ card.appendChild(message);
2606
+ uploadQueue.appendChild(card);
2607
+ });
2608
+ }
2609
+ function createUploadItem(file, index) {
2610
+ return {
2611
+ id: file.name + '::' + file.size + '::' + file.lastModified + '::' + index + '::' + Date.now(),
2612
+ fileName: file.name,
2613
+ fileSize: file.size,
2614
+ status: 'queued',
2615
+ progress: 0,
2616
+ error: null
2617
+ };
2618
+ }
2619
+ function updateUploadItem(itemId, updates) {
2620
+ uploadItems = uploadItems.map(function (item) {
2621
+ return item.id === itemId ? Object.assign({}, item, updates) : item;
2622
+ });
2623
+ renderUploadQueue();
2624
+ }
2625
+ function removeUploadItems(predicate) {
2626
+ uploadItems = uploadItems.filter(function (item) {
2627
+ return !predicate(item);
2628
+ });
2629
+ renderUploadQueue();
2630
+ }
2631
+ function uploadSingleDocument(file, itemIdToUpdate, fileIndex, totalFiles) {
2632
+ return new Promise(function (resolve, reject) {
2633
+ var formData = new FormData();
2634
+ formData.append('chatInteractionId', config.itemId);
2635
+ formData.append('files', file);
2636
+ var xhr = new XMLHttpRequest();
2637
+ xhr.open('POST', config.uploadDocumentUrl, true);
2638
+ xhr.upload.addEventListener('progress', function (event) {
2639
+ if (!event.lengthComputable) {
2640
+ return;
2641
+ }
2642
+ var fileProgress = Math.round(event.loaded / event.total * 100);
2643
+ updateUploadItem(itemIdToUpdate, {
2644
+ status: 'uploading',
2645
+ progress: fileProgress
2646
+ });
2647
+ var overallProgress = (fileIndex + event.loaded / event.total) / totalFiles * 100;
2648
+ showUploadProgress(overallProgress, 'Uploading ' + (fileIndex + 1) + ' of ' + totalFiles, 'progress-bar-striped progress-bar-animated');
2649
+ });
2650
+ xhr.addEventListener('load', function () {
2651
+ if (xhr.status >= 200 && xhr.status < 300) {
2652
+ try {
2653
+ resolve(JSON.parse(xhr.responseText));
2654
+ } catch (error) {
2655
+ reject(new Error('Upload failed: invalid server response.'));
2656
+ }
2657
+ return;
2658
+ }
2659
+ reject(new Error((xhr.responseText || 'Upload failed.').trim()));
2660
+ });
2661
+ xhr.addEventListener('error', function () {
2662
+ reject(new Error('Upload failed. Please check your connection and try again.'));
2663
+ });
2664
+ xhr.send(formData);
2665
+ });
2666
+ }
2667
+ function uploadDocuments(_x) {
2668
+ return _uploadDocuments.apply(this, arguments);
2669
+ }
2670
+ function _uploadDocuments() {
2671
+ _uploadDocuments = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(files) {
2672
+ var filesToUpload, duplicateItems, knownDocumentKeys, pendingItems, uploadedCount, failedUploads, i, file, pendingItem, result, uploaded, failed, missingUploadMessage, failedMessage, errorMessage, _t2, _t3;
2673
+ return _regenerator().w(function (_context6) {
2674
+ while (1) switch (_context6.p = _context6.n) {
2675
+ case 0:
2676
+ if (!(!config.uploadDocumentUrl || !files || files.length === 0)) {
2677
+ _context6.n = 1;
2678
+ break;
2679
+ }
2680
+ return _context6.a(2);
2681
+ case 1:
2682
+ if (!isUploadingDocuments) {
2683
+ _context6.n = 2;
2684
+ break;
2685
+ }
2686
+ showUploadStatus('A document upload is already in progress.', 'text-warning');
2687
+ return _context6.a(2);
2688
+ case 2:
2689
+ isUploadingDocuments = true;
2690
+ filesToUpload = [];
2691
+ duplicateItems = [];
2692
+ knownDocumentKeys = new Set(interactionDocuments.map(function (document) {
2693
+ return getDocumentKey(document.fileName, document.fileSize);
2694
+ }));
2695
+ Array.from(files).forEach(function (file) {
2696
+ if (isDuplicateFile(file, knownDocumentKeys)) {
2697
+ duplicateItems.push(file);
2698
+ return;
2699
+ }
2700
+ knownDocumentKeys.add(getDocumentKey(file.name, file.size));
2701
+ filesToUpload.push(file);
2702
+ });
2703
+ if (duplicateItems.length > 0) {
2704
+ uploadItems = uploadItems.concat(duplicateItems.map(function (file, index) {
2705
+ return Object.assign(createUploadItem(file, index), {
2706
+ status: 'failed',
2707
+ progress: 100,
2708
+ error: 'This document is already attached.'
2709
+ });
2710
+ }));
2711
+ renderUploadQueue();
2712
+ }
2713
+ if (!(filesToUpload.length === 0)) {
2714
+ _context6.n = 3;
2715
+ break;
2716
+ }
2717
+ isUploadingDocuments = false;
2718
+ showUploadStatus(duplicateItems.map(function (file) {
2719
+ return file.name + ': This document is already attached.';
2720
+ }).join(' | '), 'text-warning');
2721
+ showUploadProgress(null);
2722
+ return _context6.a(2);
2723
+ case 3:
2724
+ pendingItems = filesToUpload.map(createUploadItem);
2725
+ uploadItems = uploadItems.concat(pendingItems);
2726
+ renderUploadQueue();
2727
+ showUploadProgress(0, 'Preparing upload...', 'progress-bar-striped progress-bar-animated');
2728
+ fileInput.disabled = true;
2729
+ _context6.p = 4;
2730
+ uploadedCount = 0;
2731
+ failedUploads = duplicateItems.map(function (file) {
2732
+ return file.name + ': This document is already attached.';
2733
+ });
2734
+ i = 0;
2735
+ case 5:
2736
+ if (!(i < filesToUpload.length)) {
2737
+ _context6.n = 10;
2738
+ break;
2739
+ }
2740
+ file = filesToUpload[i];
2741
+ pendingItem = pendingItems[i];
2742
+ updateUploadItem(pendingItem.id, {
2743
+ status: 'uploading',
2744
+ progress: 0,
2745
+ error: null
2746
+ });
2747
+ showUploadStatus('Uploading ' + (i + 1) + ' of ' + filesToUpload.length + ' document(s)...', 'text-warning');
2748
+ _context6.p = 6;
2749
+ _context6.n = 7;
2750
+ return uploadSingleDocument(file, pendingItem.id, i, filesToUpload.length);
2751
+ case 7:
2752
+ result = _context6.v;
2753
+ uploaded = (Array.isArray(result.uploaded) ? result.uploaded : []).map(normalizeDocumentInfo).filter(function (document) {
2754
+ return document && document.documentId;
2755
+ });
2756
+ failed = Array.isArray(result.failed) ? result.failed : [];
2757
+ if (uploaded.length > 0) {
2758
+ uploadedCount += uploaded.length;
2759
+ interactionDocuments = interactionDocuments.concat(uploaded);
2760
+ updateUploadItem(pendingItem.id, {
2761
+ status: 'uploaded',
2762
+ progress: 100,
2763
+ error: null
2764
+ });
2765
+ } else {
2766
+ missingUploadMessage = failed.length > 0 ? failed.map(function (entry) {
2767
+ return entry.fileName + ': ' + entry.error;
2768
+ }).join(' | ') : 'The server did not confirm that the file was uploaded.';
2769
+ if (failed.length === 0) {
2770
+ failedUploads.push(missingUploadMessage);
2771
+ }
2772
+ updateUploadItem(pendingItem.id, {
2773
+ status: 'failed',
2774
+ progress: 100,
2775
+ error: missingUploadMessage
2776
+ });
2777
+ }
2778
+ if (failed.length > 0) {
2779
+ failedMessage = failed.map(function (entry) {
2780
+ return entry.fileName + ': ' + entry.error;
2781
+ }).join(' | ');
2782
+ failedUploads.push(failedMessage);
2783
+ updateUploadItem(pendingItem.id, {
2784
+ status: 'failed',
2785
+ progress: 100,
2786
+ error: failedMessage
2787
+ });
2788
+ }
2789
+ _context6.n = 9;
2790
+ break;
2791
+ case 8:
2792
+ _context6.p = 8;
2793
+ _t2 = _context6.v;
2794
+ errorMessage = _t2 && _t2.message ? _t2.message : 'Upload failed. Please try again.';
2795
+ console.error('Upload failed:', _t2);
2796
+ failedUploads.push(file.name + ': ' + errorMessage);
2797
+ updateUploadItem(pendingItem.id, {
2798
+ status: 'failed',
2799
+ progress: pendingItem.progress || 0,
2800
+ error: errorMessage
2801
+ });
2802
+ case 9:
2803
+ i++;
2804
+ _context6.n = 5;
2805
+ break;
2806
+ case 10:
2807
+ renderDocuments();
2808
+ if (!(failedUploads.length > 0)) {
2809
+ _context6.n = 11;
2810
+ break;
2811
+ }
2812
+ removeUploadItems(function (item) {
2813
+ return item.status === 'uploaded';
2814
+ });
2815
+ showUploadStatus((uploadedCount > 0 ? 'Uploaded ' + uploadedCount + ' document(s). ' : '') + failedUploads.join(' | '), uploadedCount > 0 ? 'text-warning' : 'text-danger');
2816
+ showUploadProgress(null);
2817
+ return _context6.a(2);
2818
+ case 11:
2819
+ removeUploadItems(function () {
2820
+ return true;
2821
+ });
2822
+ showUploadStatus('Uploaded ' + uploadedCount + ' document(s).', 'text-success');
2823
+ showUploadProgress(null);
2824
+ _context6.n = 13;
2825
+ break;
2826
+ case 12:
2827
+ _context6.p = 12;
2828
+ _t3 = _context6.v;
2829
+ console.error('Upload failed:', _t3);
2830
+ showUploadStatus('Upload failed. Please try again.', 'text-danger');
2831
+ showUploadProgress(null);
2832
+ case 13:
2833
+ _context6.p = 13;
2834
+ isUploadingDocuments = false;
2835
+ fileInput.disabled = false;
2836
+ fileInput.value = '';
2837
+ return _context6.f(13);
2838
+ case 14:
2839
+ return _context6.a(2);
2840
+ }
2841
+ }, _callee6, null, [[6, 8], [4, 12, 13, 14]]);
2842
+ }));
2843
+ return _uploadDocuments.apply(this, arguments);
2844
+ }
2845
+ function removeDocument(_x2) {
2846
+ return _removeDocument.apply(this, arguments);
2847
+ }
2848
+ function _removeDocument() {
2849
+ _removeDocument = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(documentId) {
2850
+ var response, result, serverDocuments, _t4, _t5;
2851
+ return _regenerator().w(function (_context7) {
2852
+ while (1) switch (_context7.p = _context7.n) {
2853
+ case 0:
2854
+ if (!(!config.removeDocumentUrl || !documentId || !window.confirm('Remove this document?'))) {
2855
+ _context7.n = 1;
2856
+ break;
2857
+ }
2858
+ return _context7.a(2);
2859
+ case 1:
2860
+ _context7.p = 1;
2861
+ _context7.n = 2;
2862
+ return fetch(config.removeDocumentUrl, {
2863
+ method: 'POST',
2864
+ headers: {
2865
+ 'Content-Type': 'application/json'
2866
+ },
2867
+ body: JSON.stringify({
2868
+ itemId: config.itemId,
2869
+ documentId: documentId
2870
+ })
2871
+ });
2872
+ case 2:
2873
+ response = _context7.v;
2874
+ if (response.ok) {
2875
+ _context7.n = 4;
2876
+ break;
2877
+ }
2878
+ _t4 = console;
2879
+ _context7.n = 3;
2880
+ return response.text();
2881
+ case 3:
2882
+ _t4.error.call(_t4, 'Failed to remove document:', _context7.v);
2883
+ showUploadStatus('Failed to remove document.', 'text-danger');
2884
+ return _context7.a(2);
2885
+ case 4:
2886
+ _context7.n = 5;
2887
+ return response.json();
2888
+ case 5:
2889
+ result = _context7.v;
2890
+ serverDocuments = (Array.isArray(result.documents) ? result.documents : []).map(normalizeDocumentInfo).filter(function (document) {
2891
+ return document && document.documentId;
2892
+ });
2893
+ interactionDocuments = serverDocuments.length > 0 ? serverDocuments : interactionDocuments.filter(function (document) {
2894
+ return document.documentId !== documentId;
2895
+ });
2896
+ renderDocuments();
2897
+ showUploadStatus('Document removed.', 'text-success');
2898
+ _context7.n = 7;
2899
+ break;
2900
+ case 6:
2901
+ _context7.p = 6;
2902
+ _t5 = _context7.v;
2903
+ console.error('Remove failed:', _t5);
2904
+ showUploadStatus('Failed to remove document.', 'text-danger');
2905
+ case 7:
2906
+ return _context7.a(2);
2907
+ }
2908
+ }, _callee7, null, [[1, 6]]);
2909
+ }));
2910
+ return _removeDocument.apply(this, arguments);
2911
+ }
2912
+ var onFileInputChange = function onFileInputChange(event) {
2913
+ var selectedFiles = event.target.files ? Array.from(event.target.files) : [];
2914
+ uploadDocuments(selectedFiles);
2915
+ };
2916
+ fileInput.addEventListener('change', onFileInputChange);
2917
+ fileInput[managerStateKey] = {
2918
+ dispose: function dispose() {
2919
+ fileInput.removeEventListener('change', onFileInputChange);
2920
+ }
2921
+ };
2922
+ renderDocuments();
2923
+ renderUploadQueue();
2924
+ showUploadStatus(null);
2925
+ showUploadProgress(null);
2926
+ return fileInput[managerStateKey];
2927
+ }
2928
+ function parseJsonAttribute(element, attributeName, description) {
2929
+ var rawValue = element.getAttribute(attributeName);
2930
+ if (!rawValue) {
2931
+ return null;
2932
+ }
2933
+ try {
2934
+ return JSON.parse(rawValue);
2935
+ } catch (error) {
2936
+ console.error('Failed to parse ' + description + ' JSON.', error);
2937
+ return null;
2938
+ }
2939
+ }
2940
+ function initializeFromElement(element) {
2941
+ if (!element || element.dataset.chatInteractionDocumentManagerInitialized === 'true') {
2942
+ return element ? element[managerStateKey] || null : null;
2943
+ }
2944
+ var config = parseJsonAttribute(element, 'data-chat-interaction-document-manager-config', 'chat interaction document manager config');
2945
+ if (!config) {
2946
+ return null;
2947
+ }
2948
+ var state = initialize(config);
2949
+ if (!state) {
2950
+ return null;
2951
+ }
2952
+ element.dataset.chatInteractionDocumentManagerInitialized = 'true';
2953
+ return state;
2954
+ }
2955
+ function scanForAutoInitialization(root) {
2956
+ if (!root || typeof root.querySelectorAll !== 'function') {
2957
+ return;
2958
+ }
2959
+ if (typeof root.matches === 'function' && root.matches('[data-chat-interaction-document-manager-config]')) {
2960
+ initializeFromElement(root);
2961
+ }
2962
+ root.querySelectorAll('[data-chat-interaction-document-manager-config]').forEach(initializeFromElement);
2963
+ }
2964
+ function startAutoInitialization() {
2965
+ scanForAutoInitialization(document);
2966
+ if (typeof MutationObserver === 'undefined') {
2967
+ return;
2968
+ }
2969
+ var observer = new MutationObserver(function (mutations) {
2970
+ mutations.forEach(function (mutation) {
2971
+ mutation.addedNodes.forEach(function (node) {
2972
+ if (node && node.nodeType === 1) {
2973
+ scanForAutoInitialization(node);
2974
+ }
2975
+ });
2976
+ });
2977
+ });
2978
+ observer.observe(document.body, {
2979
+ childList: true,
2980
+ subtree: true
2981
+ });
2982
+ }
2983
+ if (document.readyState === 'loading') {
2984
+ document.addEventListener('DOMContentLoaded', startAutoInitialization, {
2985
+ once: true
2986
+ });
2987
+ } else {
2988
+ startAutoInitialization();
2989
+ }
2092
2990
  return {
2093
- initialize: initialize
2991
+ initialize: initialize,
2992
+ initializeFromElement: initializeFromElement
2094
2993
  };
2095
2994
  }();
2096
2995