@crestapps/ai-chat-ui 1.0.0-preview-22-preview.2 → 1.0.0-preview-22.5
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.
- package/dist/ai-chat.js +52 -11
- package/dist/ai-chat.js.map +1 -0
- package/dist/ai-chat.min.js +2 -1
- package/dist/ai-chat.min.js.map +1 -0
- package/dist/chat-interaction.js +40 -9
- package/dist/chat-interaction.js.map +1 -0
- package/dist/chat-interaction.min.js +2 -1
- package/dist/chat-interaction.min.js.map +1 -0
- package/dist/chat-widget.css +126 -35
- package/dist/chat-widget.css.map +1 -0
- package/dist/chat-widget.min.css +1 -1
- package/dist/document-drop-zone.css +2 -0
- package/dist/document-drop-zone.css.map +1 -0
- package/dist/document-drop-zone.js +2 -1
- package/dist/document-drop-zone.js.map +1 -0
- package/dist/document-drop-zone.min.js +1 -0
- package/dist/document-drop-zone.min.js.map +1 -0
- package/dist/technical-name-generator.js +2 -1
- package/dist/technical-name-generator.js.map +1 -0
- package/dist/technical-name-generator.min.js +1 -0
- package/dist/technical-name-generator.min.js.map +1 -0
- package/package.json +11 -1
package/dist/ai-chat.js
CHANGED
|
@@ -25,7 +25,6 @@ window.openAIChatManager = function () {
|
|
|
25
25
|
// UI defaults for generated media
|
|
26
26
|
generatedImageAltText: 'Generated Image',
|
|
27
27
|
generatedImageMaxWidth: 400,
|
|
28
|
-
generatedChartMaxWidth: 900,
|
|
29
28
|
downloadImageTitle: 'Download image',
|
|
30
29
|
downloadChartTitle: 'Download chart as image',
|
|
31
30
|
downloadChartButtonText: 'Download',
|
|
@@ -35,7 +34,7 @@ window.openAIChatManager = function () {
|
|
|
35
34
|
thumbsDownTitle: 'Thumbs down',
|
|
36
35
|
copyTitle: 'Click here to copy response to clipboard.',
|
|
37
36
|
codeCopiedText: 'Copied!',
|
|
38
|
-
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"'msg-' + 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\">{{ userLabel }}</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 <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <template v-if=\"metricsEnabled && message.role === 'assistant'\">\n <span class=\"ai-chat-message-assistant-feedback\" :data-message-id=\"message.id\">\n <button class=\"btn btn-sm btn-link text-success p-0 me-2 button-message-toolbox rate-up-btn\" @click=\"rateMessage(message, true, $event)\" :title=\"thumbsUpTitle\">\n <i class=\"fa-regular fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm btn-link text-danger p-0 me-2 button-message-toolbox rate-down-btn\" @click=\"rateMessage(message, false, $event)\" :title=\"thumbsDownTitle\">\n <i class=\"fa-regular fa-thumbs-down\"></i>\n </button>\n </span>\n </template>\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" :title=\"copyTitle\">\n <i class=\"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 ",
|
|
37
|
+
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"'msg-' + 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\">{{ userLabel }}</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 <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <template v-if=\"metricsEnabled && message.role === 'assistant'\">\n <span class=\"ai-chat-message-assistant-feedback\" :data-message-id=\"message.id\">\n <button class=\"btn btn-sm btn-link text-success p-0 me-2 button-message-toolbox rate-up-btn\" @click=\"rateMessage(message, true, $event)\" :title=\"thumbsUpTitle\">\n <i class=\"fa-regular fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm btn-link text-danger p-0 me-2 button-message-toolbox rate-down-btn\" @click=\"rateMessage(message, false, $event)\" :title=\"thumbsDownTitle\">\n <i class=\"fa-regular fa-thumbs-down\"></i>\n </button>\n </span>\n </template>\n <button v-if=\"textToSpeechEnabled && 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 <i :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></i>\n </button>\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" :title=\"copyTitle\">\n <i class=\"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 ",
|
|
39
38
|
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 "
|
|
40
39
|
};
|
|
41
40
|
|
|
@@ -134,8 +133,7 @@ window.openAIChatManager = function () {
|
|
|
134
133
|
// its DOM update to render charts it didn't create itself.
|
|
135
134
|
window.__chartConfigs = window.__chartConfigs || {};
|
|
136
135
|
function createChartHtml(chartId) {
|
|
137
|
-
|
|
138
|
-
return "<div class=\"chart-container\" style=\"position: relative; width: 100%; max-width: ".concat(chartMaxWidth, "px;\">") + "<canvas id=\"".concat(chartId, "\" class=\"img-thumbnail\"></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>";
|
|
136
|
+
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>";
|
|
139
137
|
}
|
|
140
138
|
|
|
141
139
|
// Register [chart:{...json...}] as a native marked block extension so the
|
|
@@ -263,25 +261,37 @@ window.openAIChatManager = function () {
|
|
|
263
261
|
function renderChartOnCanvas(chartId, config) {
|
|
264
262
|
var canvas = document.getElementById(chartId);
|
|
265
263
|
if (!canvas) {
|
|
266
|
-
return;
|
|
264
|
+
return false;
|
|
267
265
|
}
|
|
268
266
|
if (typeof Chart === 'undefined') {
|
|
269
267
|
console.warn('Chart.js is not loaded. To render interactive charts, include the Chart.js library on the page (e.g., <script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>).');
|
|
270
|
-
return;
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// When the canvas is inside a hidden container (e.g., a widget panel with
|
|
272
|
+
// display:none), it has zero dimensions and Chart.js cannot render correctly.
|
|
273
|
+
// Keep the config in __chartConfigs so renderPendingCharts() can retry later
|
|
274
|
+
// once the container becomes visible.
|
|
275
|
+
if (canvas.offsetParent === null) {
|
|
276
|
+
window.__chartConfigs[chartId] = config;
|
|
277
|
+
return false;
|
|
271
278
|
}
|
|
272
279
|
try {
|
|
273
|
-
var _cfg$options;
|
|
280
|
+
var _cfg$options, _cfg$options2, _cfg$options2$aspectR;
|
|
274
281
|
if (canvas._chartInstance) {
|
|
275
282
|
canvas._chartInstance.destroy();
|
|
276
283
|
}
|
|
277
284
|
var cfg = typeof config === 'string' ? JSON.parse(config) : config;
|
|
278
285
|
(_cfg$options = cfg.options) !== null && _cfg$options !== void 0 ? _cfg$options : cfg.options = {};
|
|
279
286
|
cfg.options.responsive = true;
|
|
280
|
-
cfg.options.maintainAspectRatio =
|
|
287
|
+
cfg.options.maintainAspectRatio = true;
|
|
288
|
+
(_cfg$options2$aspectR = (_cfg$options2 = cfg.options).aspectRatio) !== null && _cfg$options2$aspectR !== void 0 ? _cfg$options2$aspectR : _cfg$options2.aspectRatio = 4 / 3;
|
|
281
289
|
canvas._chartInstance = new Chart(canvas, cfg);
|
|
282
290
|
delete window.__chartConfigs[chartId];
|
|
291
|
+
return true;
|
|
283
292
|
} catch (e) {
|
|
284
293
|
console.error('Error creating chart:', e);
|
|
294
|
+
return false;
|
|
285
295
|
}
|
|
286
296
|
}
|
|
287
297
|
|
|
@@ -378,13 +388,16 @@ window.openAIChatManager = function () {
|
|
|
378
388
|
preRecordingPrompt: '',
|
|
379
389
|
micButton: null,
|
|
380
390
|
speechToTextEnabled: config.chatMode === 'AudioInput' || config.chatMode === 'Conversation',
|
|
381
|
-
textToSpeechEnabled: config.chatMode === 'Conversation',
|
|
391
|
+
textToSpeechEnabled: config.chatMode === 'Conversation' || !!config.textToSpeechEnabled,
|
|
382
392
|
ttsVoiceName: config.ttsVoiceName || null,
|
|
383
393
|
audioChunks: [],
|
|
384
394
|
audioPlayQueue: [],
|
|
385
395
|
isPlayingAudio: false,
|
|
386
396
|
currentAudioElement: null,
|
|
387
397
|
ttsButton: null,
|
|
398
|
+
ttsPlayingMessageIndex: -1,
|
|
399
|
+
ttsAudioCache: {},
|
|
400
|
+
singleResponseMode: !!config.singleResponseMode,
|
|
388
401
|
conversationModeEnabled: config.chatMode === 'Conversation',
|
|
389
402
|
conversationButton: null,
|
|
390
403
|
isConversationMode: false,
|
|
@@ -1180,6 +1193,11 @@ window.openAIChatManager = function () {
|
|
|
1180
1193
|
|
|
1181
1194
|
// Prevent stale ReceiveTranscript events from repopulating the prompt.
|
|
1182
1195
|
this._audioInputSent = true;
|
|
1196
|
+
|
|
1197
|
+
// In single-response mode, clear all previous messages.
|
|
1198
|
+
if (this.singleResponseMode) {
|
|
1199
|
+
this.messages.splice(0, this.messages.length);
|
|
1200
|
+
}
|
|
1183
1201
|
this.addMessage({
|
|
1184
1202
|
role: 'user',
|
|
1185
1203
|
content: trimmedPrompt
|
|
@@ -1535,18 +1553,34 @@ window.openAIChatManager = function () {
|
|
|
1535
1553
|
}
|
|
1536
1554
|
}
|
|
1537
1555
|
},
|
|
1538
|
-
synthesizeSpeech: function synthesizeSpeech(text) {
|
|
1556
|
+
synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
|
|
1539
1557
|
var _this0 = this;
|
|
1540
1558
|
if (!this.textToSpeechEnabled || !text || !this.connection) {
|
|
1541
1559
|
return;
|
|
1542
1560
|
}
|
|
1543
1561
|
this.audioChunks = [];
|
|
1544
1562
|
this.isPlayingAudio = true;
|
|
1563
|
+
this._ttsCacheIndex = cacheIndex !== undefined ? cacheIndex : -1;
|
|
1545
1564
|
this.connection.invoke("SynthesizeSpeech", this.getProfileId(), this.getSessionId(), text, this.ttsVoiceName)["catch"](function (err) {
|
|
1546
1565
|
console.error("TTS synthesis error:", err);
|
|
1547
1566
|
_this0.isPlayingAudio = false;
|
|
1567
|
+
_this0.ttsPlayingMessageIndex = -1;
|
|
1568
|
+
_this0._ttsCacheIndex = -1;
|
|
1548
1569
|
});
|
|
1549
1570
|
},
|
|
1571
|
+
toggleMessageTts: function toggleMessageTts(message, index) {
|
|
1572
|
+
if (this.ttsPlayingMessageIndex === index) {
|
|
1573
|
+
this.stopAudio();
|
|
1574
|
+
return;
|
|
1575
|
+
}
|
|
1576
|
+
this.stopAudio();
|
|
1577
|
+
this.ttsPlayingMessageIndex = index;
|
|
1578
|
+
if (this.ttsAudioCache[index]) {
|
|
1579
|
+
this.playAudioBlob(this.ttsAudioCache[index]);
|
|
1580
|
+
return;
|
|
1581
|
+
}
|
|
1582
|
+
this.synthesizeSpeech(message.content, index);
|
|
1583
|
+
},
|
|
1550
1584
|
playCollectedAudio: function playCollectedAudio() {
|
|
1551
1585
|
if (this.audioChunks.length === 0) {
|
|
1552
1586
|
if (!this.currentAudioElement && this.audioPlayQueue.length === 0) {
|
|
@@ -1576,6 +1610,10 @@ window.openAIChatManager = function () {
|
|
|
1576
1610
|
var blob = new Blob([combined], {
|
|
1577
1611
|
type: 'audio/mp3'
|
|
1578
1612
|
});
|
|
1613
|
+
if (this._ttsCacheIndex >= 0) {
|
|
1614
|
+
this.ttsAudioCache[this._ttsCacheIndex] = blob;
|
|
1615
|
+
this._ttsCacheIndex = -1;
|
|
1616
|
+
}
|
|
1579
1617
|
|
|
1580
1618
|
// If audio is already playing, queue this blob for sequential playback.
|
|
1581
1619
|
if (this.currentAudioElement) {
|
|
@@ -1613,6 +1651,7 @@ window.openAIChatManager = function () {
|
|
|
1613
1651
|
this.playAudioBlob(nextBlob);
|
|
1614
1652
|
} else {
|
|
1615
1653
|
this.isPlayingAudio = false;
|
|
1654
|
+
this.ttsPlayingMessageIndex = -1;
|
|
1616
1655
|
this.conversationModeOnAudioEnded();
|
|
1617
1656
|
}
|
|
1618
1657
|
},
|
|
@@ -1625,6 +1664,7 @@ window.openAIChatManager = function () {
|
|
|
1625
1664
|
this.audioChunks = [];
|
|
1626
1665
|
this.audioPlayQueue = [];
|
|
1627
1666
|
this.isPlayingAudio = false;
|
|
1667
|
+
this.ttsPlayingMessageIndex = -1;
|
|
1628
1668
|
},
|
|
1629
1669
|
toggleConversationMode: function toggleConversationMode() {
|
|
1630
1670
|
if (this.isConversationMode) {
|
|
@@ -2451,4 +2491,5 @@ document.addEventListener('click', function (e) {
|
|
|
2451
2491
|
})["catch"](function (err) {
|
|
2452
2492
|
console.error('Failed to download image:', err);
|
|
2453
2493
|
});
|
|
2454
|
-
});
|
|
2494
|
+
});
|
|
2495
|
+
//# sourceMappingURL=ai-chat.js.map
|