emanate-ai-chat-lib 0.1.6 → 0.1.7
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/bundles/emanate-ai-chat-lib.umd.js +301 -46
- package/bundles/emanate-ai-chat-lib.umd.js.map +1 -1
- package/esm2015/lib/components/ai-chat.component.js +110 -40
- package/esm2015/lib/services/ai-agent.service.js +100 -10
- package/esm2015/lib/services/conversation-state.service.js +92 -2
- package/fesm2015/emanate-ai-chat-lib.js +299 -49
- package/fesm2015/emanate-ai-chat-lib.js.map +1 -1
- package/lib/components/ai-chat.component.d.ts +12 -3
- package/lib/services/ai-agent.service.d.ts +52 -0
- package/lib/services/conversation-state.service.d.ts +24 -1
- package/package.json +1 -1
|
@@ -962,19 +962,109 @@
|
|
|
962
962
|
return this.http.get(url, { headers: this.getHeaders() })
|
|
963
963
|
.pipe(operators.timeout(this.config.timeout || 30000), operators.catchError(function (error) {
|
|
964
964
|
console.log('GetConversationHistory API not available:', error);
|
|
965
|
-
//
|
|
965
|
+
// Return empty history in demo mode
|
|
966
966
|
var mockHistory = {
|
|
967
967
|
conversations: [],
|
|
968
968
|
skip: skip,
|
|
969
969
|
take: take,
|
|
970
970
|
hasMore: false
|
|
971
971
|
};
|
|
972
|
-
return
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
972
|
+
return rxjs.throwError({ error: 'API not available (Demo Mode)', status: 503 });
|
|
973
|
+
}));
|
|
974
|
+
};
|
|
975
|
+
// ============= Message Retrieval Methods =============
|
|
976
|
+
/**
|
|
977
|
+
* 8. Get messages for a specific conversation
|
|
978
|
+
* @param conversationId - The conversation ID
|
|
979
|
+
*/
|
|
980
|
+
AiAgentService.prototype.getConversationMessages = function (conversationId) {
|
|
981
|
+
if (!this.config.enableConversationLifecycle) {
|
|
982
|
+
return rxjs.throwError({ error: 'Conversation lifecycle is disabled' });
|
|
983
|
+
}
|
|
984
|
+
var url = this.getBaseUrl() + "/conversations/" + conversationId + "/messages";
|
|
985
|
+
console.log('Getting conversation messages at:', url);
|
|
986
|
+
return this.http.get(url, { headers: this.getHeaders() })
|
|
987
|
+
.pipe(operators.timeout(this.config.timeout || 30000), operators.catchError(function (error) {
|
|
988
|
+
if (error.status === 404) {
|
|
989
|
+
console.error('Conversation not found:', conversationId);
|
|
990
|
+
return rxjs.throwError({ error: 'Conversation not found', status: 404 });
|
|
991
|
+
}
|
|
992
|
+
if (error.status === 503) {
|
|
993
|
+
console.error('Message retrieval unavailable (in-memory mode):', conversationId);
|
|
994
|
+
return rxjs.throwError({ error: 'Service unavailable - SQL Server required', status: 503 });
|
|
995
|
+
}
|
|
996
|
+
console.log('GetConversationMessages API not available:', error);
|
|
997
|
+
return rxjs.throwError({ error: 'API not available (Demo Mode)', status: 503 });
|
|
998
|
+
}));
|
|
999
|
+
};
|
|
1000
|
+
/**
|
|
1001
|
+
* 9. Get active conversation messages for a user
|
|
1002
|
+
* Automatically finds and returns the user's active conversation with messages
|
|
1003
|
+
* @param userId - User ID
|
|
1004
|
+
*/
|
|
1005
|
+
AiAgentService.prototype.getActiveConversationMessages = function (userId) {
|
|
1006
|
+
if (!this.config.enableConversationLifecycle) {
|
|
1007
|
+
return rxjs.throwError({ error: 'Conversation lifecycle is disabled' });
|
|
1008
|
+
}
|
|
1009
|
+
var url = this.getBaseUrl() + "/conversations/active/messages?userId=" + encodeURIComponent(userId);
|
|
1010
|
+
console.log('Getting active conversation messages at:', url);
|
|
1011
|
+
return this.http.get(url, { headers: this.getHeaders() })
|
|
1012
|
+
.pipe(operators.timeout(this.config.timeout || 30000), operators.catchError(function (error) {
|
|
1013
|
+
if (error.status === 400) {
|
|
1014
|
+
console.error('Invalid userId parameter');
|
|
1015
|
+
return rxjs.throwError({ error: 'Invalid userId', status: 400 });
|
|
1016
|
+
}
|
|
1017
|
+
if (error.status === 503) {
|
|
1018
|
+
console.error('Message retrieval unavailable (in-memory mode)');
|
|
1019
|
+
return rxjs.throwError({ error: 'Service unavailable - SQL Server required', status: 503 });
|
|
1020
|
+
}
|
|
1021
|
+
console.log('GetActiveConversationMessages API not available:', error);
|
|
1022
|
+
// Return empty response in demo mode
|
|
1023
|
+
var emptyResponse = {
|
|
1024
|
+
userId: userId,
|
|
1025
|
+
hasActiveConversation: false,
|
|
1026
|
+
conversation: null,
|
|
1027
|
+
messages: []
|
|
1028
|
+
};
|
|
1029
|
+
return rxjs.throwError({ error: 'API not available (Demo Mode)', status: 503 });
|
|
1030
|
+
}));
|
|
1031
|
+
};
|
|
1032
|
+
/**
|
|
1033
|
+
* 10. Get user messages with filtering
|
|
1034
|
+
* Retrieve messages for multiple conversations with optional filtering
|
|
1035
|
+
* @param userId - User ID
|
|
1036
|
+
* @param options - Query options (source, includeCompleted, skip, take)
|
|
1037
|
+
*/
|
|
1038
|
+
AiAgentService.prototype.getUserMessages = function (userId, options) {
|
|
1039
|
+
if (!this.config.enableConversationLifecycle) {
|
|
1040
|
+
return rxjs.throwError({ error: 'Conversation lifecycle is disabled' });
|
|
1041
|
+
}
|
|
1042
|
+
var params = new URLSearchParams(Object.assign(Object.assign(Object.assign(Object.assign({ userId: userId }, ((options === null || options === void 0 ? void 0 : options.source) && { source: options.source })), ((options === null || options === void 0 ? void 0 : options.includeCompleted) !== undefined && { includeCompleted: String(options.includeCompleted) })), ((options === null || options === void 0 ? void 0 : options.skip) !== undefined && { skip: String(options.skip) })), ((options === null || options === void 0 ? void 0 : options.take) !== undefined && { take: String(options.take) })));
|
|
1043
|
+
var url = this.getBaseUrl() + "/conversations/messages?" + params.toString();
|
|
1044
|
+
console.log('Getting user messages at:', url);
|
|
1045
|
+
return this.http.get(url, { headers: this.getHeaders() })
|
|
1046
|
+
.pipe(operators.timeout(this.config.timeout || 30000), operators.catchError(function (error) {
|
|
1047
|
+
if (error.status === 400) {
|
|
1048
|
+
console.error('Invalid request parameters');
|
|
1049
|
+
return rxjs.throwError({ error: 'Invalid parameters', status: 400 });
|
|
1050
|
+
}
|
|
1051
|
+
if (error.status === 503) {
|
|
1052
|
+
console.error('Message retrieval unavailable (in-memory mode)');
|
|
1053
|
+
return rxjs.throwError({ error: 'Service unavailable - SQL Server required', status: 503 });
|
|
1054
|
+
}
|
|
1055
|
+
console.log('GetUserMessages API not available:', error);
|
|
1056
|
+
// Return empty response in demo mode
|
|
1057
|
+
var emptyResponse = {
|
|
1058
|
+
userId: userId,
|
|
1059
|
+
source: options === null || options === void 0 ? void 0 : options.source,
|
|
1060
|
+
includeCompleted: (options === null || options === void 0 ? void 0 : options.includeCompleted) || false,
|
|
1061
|
+
totalConversations: 0,
|
|
1062
|
+
conversations: [],
|
|
1063
|
+
skip: (options === null || options === void 0 ? void 0 : options.skip) || 0,
|
|
1064
|
+
take: (options === null || options === void 0 ? void 0 : options.take) || 20,
|
|
1065
|
+
hasMore: false
|
|
1066
|
+
};
|
|
1067
|
+
return rxjs.throwError({ error: 'API not available (Demo Mode)', status: 503 });
|
|
978
1068
|
}));
|
|
979
1069
|
};
|
|
980
1070
|
/**
|
|
@@ -1344,6 +1434,98 @@
|
|
|
1344
1434
|
isActive: false
|
|
1345
1435
|
};
|
|
1346
1436
|
};
|
|
1437
|
+
// ============= Message Loading Methods =============
|
|
1438
|
+
/**
|
|
1439
|
+
* Load messages for a specific conversation
|
|
1440
|
+
* @param conversationId - The conversation ID to load messages for
|
|
1441
|
+
* @returns Observable<ConversationMessageDto[]> - Array of messages
|
|
1442
|
+
*/
|
|
1443
|
+
ConversationStateService.prototype.loadConversationMessages = function (conversationId) {
|
|
1444
|
+
console.log('Loading messages for conversation:', conversationId);
|
|
1445
|
+
return this.aiAgentService.getConversationMessages(conversationId).pipe(operators.tap(function (messages) {
|
|
1446
|
+
console.log("Loaded " + messages.length + " messages for conversation " + conversationId);
|
|
1447
|
+
}), operators.catchError(function (error) {
|
|
1448
|
+
console.error('Failed to load conversation messages:', error);
|
|
1449
|
+
// Return empty array on error (graceful degradation)
|
|
1450
|
+
return rxjs.of([]);
|
|
1451
|
+
}));
|
|
1452
|
+
};
|
|
1453
|
+
/**
|
|
1454
|
+
* Load messages for the active conversation
|
|
1455
|
+
* Uses the active conversation messages endpoint for efficiency
|
|
1456
|
+
* @param userId - User ID
|
|
1457
|
+
* @returns Observable with conversation and messages
|
|
1458
|
+
*/
|
|
1459
|
+
ConversationStateService.prototype.loadActiveConversationWithMessages = function (userId) {
|
|
1460
|
+
var _this = this;
|
|
1461
|
+
console.log('Loading active conversation with messages for user:', userId);
|
|
1462
|
+
return this.aiAgentService.getActiveConversationMessages(userId).pipe(operators.tap(function (response) {
|
|
1463
|
+
if (response.hasActiveConversation && response.conversation) {
|
|
1464
|
+
// Update state with the active conversation
|
|
1465
|
+
var state = {
|
|
1466
|
+
conversationId: response.conversation.conversationId,
|
|
1467
|
+
userId: response.conversation.userId,
|
|
1468
|
+
userName: response.conversation.userName || null,
|
|
1469
|
+
status: response.conversation.status,
|
|
1470
|
+
startedDate: response.conversation.startedDate,
|
|
1471
|
+
lastActivityDate: response.conversation.lastActivityDate,
|
|
1472
|
+
isActive: response.conversation.isActive
|
|
1473
|
+
};
|
|
1474
|
+
_this.setActiveConversation(state);
|
|
1475
|
+
console.log("Loaded active conversation with " + response.messages.length + " messages");
|
|
1476
|
+
}
|
|
1477
|
+
else {
|
|
1478
|
+
console.log('No active conversation found for user');
|
|
1479
|
+
}
|
|
1480
|
+
}), operators.catchError(function (error) {
|
|
1481
|
+
console.error('Failed to load active conversation messages:', error);
|
|
1482
|
+
// Return empty response on error
|
|
1483
|
+
var emptyResponse = {
|
|
1484
|
+
userId: userId,
|
|
1485
|
+
hasActiveConversation: false,
|
|
1486
|
+
conversation: null,
|
|
1487
|
+
messages: []
|
|
1488
|
+
};
|
|
1489
|
+
return rxjs.of(emptyResponse);
|
|
1490
|
+
}));
|
|
1491
|
+
};
|
|
1492
|
+
/**
|
|
1493
|
+
* Recover conversation with messages
|
|
1494
|
+
* Enhanced version of recoverState that also loads messages
|
|
1495
|
+
* @param userId - User ID
|
|
1496
|
+
* @returns Observable with conversationId and messages
|
|
1497
|
+
*/
|
|
1498
|
+
ConversationStateService.prototype.recoverStateWithMessages = function (userId) {
|
|
1499
|
+
var _this = this;
|
|
1500
|
+
console.log('Recovering conversation state with messages for user:', userId);
|
|
1501
|
+
// Use the active conversation messages endpoint (most efficient)
|
|
1502
|
+
return this.loadActiveConversationWithMessages(userId).pipe(operators.map(function (response) {
|
|
1503
|
+
if (response.hasActiveConversation && response.conversation) {
|
|
1504
|
+
return {
|
|
1505
|
+
conversationId: response.conversation.conversationId,
|
|
1506
|
+
messages: response.messages
|
|
1507
|
+
};
|
|
1508
|
+
}
|
|
1509
|
+
else {
|
|
1510
|
+
return {
|
|
1511
|
+
conversationId: null,
|
|
1512
|
+
messages: []
|
|
1513
|
+
};
|
|
1514
|
+
}
|
|
1515
|
+
}), operators.catchError(function (error) {
|
|
1516
|
+
console.error('Failed to recover conversation with messages:', error);
|
|
1517
|
+
// Fallback to regular recovery without messages
|
|
1518
|
+
return _this.recoverState(userId).pipe(operators.switchMap(function (conversationId) {
|
|
1519
|
+
if (conversationId) {
|
|
1520
|
+
// Try to load messages for the recovered conversation
|
|
1521
|
+
return _this.loadConversationMessages(conversationId).pipe(operators.map(function (messages) { return ({ conversationId: conversationId, messages: messages }); }));
|
|
1522
|
+
}
|
|
1523
|
+
else {
|
|
1524
|
+
return rxjs.of({ conversationId: null, messages: [] });
|
|
1525
|
+
}
|
|
1526
|
+
}));
|
|
1527
|
+
}));
|
|
1528
|
+
};
|
|
1347
1529
|
return ConversationStateService;
|
|
1348
1530
|
}());
|
|
1349
1531
|
ConversationStateService.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0__namespace, type: ConversationStateService, deps: [{ token: AiAgentService }], target: i0__namespace.ɵɵFactoryTarget.Injectable });
|
|
@@ -1558,11 +1740,12 @@
|
|
|
1558
1740
|
});
|
|
1559
1741
|
};
|
|
1560
1742
|
/**
|
|
1561
|
-
* Initialize conversation -
|
|
1562
|
-
*
|
|
1563
|
-
*
|
|
1743
|
+
* Initialize conversation - with message loading from API
|
|
1744
|
+
* Attempts to load active conversation and its messages from backend
|
|
1745
|
+
* Falls back to welcome message if no active conversation found
|
|
1564
1746
|
*/
|
|
1565
1747
|
AiChatComponent.prototype.initializeConversation = function () {
|
|
1748
|
+
var _this = this;
|
|
1566
1749
|
if (!this.userId) {
|
|
1567
1750
|
console.warn('Cannot initialize conversation without userId');
|
|
1568
1751
|
this.updateStatus('Ready');
|
|
@@ -1571,41 +1754,99 @@
|
|
|
1571
1754
|
this.applySizePreset(this.currentSize);
|
|
1572
1755
|
return;
|
|
1573
1756
|
}
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1757
|
+
this.updateStatus('Loading conversation...');
|
|
1758
|
+
// Try to load active conversation with messages from API
|
|
1759
|
+
this.conversationStateService.recoverStateWithMessages(this.userId)
|
|
1760
|
+
.pipe(operators.takeUntil(this.destroy$))
|
|
1761
|
+
.subscribe({
|
|
1762
|
+
next: function (result) {
|
|
1763
|
+
if (result.conversationId && result.messages.length > 0) {
|
|
1764
|
+
// Successfully loaded conversation with messages
|
|
1765
|
+
_this.conversationId = result.conversationId;
|
|
1766
|
+
_this.conversationInitialized = true;
|
|
1767
|
+
console.log("Loaded conversation " + result.conversationId + " with " + result.messages.length + " messages");
|
|
1768
|
+
// Convert API messages to chat messages
|
|
1769
|
+
_this.loadMessagesFromApi(result.messages);
|
|
1770
|
+
_this.updateStatus('Ready');
|
|
1771
|
+
}
|
|
1772
|
+
else if (result.conversationId) {
|
|
1773
|
+
// Found conversation but no messages
|
|
1774
|
+
_this.conversationId = result.conversationId;
|
|
1775
|
+
_this.conversationInitialized = true;
|
|
1776
|
+
console.log("Loaded empty conversation " + result.conversationId);
|
|
1777
|
+
_this.addWelcomeMessage();
|
|
1778
|
+
_this.updateStatus('Ready');
|
|
1779
|
+
}
|
|
1780
|
+
else {
|
|
1781
|
+
// No active conversation found
|
|
1782
|
+
console.log('No active conversation found - will create on first message');
|
|
1783
|
+
// Load historical messages if provided by parent
|
|
1784
|
+
if (_this.historicalMessages && _this.historicalMessages.length > 0) {
|
|
1785
|
+
_this.loadHistoricalMessages(_this.historicalMessages);
|
|
1786
|
+
}
|
|
1787
|
+
else {
|
|
1788
|
+
_this.addWelcomeMessage();
|
|
1789
|
+
}
|
|
1790
|
+
_this.updateStatus('Ready');
|
|
1791
|
+
}
|
|
1792
|
+
_this.loadSavedSize();
|
|
1793
|
+
_this.applySizePreset(_this.currentSize);
|
|
1794
|
+
},
|
|
1795
|
+
error: function (error) {
|
|
1796
|
+
console.error('Failed to load conversation:', error);
|
|
1797
|
+
// Fallback: try to use conversation ID from input or storage
|
|
1798
|
+
var storedState = _this.conversationStateService.getCurrentState();
|
|
1799
|
+
if (storedState && storedState.conversationId && storedState.userId === _this.userId) {
|
|
1800
|
+
_this.conversationId = storedState.conversationId;
|
|
1801
|
+
_this.conversationInitialized = true;
|
|
1802
|
+
console.log('Using stored conversation ID (API unavailable):', _this.conversationId);
|
|
1803
|
+
}
|
|
1804
|
+
else if (_this.conversationId) {
|
|
1805
|
+
_this.conversationInitialized = true;
|
|
1806
|
+
console.log('Using input conversation ID (API unavailable):', _this.conversationId);
|
|
1807
|
+
}
|
|
1808
|
+
// Load historical messages if provided
|
|
1809
|
+
if (_this.historicalMessages && _this.historicalMessages.length > 0) {
|
|
1810
|
+
_this.loadHistoricalMessages(_this.historicalMessages);
|
|
1811
|
+
}
|
|
1812
|
+
else {
|
|
1813
|
+
_this.addWelcomeMessage();
|
|
1814
|
+
}
|
|
1815
|
+
_this.updateStatus('Ready');
|
|
1816
|
+
_this.loadSavedSize();
|
|
1817
|
+
_this.applySizePreset(_this.currentSize);
|
|
1599
1818
|
}
|
|
1600
|
-
}
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
this
|
|
1819
|
+
});
|
|
1820
|
+
};
|
|
1821
|
+
/**
|
|
1822
|
+
* Load messages from API response into chat UI
|
|
1823
|
+
* Converts ConversationMessageDto to ChatMessage format
|
|
1824
|
+
*/
|
|
1825
|
+
AiChatComponent.prototype.loadMessagesFromApi = function (apiMessages) {
|
|
1826
|
+
var _c;
|
|
1827
|
+
var _this = this;
|
|
1828
|
+
console.log('Loading messages from API:', apiMessages.length);
|
|
1829
|
+
// Clear existing messages
|
|
1830
|
+
this.messages = [];
|
|
1831
|
+
// Add welcome message first
|
|
1832
|
+
this.addWelcomeMessage();
|
|
1833
|
+
// Convert and add API messages
|
|
1834
|
+
var chatMessages = apiMessages.map(function (msg) { return ({
|
|
1835
|
+
messageId: msg.messageId,
|
|
1836
|
+
conversationId: msg.conversationId,
|
|
1837
|
+
isUser: msg.role === 'User',
|
|
1838
|
+
content: msg.content,
|
|
1839
|
+
sender: msg.role,
|
|
1840
|
+
timestamp: new Date(msg.timestamp),
|
|
1841
|
+
isLoading: false
|
|
1842
|
+
}); });
|
|
1843
|
+
// Sort by timestamp to ensure chronological order
|
|
1844
|
+
chatMessages.sort(function (a, b) { return a.timestamp.getTime() - b.timestamp.getTime(); });
|
|
1845
|
+
// Add messages to display
|
|
1846
|
+
(_c = this.messages).push.apply(_c, __spreadArray([], __read(chatMessages)));
|
|
1847
|
+
console.log("Loaded " + chatMessages.length + " messages from API");
|
|
1848
|
+
// Scroll to bottom after messages are rendered
|
|
1849
|
+
setTimeout(function () { return _this.scrollToBottom(); }, 100);
|
|
1609
1850
|
};
|
|
1610
1851
|
/**
|
|
1611
1852
|
* Ensure conversation is initialized before sending a message
|
|
@@ -1773,7 +2014,7 @@
|
|
|
1773
2014
|
_this.conversationId = conversationId;
|
|
1774
2015
|
_this.conversationInitialized = true;
|
|
1775
2016
|
_this.conversationStarted.emit(conversationId); // Emit event
|
|
1776
|
-
_this.updateStatus('
|
|
2017
|
+
_this.updateStatus('Ready');
|
|
1777
2018
|
// Clear existing messages and start fresh
|
|
1778
2019
|
_this.messages = [];
|
|
1779
2020
|
_this.addWelcomeMessage();
|
|
@@ -2151,6 +2392,20 @@
|
|
|
2151
2392
|
AiChatComponent.prototype.getFormattedTime = function (timestamp) {
|
|
2152
2393
|
return timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
2153
2394
|
};
|
|
2395
|
+
/**
|
|
2396
|
+
* Scroll to bottom of messages container
|
|
2397
|
+
*/
|
|
2398
|
+
AiChatComponent.prototype.scrollToBottom = function () {
|
|
2399
|
+
try {
|
|
2400
|
+
var messagesContainer = document.querySelector('.chat-messages');
|
|
2401
|
+
if (messagesContainer) {
|
|
2402
|
+
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
catch (error) {
|
|
2406
|
+
console.error('Error scrolling to bottom:', error);
|
|
2407
|
+
}
|
|
2408
|
+
};
|
|
2154
2409
|
// ============= Resize Methods =============
|
|
2155
2410
|
AiChatComponent.prototype.startResize = function (event, direction) {
|
|
2156
2411
|
var _this = this;
|
|
@@ -2391,7 +2646,7 @@
|
|
|
2391
2646
|
return AiChatComponent;
|
|
2392
2647
|
}());
|
|
2393
2648
|
AiChatComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0__namespace, type: AiChatComponent, deps: [{ token: AiAgentService }, { token: ConversationStateService }, { token: i3__namespace.DomSanitizer }], target: i0__namespace.ɵɵFactoryTarget.Component });
|
|
2394
|
-
AiChatComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: AiChatComponent, selector: "emanate-ai-chat", inputs: { title: "title", placeholder: "placeholder", showDebugInfo: "showDebugInfo", apiUrl: "apiUrl", appKey: "appKey", appSource: "appSource", userId: "userId", firstName: "firstName", userName: "userName", templateDesign: "templateDesign", welcomeMessage: "welcomeMessage", historicalMessages: "historicalMessages", conversationId: "conversationId", enableImageUpload: "enableImageUpload", enableFileUpload: "enableFileUpload", iconSet: "iconSet", customIcons: "customIcons", enableAnimations: "enableAnimations", animationSpeed: "animationSpeed", enableStatusTransitions: "enableStatusTransitions", enableConversationLifecycle: "enableConversationLifecycle", enableAutoConversationRecovery: "enableAutoConversationRecovery", showCloseButton: "showCloseButton", showNewConversationButton: "showNewConversationButton", confirmNewConversation: "confirmNewConversation", newConversationConfirmMessage: "newConversationConfirmMessage" }, outputs: { messageReceived: "messageReceived", conversationStarted: "conversationStarted", messageSent: "messageSent", fileUploaded: "fileUploaded", sizeChanged: "sizeChanged" }, host: { listeners: { "document:keydown.escape": "handleEscapeKey($event)" } }, usesOnChanges: true, ngImport: i0__namespace, template: "<div class=\"ai-chat-container\" \r\n [ngClass]=\"getThemeClass()\" \r\n [ngStyle]=\"getContainerStyle()\"\r\n [class.fullscreen]=\"isFullscreen\"\r\n [class.resizing]=\"isResizing\"\r\n [class]=\"getAnimationClass()\">\r\n \r\n <!-- Resize Handles -->\r\n <div class=\"resize-handle resize-handle-right\" \r\n (mousedown)=\"startResize($event, 'width')\"\r\n *ngIf=\"!isFullscreen\"\r\n title=\"Drag to resize width\">\r\n </div>\r\n \r\n <div class=\"resize-handle resize-handle-corner\" \r\n (mousedown)=\"startResize($event, 'both')\"\r\n *ngIf=\"!isFullscreen\"\r\n title=\"Drag to resize\">\r\n </div>\r\n \r\n <!-- Debug Information (only shown when showDebugInfo is true) -->\r\n <div *ngIf=\"showDebugInfo\" class=\"debug-info\">\r\n <h3>DEBUG: AI Chat Component Loaded</h3>\r\n <p>Status: {{ configurationStatus || 'Loading...' }}</p>\r\n <p>Messages count: {{ messages.length || 0 }}</p>\r\n <p>Theme: {{ templateDesign || 'default' }}</p>\r\n <p>Size: {{ currentSize }} ({{ containerWidth }}x{{ containerHeight }})</p>\r\n </div>\r\n\r\n <div class=\"chat-header\">\r\n <div class=\"header-left\">\r\n <h2>{{ title }}</h2>\r\n <!-- Icon-only status indicator -->\r\n <div class=\"status-indicator-icon\" \r\n [ngClass]=\"{'status-ready': configurationStatus === 'AI Agent is ready' || configurationStatus === 'Ready', \r\n 'status-error': configurationStatus !== 'AI Agent is ready' && configurationStatus !== 'Ready' && configurationStatus !== 'Initializing...' && configurationStatus !== 'Testing connection...',\r\n 'status-loading': configurationStatus === 'Initializing...' || configurationStatus === 'Testing connection...',\r\n 'transition-enabled': enableStatusTransitions}\"\r\n [title]=\"configurationStatus\">\r\n </div>\r\n </div>\r\n \r\n <div class=\"header-controls\">\r\n <!-- New Conversation Button -->\r\n <button *ngIf=\"showNewConversationButton && enableConversationLifecycle && conversationId\" \r\n class=\"control-button new-conversation-button prominent-button\" \r\n (click)=\"startNewConversationExplicit()\"\r\n title=\"Start New Conversation\"\r\n attr.aria-label=\"Start New Conversation\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>\r\n <line x1=\"9\" y1=\"10\" x2=\"15\" y2=\"10\"></line>\r\n <line x1=\"12\" y1=\"7\" x2=\"12\" y2=\"13\"></line>\r\n </svg>\r\n <span class=\"button-text\">New Chat</span>\r\n </button>\r\n \r\n <!-- Close Conversation Button -->\r\n <button *ngIf=\"showCloseButton && enableConversationLifecycle && conversationId\" \r\n class=\"control-button close-button\" \r\n (click)=\"closeConversation('UserCompleted')\"\r\n title=\"Close Conversation\"\r\n attr.aria-label=\"Close Conversation\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n </button>\r\n \r\n <!-- Size Preset Buttons -->\r\n <div class=\"size-controls\" *ngIf=\"!isFullscreen\">\r\n <button class=\"control-button size-button\" \r\n (click)=\"applySizePreset('compact')\"\r\n [class.active]=\"currentSize === 'compact'\"\r\n title=\"Compact View\"\r\n attr.aria-label=\"Compact View\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.compactView\"></span>\r\n </button>\r\n <button class=\"control-button size-button\" \r\n (click)=\"applySizePreset('default')\"\r\n [class.active]=\"currentSize === 'default'\"\r\n title=\"Default View\"\r\n attr.aria-label=\"Default View\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.defaultView\"></span>\r\n </button>\r\n <button class=\"control-button size-button\" \r\n (click)=\"applySizePreset('expanded')\"\r\n [class.active]=\"currentSize === 'expanded'\"\r\n title=\"Expanded View\"\r\n attr.aria-label=\"Expanded View\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.expandedView\"></span>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chat-messages\" #messagesContainer>\r\n <div *ngFor=\"let message of messages; let i = index; trackBy: trackByIndex\" class=\"message-wrapper\">\r\n <!-- Message -->\r\n <div class=\"message\" \r\n [ngClass]=\"{'user-message': message.isUser, 'ai-message': !message.isUser, 'loading-message': message.isLoading}\">\r\n \r\n <div class=\"message-content\">\r\n <div [innerHTML]=\"message.content\"></div>\r\n <div class=\"message-timestamp\">{{ getFormattedTime(message.timestamp) }}</div>\r\n </div>\r\n \r\n <div class=\"message-avatar\">\r\n <span *ngIf=\"message.isUser\" class=\"avatar-icon\" [innerHTML]=\"sanitizedIcons.userAvatar\"></span>\r\n <span *ngIf=\"!message.isUser && !message.isLoading\" class=\"avatar-icon\" [innerHTML]=\"sanitizedIcons.aiAvatar\"></span>\r\n <span *ngIf=\"message.isLoading\" class=\"avatar-icon loading-spinner\" [innerHTML]=\"sanitizedIcons.loadingAvatar\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chat-input\">\r\n <!-- Attachments Preview -->\r\n <div class=\"attachments-preview\" *ngIf=\"selectedFiles.length > 0\">\r\n <div class=\"attachment-item\" *ngFor=\"let file of selectedFiles\">\r\n <svg class=\"attachment-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\"></path>\r\n </svg>\r\n <span class=\"attachment-name\">{{ file.name }}</span>\r\n <span class=\"attachment-size\">{{ getFileSizeFormatted(file.size) }}</span>\r\n <button class=\"remove-attachment\" (click)=\"removeAttachment(file.id)\" title=\"Remove\" attr.aria-label=\"Remove attachment\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n \r\n <div class=\"input-container\">\r\n <!-- File Upload Inputs (Hidden) -->\r\n <input type=\"file\" \r\n id=\"image-upload-input\" \r\n accept=\"image/*\" \r\n multiple \r\n (change)=\"onImageUpload($event)\"\r\n style=\"display: none;\"\r\n [disabled]=\"!enableImageUpload\">\r\n \r\n <input type=\"file\" \r\n id=\"file-upload-input\" \r\n accept=\".pdf,.doc,.docx,.txt,.csv\" \r\n multiple \r\n (change)=\"onFileUpload($event)\"\r\n style=\"display: none;\"\r\n [disabled]=\"!enableFileUpload\">\r\n \r\n <!-- Upload Buttons (Conditionally rendered) -->\r\n <div class=\"upload-buttons\" *ngIf=\"enableImageUpload || enableFileUpload\">\r\n <button *ngIf=\"enableImageUpload\" \r\n class=\"upload-button image-upload\" \r\n (click)=\"triggerImageUpload()\"\r\n [disabled]=\"isLoading\"\r\n title=\"Upload Image\"\r\n attr.aria-label=\"Upload Image\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.imageUpload\"></span>\r\n </button>\r\n \r\n <button *ngIf=\"enableFileUpload\" \r\n class=\"upload-button file-upload\" \r\n (click)=\"triggerFileUpload()\"\r\n [disabled]=\"isLoading\"\r\n title=\"Attach File\"\r\n attr.aria-label=\"Attach File\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.fileUpload\"></span>\r\n </button>\r\n </div>\r\n \r\n <textarea \r\n [(ngModel)]=\"currentInquiry\" \r\n (keypress)=\"onKeyPress($event)\"\r\n [placeholder]=\"placeholder\"\r\n rows=\"2\"\r\n [disabled]=\"isLoading\"\r\n class=\"inquiry-textarea\"\r\n attr.aria-label=\"Type your message\"></textarea>\r\n \r\n <button \r\n (click)=\"sendInquiry()\" \r\n [disabled]=\"!currentInquiry.trim() || isLoading\"\r\n class=\"send-button\"\r\n title=\"Send Message\"\r\n attr.aria-label=\"Send Message\">\r\n <span *ngIf=\"!isLoading\" class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.send\"></span>\r\n <span *ngIf=\"isLoading\" class=\"icon-svg loading-icon\" [innerHTML]=\"sanitizedIcons.sendLoading\"></span>\r\n <span class=\"text\">{{ isLoading ? 'Sending...' : 'Send' }}</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Confirmation Modal -->\r\n <div class=\"confirmation-modal-backdrop\" \r\n *ngIf=\"showConfirmationModal\"\r\n (click)=\"cancelConfirmation()\">\r\n <div class=\"confirmation-modal\" \r\n [ngClass]=\"getThemeClass()\"\r\n (click)=\"$event.stopPropagation()\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n [attr.aria-labelledby]=\"'modal-title-' + conversationId\"\r\n [attr.aria-describedby]=\"'modal-description-' + conversationId\">\r\n \r\n <div class=\"modal-icon warning-icon\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"></path>\r\n <line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"></line>\r\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"></line>\r\n </svg>\r\n </div>\r\n \r\n <h3 class=\"modal-title\" [id]=\"'modal-title-' + conversationId\">Start New Conversation?</h3>\r\n \r\n <p class=\"modal-message\" [id]=\"'modal-description-' + conversationId\">\r\n {{ newConversationConfirmMessage }}\r\n </p>\r\n \r\n <div class=\"modal-actions\">\r\n <button class=\"modal-button secondary-button\" \r\n (click)=\"cancelConfirmation()\"\r\n type=\"button\"\r\n attr.aria-label=\"Cancel\">\r\n Cancel\r\n </button>\r\n <button class=\"modal-button primary-button\" \r\n (click)=\"onConfirmNewConversation()\"\r\n type=\"button\"\r\n attr.aria-label=\"Start New Conversation\">\r\n Start New Chat\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: ["@charset \"UTF-8\";.ai-chat-container{display:flex;flex-direction:column;height:100vh;max-width:800px;margin:0 auto;background:#ffffff;border-radius:12px;overflow:hidden;position:relative;transition:all .25s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 8px #00000014,0 4px 16px #0000000a;--icon-primary: #667eea;--icon-secondary: #6b7280;--icon-avatar-user: #667eea;--icon-avatar-ai: #764ba2;--icon-header: #ffffff;--icon-upload: #667eea;--icon-send: #ffffff;--icon-active: #667eea;--icon-disabled: #d1d5db;--icon-hover: #5568d3}.ai-chat-container.fullscreen{position:fixed!important;top:0!important;left:0!important;right:0!important;bottom:0!important;width:100vw!important;height:100vh!important;max-width:100vw!important;max-height:100vh!important;border-radius:0;z-index:99999;margin:0}.ai-chat-container.resizing{-webkit-user-select:none;user-select:none;cursor:nwse-resize;transition:none}.resize-handle{position:absolute;background:rgba(102,126,234,.3);transition:background .2s ease;z-index:10}.resize-handle:hover{background:rgba(102,126,234,.6)}.resize-handle.resize-handle-right{top:0;right:-4px;width:8px;height:100%;cursor:ew-resize}.resize-handle.resize-handle-corner{bottom:-4px;right:-4px;width:20px;height:20px;cursor:nwse-resize;border-radius:0 0 8px}.resize-handle.resize-handle-corner:after{content:\"\\22f0\";position:absolute;bottom:2px;right:2px;font-size:12px;color:#fffc}.debug-info{background:yellow;padding:10px;border:1px solid orange}.debug-info h3{margin:0;font-size:1.2rem}.debug-info p{margin:5px 0}.icon-svg{display:inline-block;width:20px;height:20px;color:var(--icon-secondary)}.icon-svg svg{width:100%;height:100%;stroke-width:2;transition:all .2s ease}.avatar-icon{display:inline-block;width:28px;height:28px}.avatar-icon svg{width:100%;height:100%}.chat-header{background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);color:#fff;padding:1rem 1.25rem;display:flex;justify-content:space-between;align-items:center;grid-gap:1rem;gap:1rem;flex-wrap:wrap;box-shadow:0 2px 4px #0000001a}.chat-header .header-left{display:flex;align-items:center;grid-gap:.75rem;gap:.75rem;flex:1;min-width:200px}.chat-header .header-left h2{margin:0;font-size:1.25rem;font-weight:600;letter-spacing:-.01em}.chat-header .header-controls{display:flex;align-items:center;grid-gap:.5rem;gap:.5rem}.chat-header .header-controls .icon-svg{color:var(--icon-header)}.chat-header .status-indicator-icon{width:10px;height:10px;border-radius:50%;background:rgba(255,255,255,.4);transition:all .3s ease;box-shadow:0 0 0 2px #fff3;cursor:help}.chat-header .status-indicator-icon.transition-enabled{transition:background-color .4s cubic-bezier(.4,0,.2,1),box-shadow .4s cubic-bezier(.4,0,.2,1),transform .3s cubic-bezier(.4,0,.2,1)}.chat-header .status-indicator-icon.status-ready{background:#2ecc71;box-shadow:0 0 0 2px #2ecc714d,0 0 8px #2ecc7166}.chat-header .status-indicator-icon.status-ready.transition-enabled{animation:statusReady .5s cubic-bezier(.4,0,.2,1)}.chat-header .status-indicator-icon.status-error{background:#e74c3c;box-shadow:0 0 0 2px #e74c3c4d,0 0 8px #e74c3c66}.chat-header .status-indicator-icon.status-error.transition-enabled{animation:statusError .5s cubic-bezier(.4,0,.2,1)}.chat-header .status-indicator-icon.status-loading{background:#f39c12;box-shadow:0 0 0 2px #f39c124d;animation:pulse 1.5s ease-in-out infinite}.chat-header .status-indicator-icon.status-loading.transition-enabled{animation:pulse 1.5s ease-in-out infinite,statusLoading .5s cubic-bezier(.4,0,.2,1)}@keyframes pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(1.1)}}@keyframes statusReady{0%{transform:scale(.8);opacity:0}50%{transform:scale(1.2)}to{transform:scale(1);opacity:1}}@keyframes statusError{0%{transform:scale(.8);opacity:0}50%{transform:scale(1.15)}to{transform:scale(1);opacity:1}}@keyframes statusLoading{0%{transform:scale(.8) rotate(0);opacity:0}to{transform:scale(1) rotate(360deg);opacity:1}}.ai-chat-container{--animation-duration: .25s;--animation-easing: cubic-bezier(.4, 0, .2, 1)}.ai-chat-container.animation-speed-slow{--animation-duration: .5s}.ai-chat-container.animation-speed-slow *{transition-duration:.5s!important}.ai-chat-container.animation-speed-slow .status-indicator-icon.transition-enabled{transition-duration:.6s!important}.ai-chat-container.animation-speed-slow .message{animation-duration:.6s!important}.ai-chat-container.animation-speed-fast{--animation-duration: .15s}.ai-chat-container.animation-speed-fast *{transition-duration:.15s!important}.ai-chat-container.animation-speed-fast .status-indicator-icon.transition-enabled{transition-duration:.2s!important}.ai-chat-container.animation-speed-fast .message{animation-duration:.2s!important}.ai-chat-container.no-animations{--animation-duration: 0ms}.ai-chat-container.no-animations *,.ai-chat-container.no-animations *:before,.ai-chat-container.no-animations *:after{animation-duration:0ms!important;animation-delay:0ms!important;transition-duration:0ms!important;transition-delay:0ms!important}.ai-chat-container.no-animations .status-indicator-icon{animation:none!important;transition:none!important}.size-controls{display:flex;grid-gap:.5rem;gap:.5rem;background:transparent;padding:0;border-radius:0;backdrop-filter:none}.size-controls .size-button{width:24px!important;height:24px!important;padding:0!important}.size-controls .size-button .icon-svg{width:14px!important;height:14px!important}.control-button{background:transparent;border:none;border-radius:0;width:28px;height:28px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);color:#fff;padding:0}.control-button .icon-svg{width:18px;height:18px;color:var(--icon-header)}.control-button:hover:not(:disabled){opacity:.8;transform:scale(1.1)}.control-button:active:not(:disabled){transform:scale(.95)}.control-button.active{opacity:1;transform:scale(1.15)}.control-button:disabled{opacity:.4;cursor:not-allowed}.prominent-button{background:rgba(255,255,255,.2)!important;border-radius:6px!important;padding:6px 12px!important;width:auto!important;height:auto!important;grid-gap:6px;gap:6px;backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.3);font-size:13px;font-weight:500}.prominent-button .button-text{color:#fff;white-space:nowrap}.prominent-button svg{width:16px;height:16px}.prominent-button:hover:not(:disabled){background:rgba(255,255,255,.3)!important;transform:translateY(-1px);box-shadow:0 2px 8px #00000026}.prominent-button:active:not(:disabled){transform:translateY(0)}.fullscreen-button{background:transparent}.fullscreen-button:hover:not(:disabled){opacity:.8;transform:scale(1.1)}.clear-button{background:transparent}.clear-button:hover:not(:disabled){opacity:.8;transform:scale(1.1);color:#fcc}.chat-messages{flex:1;overflow-y:auto;overflow-x:hidden;padding:1.25rem;display:flex;flex-direction:column;grid-gap:.875rem;gap:.875rem;scroll-behavior:smooth;background:#f8f9fa}.chat-messages::-webkit-scrollbar{width:6px}.chat-messages::-webkit-scrollbar-track{background:transparent}.chat-messages::-webkit-scrollbar-thumb{background:rgba(0,0,0,.15);border-radius:3px}.chat-messages::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.25)}.message-wrapper{display:flex;flex-direction:column}.message{display:flex;max-width:75%;animation:fadeInSlide .25s cubic-bezier(.4,0,.2,1)}.message.user-message{align-self:flex-end;flex-direction:row-reverse}.message.user-message .message-content{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border-radius:18px 18px 4px;box-shadow:0 1px 2px #0000001a}.message.user-message .avatar-icon{color:var(--icon-avatar-user)}.message.ai-message{align-self:flex-start}.message.ai-message .message-content{background:white;color:#1a1a1a;border-radius:18px 18px 18px 4px;border:1px solid #e8e8e8;box-shadow:0 1px 2px #0000000d}.message.ai-message .avatar-icon{color:var(--icon-avatar-ai)}.message.loading-message{opacity:.7}.message.loading-message .message-content{font-style:italic}@keyframes fadeInSlide{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.message-content{padding:.75rem 1rem;margin:0 .5rem;word-wrap:break-word;max-width:100%;line-height:1.5;font-size:.9375rem}.message-timestamp{font-size:.6875rem;opacity:.65;margin-top:.375rem;text-align:right;font-weight:500}.message-avatar{width:36px;height:36px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.message-avatar .avatar-icon{opacity:.9}.loading-spinner{animation:spin 1.2s linear infinite;opacity:.7}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.chat-input{background:white;padding:1rem 1.25rem;border-top:1px solid #e8e8e8;display:flex;flex-direction:column;grid-gap:.75rem;gap:.75rem;box-shadow:0 -2px 8px #0000000a}.input-container{display:flex;grid-gap:.5rem;gap:.5rem;align-items:flex-end}.upload-buttons{display:flex;grid-gap:.5rem;gap:.5rem;flex-direction:column}.upload-button{background:#f5f5f5;border:1px solid #e0e0e0;border-radius:10px;width:42px;height:42px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1)}.upload-button .icon-svg{width:20px;height:20px;color:var(--icon-upload)}.upload-button:hover:not(:disabled){background:var(--icon-upload);border-color:var(--icon-upload);transform:translateY(-1px);box-shadow:0 2px 8px #667eea40}.upload-button:hover:not(:disabled) .icon-svg{color:#fff}.upload-button:active:not(:disabled){transform:translateY(0)}.upload-button:disabled{opacity:.4;cursor:not-allowed;background:#fafafa}.attachments-preview{display:flex;flex-wrap:wrap;grid-gap:.5rem;gap:.5rem;padding:.75rem;background:#f8f9fa;border-radius:10px;border:1px solid #e8e8e8}.attachment-item{display:flex;align-items:center;grid-gap:.625rem;gap:.625rem;background:white;border:1px solid #e0e0e0;border-radius:8px;padding:.625rem .875rem;font-size:.875rem;transition:all .2s ease}.attachment-item:hover{border-color:#667eea;box-shadow:0 2px 4px #667eea1a}.attachment-item .attachment-icon{width:20px;height:20px;color:#667eea;flex-shrink:0}.attachment-item .attachment-name{font-weight:500;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#1a1a1a}.attachment-item .attachment-size{color:#666;font-size:.75rem;font-weight:500}.attachment-item .remove-attachment{background:transparent;border:none;color:#999;cursor:pointer;padding:.25rem;margin-left:.25rem;transition:all .2s ease;display:flex;align-items:center;justify-content:center;border-radius:4px}.attachment-item .remove-attachment svg{width:16px;height:16px}.attachment-item .remove-attachment:hover{color:#e74c3c;background:rgba(231,76,60,.1)}.inquiry-textarea{flex:1;border:1.5px solid #e0e0e0;border-radius:22px;padding:.875rem 1.125rem;font-family:inherit;font-size:.9375rem;line-height:1.5;resize:none;outline:none;transition:all .2s cubic-bezier(.4,0,.2,1);background:#fafafa}.inquiry-textarea:focus{border-color:#667eea;background:white;box-shadow:0 0 0 3px #667eea14}.inquiry-textarea:disabled{background:#f5f5f5;cursor:not-allowed;opacity:.6}.inquiry-textarea::placeholder{color:#999}.send-button{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:50px;padding:.875rem 1.75rem;font-size:.9375rem;font-weight:600;cursor:pointer;display:flex;align-items:center;grid-gap:.5rem;gap:.5rem;transition:all .2s cubic-bezier(.4,0,.2,1);min-width:110px;justify-content:center;box-shadow:0 2px 8px #667eea40}.send-button .icon-svg{width:18px;height:18px;color:var(--icon-send)}.send-button .loading-icon{animation:spin 1.2s linear infinite}.send-button:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 4px 16px #667eea66}.send-button:active:not(:disabled){transform:translateY(0)}.send-button:disabled{background:#d0d0d0;cursor:not-allowed;box-shadow:none;opacity:.6}@media (max-width: 768px){.ai-chat-container{max-width:100%;border-radius:0;height:100vh}.ai-chat-container:not(.fullscreen){width:100%!important}.resize-handle{display:none}.size-controls{display:none}.chat-header{padding:.875rem 1rem}.chat-header .header-left h2{font-size:1.125rem}.chat-header .status-indicator-icon{width:8px;height:8px}.control-button{width:36px;height:36px}.control-button .icon-svg{width:18px;height:18px}.message{max-width:85%}.message-content{font-size:.875rem}.upload-buttons{flex-direction:row}.input-container{flex-wrap:wrap}.send-button{min-width:90px;padding:.75rem 1.25rem}.send-button .text{display:none}.chat-input{padding:.875rem 1rem}}@media (max-width: 480px){.chat-header{flex-direction:column;align-items:flex-start;grid-gap:.625rem;gap:.625rem}.chat-header .header-controls{width:100%;justify-content:space-between}.control-button{width:34px;height:34px}.control-button .icon-svg{width:16px;height:16px}.message-content{padding:.625rem .875rem;font-size:.875rem}.attachments-preview{flex-direction:column}.attachment-item{width:100%}.attachment-item .attachment-name{max-width:120px}.send-button{padding:.75rem 1rem;min-width:80px}}.control-button:focus,.upload-button:focus,.send-button:focus,.clear-button:focus{outline:3px solid #667eea;outline-offset:2px}@media (prefers-contrast: high){.control-button,.upload-button,.send-button{border:2px solid currentColor}.message-content{border:2px solid currentColor}}@media (prefers-reduced-motion: reduce){*{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}.theme-dark{background:#2c2c2c;--icon-primary: #818cf8;--icon-secondary: #9ca3af;--icon-avatar-user: #818cf8;--icon-avatar-ai: #a78bfa;--icon-header: #e5e7eb;--icon-upload: #818cf8;--icon-send: #ffffff;--icon-active: #818cf8;--icon-disabled: #4b5563;--icon-hover: #6366f1}.theme-dark .chat-header{background:linear-gradient(135deg,#1a1a1a,#333)}.theme-dark .chat-messages{background:#2c2c2c}.theme-dark .ai-message .message-content{background:#3a3a3a;color:#fff;border-color:#555}.theme-dark .chat-input{background:#3a3a3a;border-color:#555}.theme-dark .inquiry-textarea{background:#2c2c2c;color:#fff;border-color:#555}.theme-dark .inquiry-textarea:focus{border-color:#667eea}.theme-dark .attachments-preview{background:#3a3a3a;border-color:#555}.theme-dark .attachment-item{background:#2c2c2c;border-color:#555;color:#fff}.theme-dark .upload-button{background:rgba(255,255,255,.1);border-color:#fff3}.theme-dark .upload-button:hover:not(:disabled){background:rgba(255,255,255,.2)}.theme-blue{background:#e3f2fd;--icon-primary: #1976d2;--icon-secondary: #546e7a;--icon-avatar-user: #1976d2;--icon-avatar-ai: #0288d1;--icon-header: #ffffff;--icon-upload: #1976d2;--icon-send: #ffffff;--icon-active: #1976d2;--icon-disabled: #b0bec5;--icon-hover: #1565c0}.theme-blue .chat-header{background:linear-gradient(135deg,#1976d2,#42a5f5)}.theme-blue .user-message .message-content{background:linear-gradient(135deg,#1976d2,#42a5f5)}.theme-blue .ai-message .message-content{border-color:#bbdefb}.theme-blue .inquiry-textarea:focus{border-color:#1976d2}.theme-blue .send-button{background:linear-gradient(135deg,#1976d2,#42a5f5)}.theme-blue .upload-button{background:rgba(25,118,210,.1);border-color:#1976d24d}.theme-blue .upload-button:hover:not(:disabled){background:rgba(25,118,210,.2)}.theme-green{background:#e8f5e8;--icon-primary: #388e3c;--icon-secondary: #546e7a;--icon-avatar-user: #388e3c;--icon-avatar-ai: #2e7d32;--icon-header: #ffffff;--icon-upload: #388e3c;--icon-send: #ffffff;--icon-active: #388e3c;--icon-disabled: #b0bec5;--icon-hover: #2e7d32}.theme-green .chat-header{background:linear-gradient(135deg,#388e3c,#66bb6a)}.theme-green .user-message .message-content{background:linear-gradient(135deg,#388e3c,#66bb6a)}.theme-green .ai-message .message-content{border-color:#c8e6c9}.theme-green .inquiry-textarea:focus{border-color:#388e3c}.theme-green .send-button{background:linear-gradient(135deg,#388e3c,#66bb6a)}.theme-green .upload-button{background:rgba(56,142,60,.1);border-color:#388e3c4d}.theme-green .upload-button:hover:not(:disabled){background:rgba(56,142,60,.2)}.theme-purple{background:#f3e5f5;--icon-primary: #7b1fa2;--icon-secondary: #6a1b9a;--icon-avatar-user: #7b1fa2;--icon-avatar-ai: #8e24aa;--icon-header: #ffffff;--icon-upload: #7b1fa2;--icon-send: #ffffff;--icon-active: #7b1fa2;--icon-disabled: #ce93d8;--icon-hover: #6a1b9a}.theme-purple .chat-header{background:linear-gradient(135deg,#7b1fa2,#ab47bc)}.theme-purple .user-message .message-content{background:linear-gradient(135deg,#7b1fa2,#ab47bc)}.theme-purple .ai-message .message-content{border-color:#e1bee7}.theme-purple .inquiry-textarea:focus{border-color:#7b1fa2}.theme-purple .send-button{background:linear-gradient(135deg,#7b1fa2,#ab47bc)}.theme-purple .upload-button{background:rgba(123,31,162,.1);border-color:#7b1fa24d}.theme-purple .upload-button:hover:not(:disabled){background:rgba(123,31,162,.2)}.theme-minimal{background:#fafafa;--icon-primary: #333333;--icon-secondary: #757575;--icon-avatar-user: #424242;--icon-avatar-ai: #616161;--icon-header: #333333;--icon-upload: #424242;--icon-send: #ffffff;--icon-active: #333333;--icon-disabled: #bdbdbd;--icon-hover: #212121}.theme-minimal .chat-header{background:#fff;color:#333;border-bottom:1px solid #e0e0e0}.theme-minimal .user-message .message-content{background:#007bff;color:#fff;border-radius:18px}.theme-minimal .ai-message .message-content{background:#f8f9fa;color:#333;border:1px solid #dee2e6}.theme-minimal .send-button{background:#007bff;border-radius:4px}.theme-minimal .upload-button{background:rgba(0,123,255,.1);border-color:#007bff4d}.theme-minimal .upload-button:hover:not(:disabled){background:rgba(0,123,255,.2)}.theme-corporate{background:#f8f9fa}.theme-corporate .chat-header{background:linear-gradient(135deg,#495057,#6c757d)}.theme-corporate .user-message .message-content{background:#495057}.theme-corporate .ai-message .message-content{background:#fff;border-color:#dee2e6}.theme-corporate .inquiry-textarea:focus{border-color:#495057}.theme-corporate .send-button{background:#495057}.theme-corporate .upload-button{background:rgba(73,80,87,.1);border-color:#4950574d}.theme-corporate .upload-button:hover:not(:disabled){background:rgba(73,80,87,.2)}.theme-red{background:#ffebee}.theme-red .chat-header{background:linear-gradient(135deg,#d32f2f,#f44336)}.theme-red .user-message .message-content{background:linear-gradient(135deg,#d32f2f,#f44336)}.theme-red .ai-message .message-content{border-color:#ffcdd2}.theme-red .inquiry-textarea:focus{border-color:#d32f2f}.theme-red .send-button{background:linear-gradient(135deg,#d32f2f,#f44336)}.theme-red .upload-button{background:rgba(211,47,47,.1);border-color:#d32f2f4d}.theme-red .upload-button:hover:not(:disabled){background:rgba(211,47,47,.2)}.theme-yellow{background:#fffde7}.theme-yellow .chat-header{background:linear-gradient(135deg,#f57f17,#ffb300)}.theme-yellow .user-message .message-content{background:linear-gradient(135deg,#f57f17,#ffb300)}.theme-yellow .ai-message .message-content{border-color:#fff9c4}.theme-yellow .inquiry-textarea:focus{border-color:#f57f17}.theme-yellow .send-button{background:linear-gradient(135deg,#f57f17,#ffb300)}.theme-yellow .upload-button{background:rgba(245,127,23,.1);border-color:#f57f174d}.theme-yellow .upload-button:hover:not(:disabled){background:rgba(245,127,23,.2)}.theme-orange{background:#fff3e0}.theme-orange .chat-header{background:linear-gradient(135deg,#e65100,#ff9800)}.theme-orange .user-message .message-content{background:linear-gradient(135deg,#e65100,#ff9800)}.theme-orange .ai-message .message-content{border-color:#ffe0b2}.theme-orange .inquiry-textarea:focus{border-color:#e65100}.theme-orange .send-button{background:linear-gradient(135deg,#e65100,#ff9800)}.theme-orange .upload-button{background:rgba(230,81,0,.1);border-color:#e651004d}.theme-orange .upload-button:hover:not(:disabled){background:rgba(230,81,0,.2)}.confirmation-modal-backdrop{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:10000;animation:fadeIn .2s ease-out}.confirmation-modal{background:white;border-radius:12px;padding:24px;max-width:400px;width:90%;box-shadow:0 8px 32px #0003;animation:slideUp .3s ease-out;position:relative}.confirmation-modal .modal-icon{display:flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:50%;margin:0 auto 16px}.confirmation-modal .modal-icon svg{width:28px;height:28px}.confirmation-modal .modal-icon.warning-icon{background:rgba(255,152,0,.1);color:#ff9800}.confirmation-modal .modal-title{margin:0 0 12px;font-size:20px;font-weight:600;text-align:center;color:#1a1a1a}.confirmation-modal .modal-message{margin:0 0 24px;font-size:14px;line-height:1.5;text-align:center;color:#666}.confirmation-modal .modal-actions{display:flex;grid-gap:12px;gap:12px;justify-content:center}.confirmation-modal .modal-button{padding:10px 24px;border-radius:8px;border:none;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s ease;min-width:100px}.confirmation-modal .modal-button:focus{outline:2px solid #4a90e2;outline-offset:2px}.confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#4a90e2,#357abd);color:#fff}.confirmation-modal .modal-button.primary-button:hover{background:linear-gradient(135deg,#357abd,#2868a8);transform:translateY(-1px);box-shadow:0 4px 12px #4a90e24d}.confirmation-modal .modal-button.primary-button:active{transform:translateY(0)}.confirmation-modal .modal-button.secondary-button{background:#f5f5f5;color:#666}.confirmation-modal .modal-button.secondary-button:hover{background:#e0e0e0}.confirmation-modal .modal-button.secondary-button:active{background:#d5d5d5}.theme-modern .confirmation-modal{background:linear-gradient(135deg,#ffffff,#f8f9fa)}.theme-modern .confirmation-modal .modal-title{color:#2c3e50}.theme-modern .confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#4a90e2,#357abd)}.theme-dark .confirmation-modal{background:#2c2c2c}.theme-dark .confirmation-modal .modal-title{color:#fff}.theme-dark .confirmation-modal .modal-message{color:#b0b0b0}.theme-dark .confirmation-modal .modal-button.secondary-button{background:#3a3a3a;color:#b0b0b0}.theme-dark .confirmation-modal .modal-button.secondary-button:hover{background:#454545}.theme-light .confirmation-modal{background:white;box-shadow:0 8px 32px #0000001a}.theme-nature .confirmation-modal{background:linear-gradient(135deg,#f1f8e9,#ffffff)}.theme-nature .confirmation-modal .modal-icon.warning-icon{background:rgba(139,195,74,.1);color:#689f38}.theme-nature .confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#8bc34a,#689f38)}.theme-ocean .confirmation-modal{background:linear-gradient(135deg,#e0f7fa,#ffffff)}.theme-ocean .confirmation-modal .modal-icon.warning-icon{background:rgba(0,188,212,.1);color:#00acc1}.theme-ocean .confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#00bcd4,#00acc1)}.theme-sunset .confirmation-modal{background:linear-gradient(135deg,#fff3e0,#ffffff)}.theme-sunset .confirmation-modal .modal-icon.warning-icon{background:rgba(255,152,0,.1);color:#f57c00}.theme-sunset .confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#ff9800,#f57c00)}.theme-purple .confirmation-modal{background:linear-gradient(135deg,#f3e5f5,#ffffff)}.theme-purple .confirmation-modal .modal-icon.warning-icon{background:rgba(156,39,176,.1);color:#8e24aa}.theme-purple .confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#9c27b0,#7b1fa2)}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@media (max-width: 480px){.confirmation-modal{max-width:340px;padding:20px}.confirmation-modal .modal-actions{flex-direction:column}.confirmation-modal .modal-actions .modal-button{width:100%}}\n"], directives: [{ type: i4__namespace.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i4__namespace.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i4__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4__namespace.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5__namespace.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i5__namespace.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i5__namespace.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
2649
|
+
AiChatComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: AiChatComponent, selector: "emanate-ai-chat", inputs: { title: "title", placeholder: "placeholder", showDebugInfo: "showDebugInfo", apiUrl: "apiUrl", appKey: "appKey", appSource: "appSource", userId: "userId", firstName: "firstName", userName: "userName", templateDesign: "templateDesign", welcomeMessage: "welcomeMessage", historicalMessages: "historicalMessages", conversationId: "conversationId", enableImageUpload: "enableImageUpload", enableFileUpload: "enableFileUpload", iconSet: "iconSet", customIcons: "customIcons", enableAnimations: "enableAnimations", animationSpeed: "animationSpeed", enableStatusTransitions: "enableStatusTransitions", enableConversationLifecycle: "enableConversationLifecycle", enableAutoConversationRecovery: "enableAutoConversationRecovery", showCloseButton: "showCloseButton", showNewConversationButton: "showNewConversationButton", confirmNewConversation: "confirmNewConversation", newConversationConfirmMessage: "newConversationConfirmMessage" }, outputs: { messageReceived: "messageReceived", conversationStarted: "conversationStarted", messageSent: "messageSent", fileUploaded: "fileUploaded", sizeChanged: "sizeChanged" }, host: { listeners: { "document:keydown.escape": "handleEscapeKey($event)" } }, usesOnChanges: true, ngImport: i0__namespace, template: "<div class=\"ai-chat-container\" \r\n [ngClass]=\"getThemeClass()\" \r\n [ngStyle]=\"getContainerStyle()\"\r\n [class.fullscreen]=\"isFullscreen\"\r\n [class.resizing]=\"isResizing\"\r\n [class]=\"getAnimationClass()\">\r\n \r\n <!-- Resize Handles -->\r\n <div class=\"resize-handle resize-handle-right\" \r\n (mousedown)=\"startResize($event, 'width')\"\r\n *ngIf=\"!isFullscreen\"\r\n title=\"Drag to resize width\">\r\n </div>\r\n \r\n <div class=\"resize-handle resize-handle-corner\" \r\n (mousedown)=\"startResize($event, 'both')\"\r\n *ngIf=\"!isFullscreen\"\r\n title=\"Drag to resize\">\r\n </div>\r\n \r\n <!-- Debug Information (only shown when showDebugInfo is true) -->\r\n <div *ngIf=\"showDebugInfo\" class=\"debug-info\">\r\n <h3>DEBUG: AI Chat Component Loaded</h3>\r\n <p>Status: {{ configurationStatus || 'Loading...' }}</p>\r\n <p>Messages count: {{ messages.length || 0 }}</p>\r\n <p>Theme: {{ templateDesign || 'default' }}</p>\r\n <p>Size: {{ currentSize }} ({{ containerWidth }}x{{ containerHeight }})</p>\r\n </div>\r\n\r\n <div class=\"chat-header\">\r\n <div class=\"header-left\">\r\n <h2>{{ title }}</h2>\r\n <!-- Icon-only status indicator -->\r\n <div class=\"status-indicator-icon\" \r\n [ngClass]=\"{'status-ready': configurationStatus === 'AI Agent is ready' || configurationStatus === 'Ready', \r\n 'status-error': configurationStatus !== 'AI Agent is ready' && configurationStatus !== 'Ready' && configurationStatus !== 'Initializing...' && configurationStatus !== 'Testing connection...',\r\n 'status-loading': configurationStatus === 'Initializing...' || configurationStatus === 'Testing connection...',\r\n 'transition-enabled': enableStatusTransitions}\"\r\n [title]=\"configurationStatus\">\r\n </div>\r\n </div>\r\n \r\n <div class=\"header-controls\">\r\n <!-- New Conversation Button -->\r\n <button *ngIf=\"showNewConversationButton && enableConversationLifecycle && conversationId\" \r\n class=\"control-button new-conversation-button prominent-button\" \r\n [disabled]=\"isLoading\"\r\n (click)=\"startNewConversationExplicit()\"\r\n title=\"Start New Conversation\"\r\n attr.aria-label=\"Start New Conversation\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>\r\n <line x1=\"9\" y1=\"10\" x2=\"15\" y2=\"10\"></line>\r\n <line x1=\"12\" y1=\"7\" x2=\"12\" y2=\"13\"></line>\r\n </svg>\r\n <span class=\"button-text\">New Chat</span>\r\n </button>\r\n \r\n <!-- Close Conversation Button -->\r\n <button *ngIf=\"showCloseButton && enableConversationLifecycle && conversationId\" \r\n class=\"control-button close-button\" \r\n [disabled]=\"isLoading\"\r\n (click)=\"closeConversation('UserCompleted')\"\r\n title=\"Close Conversation\"\r\n attr.aria-label=\"Close Conversation\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n </button>\r\n \r\n <!-- Size Preset Buttons -->\r\n <div class=\"size-controls\" *ngIf=\"!isFullscreen\">\r\n <button class=\"control-button size-button\" \r\n (click)=\"applySizePreset('compact')\"\r\n [class.active]=\"currentSize === 'compact'\"\r\n title=\"Compact View\"\r\n attr.aria-label=\"Compact View\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.compactView\"></span>\r\n </button>\r\n <button class=\"control-button size-button\" \r\n (click)=\"applySizePreset('default')\"\r\n [class.active]=\"currentSize === 'default'\"\r\n title=\"Default View\"\r\n attr.aria-label=\"Default View\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.defaultView\"></span>\r\n </button>\r\n <button class=\"control-button size-button\" \r\n (click)=\"applySizePreset('expanded')\"\r\n [class.active]=\"currentSize === 'expanded'\"\r\n title=\"Expanded View\"\r\n attr.aria-label=\"Expanded View\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.expandedView\"></span>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chat-messages\" #messagesContainer>\r\n <div *ngFor=\"let message of messages; let i = index; trackBy: trackByIndex\" class=\"message-wrapper\">\r\n <!-- Message -->\r\n <div class=\"message\" \r\n [ngClass]=\"{'user-message': message.isUser, 'ai-message': !message.isUser, 'loading-message': message.isLoading}\">\r\n \r\n <div class=\"message-content\">\r\n <div [innerHTML]=\"message.content\"></div>\r\n <div class=\"message-timestamp\">{{ getFormattedTime(message.timestamp) }}</div>\r\n </div>\r\n \r\n <div class=\"message-avatar\">\r\n <span *ngIf=\"message.isUser\" class=\"avatar-icon\" [innerHTML]=\"sanitizedIcons.userAvatar\"></span>\r\n <span *ngIf=\"!message.isUser && !message.isLoading\" class=\"avatar-icon\" [innerHTML]=\"sanitizedIcons.aiAvatar\"></span>\r\n <span *ngIf=\"message.isLoading\" class=\"avatar-icon loading-spinner\" [innerHTML]=\"sanitizedIcons.loadingAvatar\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chat-input\">\r\n <!-- Attachments Preview -->\r\n <div class=\"attachments-preview\" *ngIf=\"selectedFiles.length > 0\">\r\n <div class=\"attachment-item\" *ngFor=\"let file of selectedFiles\">\r\n <svg class=\"attachment-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\"></path>\r\n </svg>\r\n <span class=\"attachment-name\">{{ file.name }}</span>\r\n <span class=\"attachment-size\">{{ getFileSizeFormatted(file.size) }}</span>\r\n <button class=\"remove-attachment\" (click)=\"removeAttachment(file.id)\" title=\"Remove\" attr.aria-label=\"Remove attachment\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n \r\n <div class=\"input-container\">\r\n <!-- File Upload Inputs (Hidden) -->\r\n <input type=\"file\" \r\n id=\"image-upload-input\" \r\n accept=\"image/*\" \r\n multiple \r\n (change)=\"onImageUpload($event)\"\r\n style=\"display: none;\"\r\n [disabled]=\"!enableImageUpload\">\r\n \r\n <input type=\"file\" \r\n id=\"file-upload-input\" \r\n accept=\".pdf,.doc,.docx,.txt,.csv\" \r\n multiple \r\n (change)=\"onFileUpload($event)\"\r\n style=\"display: none;\"\r\n [disabled]=\"!enableFileUpload\">\r\n \r\n <!-- Upload Buttons (Conditionally rendered) -->\r\n <div class=\"upload-buttons\" *ngIf=\"enableImageUpload || enableFileUpload\">\r\n <button *ngIf=\"enableImageUpload\" \r\n class=\"upload-button image-upload\" \r\n (click)=\"triggerImageUpload()\"\r\n [disabled]=\"isLoading\"\r\n title=\"Upload Image\"\r\n attr.aria-label=\"Upload Image\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.imageUpload\"></span>\r\n </button>\r\n \r\n <button *ngIf=\"enableFileUpload\" \r\n class=\"upload-button file-upload\" \r\n (click)=\"triggerFileUpload()\"\r\n [disabled]=\"isLoading\"\r\n title=\"Attach File\"\r\n attr.aria-label=\"Attach File\">\r\n <span class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.fileUpload\"></span>\r\n </button>\r\n </div>\r\n \r\n <textarea \r\n [(ngModel)]=\"currentInquiry\" \r\n (keypress)=\"onKeyPress($event)\"\r\n [placeholder]=\"placeholder\"\r\n rows=\"2\"\r\n [disabled]=\"isLoading\"\r\n class=\"inquiry-textarea\"\r\n attr.aria-label=\"Type your message\"></textarea>\r\n \r\n <button \r\n (click)=\"sendInquiry()\" \r\n [disabled]=\"!currentInquiry.trim() || isLoading\"\r\n class=\"send-button\"\r\n title=\"Send Message\"\r\n attr.aria-label=\"Send Message\">\r\n <span *ngIf=\"!isLoading\" class=\"icon-svg\" [innerHTML]=\"sanitizedIcons.send\"></span>\r\n <span *ngIf=\"isLoading\" class=\"icon-svg loading-icon\" [innerHTML]=\"sanitizedIcons.sendLoading\"></span>\r\n <span class=\"text\">{{ isLoading ? 'Sending...' : 'Send' }}</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Confirmation Modal -->\r\n <div class=\"confirmation-modal-backdrop\" \r\n *ngIf=\"showConfirmationModal\"\r\n (click)=\"cancelConfirmation()\">\r\n <div class=\"confirmation-modal\" \r\n [ngClass]=\"getThemeClass()\"\r\n (click)=\"$event.stopPropagation()\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n [attr.aria-labelledby]=\"'modal-title-' + conversationId\"\r\n [attr.aria-describedby]=\"'modal-description-' + conversationId\">\r\n \r\n <div class=\"modal-icon warning-icon\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"></path>\r\n <line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"></line>\r\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"></line>\r\n </svg>\r\n </div>\r\n \r\n <h3 class=\"modal-title\" [id]=\"'modal-title-' + conversationId\">Start New Conversation?</h3>\r\n \r\n <p class=\"modal-message\" [id]=\"'modal-description-' + conversationId\">\r\n {{ newConversationConfirmMessage }}\r\n </p>\r\n \r\n <div class=\"modal-actions\">\r\n <button class=\"modal-button secondary-button\" \r\n (click)=\"cancelConfirmation()\"\r\n type=\"button\"\r\n attr.aria-label=\"Cancel\">\r\n Cancel\r\n </button>\r\n <button class=\"modal-button primary-button\" \r\n (click)=\"onConfirmNewConversation()\"\r\n type=\"button\"\r\n attr.aria-label=\"Start New Conversation\">\r\n Start New Chat\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: ["@charset \"UTF-8\";.ai-chat-container{display:flex;flex-direction:column;height:100vh;max-width:800px;margin:0 auto;background:#ffffff;border-radius:12px;overflow:hidden;position:relative;transition:all .25s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 8px #00000014,0 4px 16px #0000000a;--icon-primary: #667eea;--icon-secondary: #6b7280;--icon-avatar-user: #667eea;--icon-avatar-ai: #764ba2;--icon-header: #ffffff;--icon-upload: #667eea;--icon-send: #ffffff;--icon-active: #667eea;--icon-disabled: #d1d5db;--icon-hover: #5568d3}.ai-chat-container.fullscreen{position:fixed!important;top:0!important;left:0!important;right:0!important;bottom:0!important;width:100vw!important;height:100vh!important;max-width:100vw!important;max-height:100vh!important;border-radius:0;z-index:99999;margin:0}.ai-chat-container.resizing{-webkit-user-select:none;user-select:none;cursor:nwse-resize;transition:none}.resize-handle{position:absolute;background:rgba(102,126,234,.3);transition:background .2s ease;z-index:10}.resize-handle:hover{background:rgba(102,126,234,.6)}.resize-handle.resize-handle-right{top:0;right:-4px;width:8px;height:100%;cursor:ew-resize}.resize-handle.resize-handle-corner{bottom:-4px;right:-4px;width:20px;height:20px;cursor:nwse-resize;border-radius:0 0 8px}.resize-handle.resize-handle-corner:after{content:\"\\22f0\";position:absolute;bottom:2px;right:2px;font-size:12px;color:#fffc}.debug-info{background:yellow;padding:10px;border:1px solid orange}.debug-info h3{margin:0;font-size:1.2rem}.debug-info p{margin:5px 0}.icon-svg{display:inline-block;width:20px;height:20px;color:var(--icon-secondary)}.icon-svg svg{width:100%;height:100%;stroke-width:2;transition:all .2s ease}.avatar-icon{display:inline-block;width:28px;height:28px}.avatar-icon svg{width:100%;height:100%}.chat-header{background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);color:#fff;padding:1rem 1.25rem;display:flex;justify-content:space-between;align-items:center;grid-gap:1rem;gap:1rem;flex-wrap:wrap;box-shadow:0 2px 4px #0000001a}.chat-header .header-left{display:flex;align-items:center;grid-gap:.75rem;gap:.75rem;flex:1;min-width:200px}.chat-header .header-left h2{margin:0;font-size:1.25rem;font-weight:600;letter-spacing:-.01em}.chat-header .header-controls{display:flex;align-items:center;grid-gap:.5rem;gap:.5rem}.chat-header .header-controls .icon-svg{color:var(--icon-header)}.chat-header .status-indicator-icon{width:10px;height:10px;border-radius:50%;background:rgba(255,255,255,.4);transition:all .3s ease;box-shadow:0 0 0 2px #fff3;cursor:help}.chat-header .status-indicator-icon.transition-enabled{transition:background-color .4s cubic-bezier(.4,0,.2,1),box-shadow .4s cubic-bezier(.4,0,.2,1),transform .3s cubic-bezier(.4,0,.2,1)}.chat-header .status-indicator-icon.status-ready{background:#2ecc71;box-shadow:0 0 0 2px #2ecc714d,0 0 8px #2ecc7166}.chat-header .status-indicator-icon.status-ready.transition-enabled{animation:statusReady .5s cubic-bezier(.4,0,.2,1)}.chat-header .status-indicator-icon.status-error{background:#e74c3c;box-shadow:0 0 0 2px #e74c3c4d,0 0 8px #e74c3c66}.chat-header .status-indicator-icon.status-error.transition-enabled{animation:statusError .5s cubic-bezier(.4,0,.2,1)}.chat-header .status-indicator-icon.status-loading{background:#f39c12;box-shadow:0 0 0 2px #f39c124d;animation:pulse 1.5s ease-in-out infinite}.chat-header .status-indicator-icon.status-loading.transition-enabled{animation:pulse 1.5s ease-in-out infinite,statusLoading .5s cubic-bezier(.4,0,.2,1)}@keyframes pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(1.1)}}@keyframes statusReady{0%{transform:scale(.8);opacity:0}50%{transform:scale(1.2)}to{transform:scale(1);opacity:1}}@keyframes statusError{0%{transform:scale(.8);opacity:0}50%{transform:scale(1.15)}to{transform:scale(1);opacity:1}}@keyframes statusLoading{0%{transform:scale(.8) rotate(0);opacity:0}to{transform:scale(1) rotate(360deg);opacity:1}}.ai-chat-container{--animation-duration: .25s;--animation-easing: cubic-bezier(.4, 0, .2, 1)}.ai-chat-container.animation-speed-slow{--animation-duration: .5s}.ai-chat-container.animation-speed-slow *{transition-duration:.5s!important}.ai-chat-container.animation-speed-slow .status-indicator-icon.transition-enabled{transition-duration:.6s!important}.ai-chat-container.animation-speed-slow .message{animation-duration:.6s!important}.ai-chat-container.animation-speed-fast{--animation-duration: .15s}.ai-chat-container.animation-speed-fast *{transition-duration:.15s!important}.ai-chat-container.animation-speed-fast .status-indicator-icon.transition-enabled{transition-duration:.2s!important}.ai-chat-container.animation-speed-fast .message{animation-duration:.2s!important}.ai-chat-container.no-animations{--animation-duration: 0ms}.ai-chat-container.no-animations *,.ai-chat-container.no-animations *:before,.ai-chat-container.no-animations *:after{animation-duration:0ms!important;animation-delay:0ms!important;transition-duration:0ms!important;transition-delay:0ms!important}.ai-chat-container.no-animations .status-indicator-icon{animation:none!important;transition:none!important}.size-controls{display:flex;grid-gap:.5rem;gap:.5rem;background:transparent;padding:0;border-radius:0;backdrop-filter:none}.size-controls .size-button{width:24px!important;height:24px!important;padding:0!important}.size-controls .size-button .icon-svg{width:14px!important;height:14px!important}.control-button{background:transparent;border:none;border-radius:0;width:28px;height:28px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);color:#fff;padding:0}.control-button .icon-svg{width:18px;height:18px;color:var(--icon-header)}.control-button:hover:not(:disabled){opacity:.8;transform:scale(1.1)}.control-button:active:not(:disabled){transform:scale(.95)}.control-button.active{opacity:1;transform:scale(1.15)}.control-button:disabled{opacity:.4;cursor:not-allowed}.prominent-button{background:rgba(255,255,255,.2)!important;border-radius:6px!important;padding:6px 12px!important;width:auto!important;height:auto!important;grid-gap:6px;gap:6px;backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.3);font-size:13px;font-weight:500}.prominent-button .button-text{color:#fff;white-space:nowrap}.prominent-button svg{width:16px;height:16px}.prominent-button:hover:not(:disabled){background:rgba(255,255,255,.3)!important;transform:translateY(-1px);box-shadow:0 2px 8px #00000026}.prominent-button:active:not(:disabled){transform:translateY(0)}.fullscreen-button{background:transparent}.fullscreen-button:hover:not(:disabled){opacity:.8;transform:scale(1.1)}.clear-button{background:transparent}.clear-button:hover:not(:disabled){opacity:.8;transform:scale(1.1);color:#fcc}.chat-messages{flex:1;overflow-y:auto;overflow-x:hidden;padding:1.25rem;display:flex;flex-direction:column;grid-gap:.875rem;gap:.875rem;scroll-behavior:smooth;background:#f8f9fa}.chat-messages::-webkit-scrollbar{width:6px}.chat-messages::-webkit-scrollbar-track{background:transparent}.chat-messages::-webkit-scrollbar-thumb{background:rgba(0,0,0,.15);border-radius:3px}.chat-messages::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.25)}.message-wrapper{display:flex;flex-direction:column}.message{display:flex;max-width:75%;animation:fadeInSlide .25s cubic-bezier(.4,0,.2,1)}.message.user-message{align-self:flex-end;flex-direction:row-reverse}.message.user-message .message-content{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border-radius:18px 18px 4px;box-shadow:0 1px 2px #0000001a}.message.user-message .avatar-icon{color:var(--icon-avatar-user)}.message.ai-message{align-self:flex-start}.message.ai-message .message-content{background:white;color:#1a1a1a;border-radius:18px 18px 18px 4px;border:1px solid #e8e8e8;box-shadow:0 1px 2px #0000000d}.message.ai-message .avatar-icon{color:var(--icon-avatar-ai)}.message.loading-message{opacity:.7}.message.loading-message .message-content{font-style:italic}@keyframes fadeInSlide{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.message-content{padding:.75rem 1rem;margin:0 .5rem;word-wrap:break-word;max-width:100%;line-height:1.5;font-size:.9375rem}.message-timestamp{font-size:.6875rem;opacity:.65;margin-top:.375rem;text-align:right;font-weight:500}.message-avatar{width:36px;height:36px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.message-avatar .avatar-icon{opacity:.9}.loading-spinner{animation:spin 1.2s linear infinite;opacity:.7}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.chat-input{background:white;padding:1rem 1.25rem;border-top:1px solid #e8e8e8;display:flex;flex-direction:column;grid-gap:.75rem;gap:.75rem;box-shadow:0 -2px 8px #0000000a}.input-container{display:flex;grid-gap:.5rem;gap:.5rem;align-items:flex-end}.upload-buttons{display:flex;grid-gap:.5rem;gap:.5rem;flex-direction:column}.upload-button{background:#f5f5f5;border:1px solid #e0e0e0;border-radius:10px;width:42px;height:42px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1)}.upload-button .icon-svg{width:20px;height:20px;color:var(--icon-upload)}.upload-button:hover:not(:disabled){background:var(--icon-upload);border-color:var(--icon-upload);transform:translateY(-1px);box-shadow:0 2px 8px #667eea40}.upload-button:hover:not(:disabled) .icon-svg{color:#fff}.upload-button:active:not(:disabled){transform:translateY(0)}.upload-button:disabled{opacity:.4;cursor:not-allowed;background:#fafafa}.attachments-preview{display:flex;flex-wrap:wrap;grid-gap:.5rem;gap:.5rem;padding:.75rem;background:#f8f9fa;border-radius:10px;border:1px solid #e8e8e8}.attachment-item{display:flex;align-items:center;grid-gap:.625rem;gap:.625rem;background:white;border:1px solid #e0e0e0;border-radius:8px;padding:.625rem .875rem;font-size:.875rem;transition:all .2s ease}.attachment-item:hover{border-color:#667eea;box-shadow:0 2px 4px #667eea1a}.attachment-item .attachment-icon{width:20px;height:20px;color:#667eea;flex-shrink:0}.attachment-item .attachment-name{font-weight:500;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#1a1a1a}.attachment-item .attachment-size{color:#666;font-size:.75rem;font-weight:500}.attachment-item .remove-attachment{background:transparent;border:none;color:#999;cursor:pointer;padding:.25rem;margin-left:.25rem;transition:all .2s ease;display:flex;align-items:center;justify-content:center;border-radius:4px}.attachment-item .remove-attachment svg{width:16px;height:16px}.attachment-item .remove-attachment:hover{color:#e74c3c;background:rgba(231,76,60,.1)}.inquiry-textarea{flex:1;border:1.5px solid #e0e0e0;border-radius:22px;padding:.875rem 1.125rem;font-family:inherit;font-size:.9375rem;line-height:1.5;resize:none;outline:none;transition:all .2s cubic-bezier(.4,0,.2,1);background:#fafafa}.inquiry-textarea:focus{border-color:#667eea;background:white;box-shadow:0 0 0 3px #667eea14}.inquiry-textarea:disabled{background:#f5f5f5;cursor:not-allowed;opacity:.6}.inquiry-textarea::placeholder{color:#999}.send-button{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:50px;padding:.875rem 1.75rem;font-size:.9375rem;font-weight:600;cursor:pointer;display:flex;align-items:center;grid-gap:.5rem;gap:.5rem;transition:all .2s cubic-bezier(.4,0,.2,1);min-width:110px;justify-content:center;box-shadow:0 2px 8px #667eea40}.send-button .icon-svg{width:18px;height:18px;color:var(--icon-send)}.send-button .loading-icon{animation:spin 1.2s linear infinite}.send-button:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 4px 16px #667eea66}.send-button:active:not(:disabled){transform:translateY(0)}.send-button:disabled{background:#d0d0d0;cursor:not-allowed;box-shadow:none;opacity:.6}@media (max-width: 768px){.ai-chat-container{max-width:100%;border-radius:0;height:100vh}.ai-chat-container:not(.fullscreen){width:100%!important}.resize-handle{display:none}.size-controls{display:none}.chat-header{padding:.875rem 1rem}.chat-header .header-left h2{font-size:1.125rem}.chat-header .status-indicator-icon{width:8px;height:8px}.control-button{width:36px;height:36px}.control-button .icon-svg{width:18px;height:18px}.message{max-width:85%}.message-content{font-size:.875rem}.upload-buttons{flex-direction:row}.input-container{flex-wrap:wrap}.send-button{min-width:90px;padding:.75rem 1.25rem}.send-button .text{display:none}.chat-input{padding:.875rem 1rem}}@media (max-width: 480px){.chat-header{flex-direction:column;align-items:flex-start;grid-gap:.625rem;gap:.625rem}.chat-header .header-controls{width:100%;justify-content:space-between}.control-button{width:34px;height:34px}.control-button .icon-svg{width:16px;height:16px}.message-content{padding:.625rem .875rem;font-size:.875rem}.attachments-preview{flex-direction:column}.attachment-item{width:100%}.attachment-item .attachment-name{max-width:120px}.send-button{padding:.75rem 1rem;min-width:80px}}.control-button:focus,.upload-button:focus,.send-button:focus,.clear-button:focus{outline:3px solid #667eea;outline-offset:2px}@media (prefers-contrast: high){.control-button,.upload-button,.send-button{border:2px solid currentColor}.message-content{border:2px solid currentColor}}@media (prefers-reduced-motion: reduce){*{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}.theme-dark{background:#2c2c2c;--icon-primary: #818cf8;--icon-secondary: #9ca3af;--icon-avatar-user: #818cf8;--icon-avatar-ai: #a78bfa;--icon-header: #e5e7eb;--icon-upload: #818cf8;--icon-send: #ffffff;--icon-active: #818cf8;--icon-disabled: #4b5563;--icon-hover: #6366f1}.theme-dark .chat-header{background:linear-gradient(135deg,#1a1a1a,#333)}.theme-dark .chat-messages{background:#2c2c2c}.theme-dark .ai-message .message-content{background:#3a3a3a;color:#fff;border-color:#555}.theme-dark .chat-input{background:#3a3a3a;border-color:#555}.theme-dark .inquiry-textarea{background:#2c2c2c;color:#fff;border-color:#555}.theme-dark .inquiry-textarea:focus{border-color:#667eea}.theme-dark .attachments-preview{background:#3a3a3a;border-color:#555}.theme-dark .attachment-item{background:#2c2c2c;border-color:#555;color:#fff}.theme-dark .upload-button{background:rgba(255,255,255,.1);border-color:#fff3}.theme-dark .upload-button:hover:not(:disabled){background:rgba(255,255,255,.2)}.theme-blue{background:#e3f2fd;--icon-primary: #1976d2;--icon-secondary: #546e7a;--icon-avatar-user: #1976d2;--icon-avatar-ai: #0288d1;--icon-header: #ffffff;--icon-upload: #1976d2;--icon-send: #ffffff;--icon-active: #1976d2;--icon-disabled: #b0bec5;--icon-hover: #1565c0}.theme-blue .chat-header{background:linear-gradient(135deg,#1976d2,#42a5f5)}.theme-blue .user-message .message-content{background:linear-gradient(135deg,#1976d2,#42a5f5)}.theme-blue .ai-message .message-content{border-color:#bbdefb}.theme-blue .inquiry-textarea:focus{border-color:#1976d2}.theme-blue .send-button{background:linear-gradient(135deg,#1976d2,#42a5f5)}.theme-blue .upload-button{background:rgba(25,118,210,.1);border-color:#1976d24d}.theme-blue .upload-button:hover:not(:disabled){background:rgba(25,118,210,.2)}.theme-green{background:#e8f5e8;--icon-primary: #388e3c;--icon-secondary: #546e7a;--icon-avatar-user: #388e3c;--icon-avatar-ai: #2e7d32;--icon-header: #ffffff;--icon-upload: #388e3c;--icon-send: #ffffff;--icon-active: #388e3c;--icon-disabled: #b0bec5;--icon-hover: #2e7d32}.theme-green .chat-header{background:linear-gradient(135deg,#388e3c,#66bb6a)}.theme-green .user-message .message-content{background:linear-gradient(135deg,#388e3c,#66bb6a)}.theme-green .ai-message .message-content{border-color:#c8e6c9}.theme-green .inquiry-textarea:focus{border-color:#388e3c}.theme-green .send-button{background:linear-gradient(135deg,#388e3c,#66bb6a)}.theme-green .upload-button{background:rgba(56,142,60,.1);border-color:#388e3c4d}.theme-green .upload-button:hover:not(:disabled){background:rgba(56,142,60,.2)}.theme-purple{background:#f3e5f5;--icon-primary: #7b1fa2;--icon-secondary: #6a1b9a;--icon-avatar-user: #7b1fa2;--icon-avatar-ai: #8e24aa;--icon-header: #ffffff;--icon-upload: #7b1fa2;--icon-send: #ffffff;--icon-active: #7b1fa2;--icon-disabled: #ce93d8;--icon-hover: #6a1b9a}.theme-purple .chat-header{background:linear-gradient(135deg,#7b1fa2,#ab47bc)}.theme-purple .user-message .message-content{background:linear-gradient(135deg,#7b1fa2,#ab47bc)}.theme-purple .ai-message .message-content{border-color:#e1bee7}.theme-purple .inquiry-textarea:focus{border-color:#7b1fa2}.theme-purple .send-button{background:linear-gradient(135deg,#7b1fa2,#ab47bc)}.theme-purple .upload-button{background:rgba(123,31,162,.1);border-color:#7b1fa24d}.theme-purple .upload-button:hover:not(:disabled){background:rgba(123,31,162,.2)}.theme-minimal{background:#fafafa;--icon-primary: #333333;--icon-secondary: #757575;--icon-avatar-user: #424242;--icon-avatar-ai: #616161;--icon-header: #333333;--icon-upload: #424242;--icon-send: #ffffff;--icon-active: #333333;--icon-disabled: #bdbdbd;--icon-hover: #212121}.theme-minimal .chat-header{background:#fff;color:#333;border-bottom:1px solid #e0e0e0}.theme-minimal .user-message .message-content{background:#007bff;color:#fff;border-radius:18px}.theme-minimal .ai-message .message-content{background:#f8f9fa;color:#333;border:1px solid #dee2e6}.theme-minimal .send-button{background:#007bff;border-radius:4px}.theme-minimal .upload-button{background:rgba(0,123,255,.1);border-color:#007bff4d}.theme-minimal .upload-button:hover:not(:disabled){background:rgba(0,123,255,.2)}.theme-corporate{background:#f8f9fa}.theme-corporate .chat-header{background:linear-gradient(135deg,#495057,#6c757d)}.theme-corporate .user-message .message-content{background:#495057}.theme-corporate .ai-message .message-content{background:#fff;border-color:#dee2e6}.theme-corporate .inquiry-textarea:focus{border-color:#495057}.theme-corporate .send-button{background:#495057}.theme-corporate .upload-button{background:rgba(73,80,87,.1);border-color:#4950574d}.theme-corporate .upload-button:hover:not(:disabled){background:rgba(73,80,87,.2)}.theme-red{background:#ffebee}.theme-red .chat-header{background:linear-gradient(135deg,#d32f2f,#f44336)}.theme-red .user-message .message-content{background:linear-gradient(135deg,#d32f2f,#f44336)}.theme-red .ai-message .message-content{border-color:#ffcdd2}.theme-red .inquiry-textarea:focus{border-color:#d32f2f}.theme-red .send-button{background:linear-gradient(135deg,#d32f2f,#f44336)}.theme-red .upload-button{background:rgba(211,47,47,.1);border-color:#d32f2f4d}.theme-red .upload-button:hover:not(:disabled){background:rgba(211,47,47,.2)}.theme-yellow{background:#fffde7}.theme-yellow .chat-header{background:linear-gradient(135deg,#f57f17,#ffb300)}.theme-yellow .user-message .message-content{background:linear-gradient(135deg,#f57f17,#ffb300)}.theme-yellow .ai-message .message-content{border-color:#fff9c4}.theme-yellow .inquiry-textarea:focus{border-color:#f57f17}.theme-yellow .send-button{background:linear-gradient(135deg,#f57f17,#ffb300)}.theme-yellow .upload-button{background:rgba(245,127,23,.1);border-color:#f57f174d}.theme-yellow .upload-button:hover:not(:disabled){background:rgba(245,127,23,.2)}.theme-orange{background:#fff3e0}.theme-orange .chat-header{background:linear-gradient(135deg,#e65100,#ff9800)}.theme-orange .user-message .message-content{background:linear-gradient(135deg,#e65100,#ff9800)}.theme-orange .ai-message .message-content{border-color:#ffe0b2}.theme-orange .inquiry-textarea:focus{border-color:#e65100}.theme-orange .send-button{background:linear-gradient(135deg,#e65100,#ff9800)}.theme-orange .upload-button{background:rgba(230,81,0,.1);border-color:#e651004d}.theme-orange .upload-button:hover:not(:disabled){background:rgba(230,81,0,.2)}.confirmation-modal-backdrop{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:10000;animation:fadeIn .2s ease-out}.confirmation-modal{background:white;border-radius:12px;padding:24px;max-width:400px;width:90%;box-shadow:0 8px 32px #0003;animation:slideUp .3s ease-out;position:relative}.confirmation-modal .modal-icon{display:flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:50%;margin:0 auto 16px}.confirmation-modal .modal-icon svg{width:28px;height:28px}.confirmation-modal .modal-icon.warning-icon{background:rgba(255,152,0,.1);color:#ff9800}.confirmation-modal .modal-title{margin:0 0 12px;font-size:20px;font-weight:600;text-align:center;color:#1a1a1a}.confirmation-modal .modal-message{margin:0 0 24px;font-size:14px;line-height:1.5;text-align:center;color:#666}.confirmation-modal .modal-actions{display:flex;grid-gap:12px;gap:12px;justify-content:center}.confirmation-modal .modal-button{padding:10px 24px;border-radius:8px;border:none;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s ease;min-width:100px}.confirmation-modal .modal-button:focus{outline:2px solid #4a90e2;outline-offset:2px}.confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#4a90e2,#357abd);color:#fff}.confirmation-modal .modal-button.primary-button:hover{background:linear-gradient(135deg,#357abd,#2868a8);transform:translateY(-1px);box-shadow:0 4px 12px #4a90e24d}.confirmation-modal .modal-button.primary-button:active{transform:translateY(0)}.confirmation-modal .modal-button.secondary-button{background:#f5f5f5;color:#666}.confirmation-modal .modal-button.secondary-button:hover{background:#e0e0e0}.confirmation-modal .modal-button.secondary-button:active{background:#d5d5d5}.theme-modern .confirmation-modal{background:linear-gradient(135deg,#ffffff,#f8f9fa)}.theme-modern .confirmation-modal .modal-title{color:#2c3e50}.theme-modern .confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#4a90e2,#357abd)}.theme-dark .confirmation-modal{background:#2c2c2c}.theme-dark .confirmation-modal .modal-title{color:#fff}.theme-dark .confirmation-modal .modal-message{color:#b0b0b0}.theme-dark .confirmation-modal .modal-button.secondary-button{background:#3a3a3a;color:#b0b0b0}.theme-dark .confirmation-modal .modal-button.secondary-button:hover{background:#454545}.theme-light .confirmation-modal{background:white;box-shadow:0 8px 32px #0000001a}.theme-nature .confirmation-modal{background:linear-gradient(135deg,#f1f8e9,#ffffff)}.theme-nature .confirmation-modal .modal-icon.warning-icon{background:rgba(139,195,74,.1);color:#689f38}.theme-nature .confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#8bc34a,#689f38)}.theme-ocean .confirmation-modal{background:linear-gradient(135deg,#e0f7fa,#ffffff)}.theme-ocean .confirmation-modal .modal-icon.warning-icon{background:rgba(0,188,212,.1);color:#00acc1}.theme-ocean .confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#00bcd4,#00acc1)}.theme-sunset .confirmation-modal{background:linear-gradient(135deg,#fff3e0,#ffffff)}.theme-sunset .confirmation-modal .modal-icon.warning-icon{background:rgba(255,152,0,.1);color:#f57c00}.theme-sunset .confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#ff9800,#f57c00)}.theme-purple .confirmation-modal{background:linear-gradient(135deg,#f3e5f5,#ffffff)}.theme-purple .confirmation-modal .modal-icon.warning-icon{background:rgba(156,39,176,.1);color:#8e24aa}.theme-purple .confirmation-modal .modal-button.primary-button{background:linear-gradient(135deg,#9c27b0,#7b1fa2)}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@media (max-width: 480px){.confirmation-modal{max-width:340px;padding:20px}.confirmation-modal .modal-actions{flex-direction:column}.confirmation-modal .modal-actions .modal-button{width:100%}}\n"], directives: [{ type: i4__namespace.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i4__namespace.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i4__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4__namespace.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5__namespace.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i5__namespace.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i5__namespace.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
2395
2650
|
i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0__namespace, type: AiChatComponent, decorators: [{
|
|
2396
2651
|
type: i0.Component,
|
|
2397
2652
|
args: [{
|