@acorex/components 22.1.0-next.14 → 22.1.0-next.16

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.
@@ -51,8 +51,11 @@ import { HttpClient } from '@angular/common/http';
51
51
  import { DomSanitizer } from '@angular/platform-browser';
52
52
 
53
53
  /**
54
+
54
55
  * Shared API Types
56
+
55
57
  * Common types used across all API services
58
+
56
59
  */
57
60
 
58
61
  /**
@@ -61,18 +64,12 @@ import { DomSanitizer } from '@angular/platform-browser';
61
64
  */
62
65
 
63
66
  /**
64
-
65
67
  * Default Configuration Values
66
-
67
68
  * Centralized defaults to avoid magic numbers throughout the codebase
68
-
69
69
  */
70
70
  /**
71
-
72
71
  * Default conversation configuration
73
-
74
72
  * All values are explicitly defined here for easy maintenance and documentation
75
-
76
73
  */
77
74
  const AX_DEFAULT_CONVERSATION_CONFIG = {
78
75
  // Pagination
@@ -83,7 +80,8 @@ const AX_DEFAULT_CONVERSATION_CONFIG = {
83
80
  infiniteScrollThreshold: 200,
84
81
  // Timeout Durations (milliseconds)
85
82
  typingIndicatorTimeout: 3000,
86
- typingIndicatorThrottle: 1000,
83
+ typingIndicatorThrottle: 3000,
84
+ typingDisplayDuration: 4000,
87
85
  messageHighlightDuration: 2000,
88
86
  debounceSearch: 300,
89
87
  // Message Storage Limits
@@ -102,7 +100,7 @@ const AX_DEFAULT_CONVERSATION_CONFIG = {
102
100
  maxFilesPerMessage: 3,
103
101
  // Intersection Observer
104
102
  messageReadThreshold: 0.3,
105
- messageReadDebounce: 400,
103
+ messageReadDebounce: 3000,
106
104
  markConversationReadOnSelect: true,
107
105
  // Message list
108
106
  messageListBackground: '',
@@ -112,15 +110,10 @@ const AX_DEFAULT_CONVERSATION_CONFIG = {
112
110
  debugApiLogging: false,
113
111
  };
114
112
  /**
115
-
116
113
  * Helper function to merge user config with defaults
117
-
118
114
  * Properly handles array merging to avoid reference issues
119
-
120
115
  * @param userConfig - User-provided configuration
121
-
122
116
  * @returns Merged configuration with all required fields
123
-
124
117
  */
125
118
  function mergeWithDefaults(userConfig) {
126
119
  if (!userConfig) {
@@ -525,220 +518,87 @@ function resolveConversationMessageFileType(type, fileType) {
525
518
  return fileType ?? AX_CONVERSATION_MESSAGE_TYPE_FILE_TYPE[type];
526
519
  }
527
520
 
521
+ /**
522
+ * Message Utilities Service
523
+ * Helper functions for message formatting and display
524
+ */
528
525
  class AXConversationMessageUtilsService {
529
- /**
530
- * Normalize optional avatar/icon values so empty or whitespace-only strings
531
- * are treated as missing data.
532
- */
533
- static normalizeOptionalMediaValue(value) {
534
- if (typeof value !== 'string') {
535
- return undefined;
536
- }
537
- const normalized = value.trim();
538
- return normalized.length > 0 ? normalized : undefined;
539
- }
540
- /**
541
- * Get conversation avatar image URL.
542
- */
543
- static getConversationAvatar(conversation) {
544
- return AXConversationMessageUtilsService.normalizeOptionalMediaValue(conversation.avatar);
526
+ static getInitials(name) {
527
+ const parts = name.trim().split(/\s+/).filter(Boolean);
528
+ if (parts.length === 0)
529
+ return '?';
530
+ if (parts.length === 1)
531
+ return parts[0].charAt(0).toUpperCase();
532
+ return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
545
533
  }
546
- /**
547
- * Font Awesome icon class(es) for a conversation when there is no avatar image.
548
- */
549
- static getConversationAvatarIcon(conversation) {
550
- if (AXConversationMessageUtilsService.getConversationAvatar(conversation)) {
551
- return undefined;
552
- }
553
- const explicit = AXConversationMessageUtilsService.normalizeOptionalMediaValue(conversation.icon);
554
- if (explicit) {
555
- return explicit;
556
- }
557
- if (conversation.type === 'group') {
558
- return AX_CONVERSATION_DEFAULT_GROUP_ICON;
534
+ static getMessageText(message) {
535
+ const payload = message.payload;
536
+ if (!payload)
537
+ return '';
538
+ if (payload.type === 'text' && 'text' in payload && typeof payload.text === 'string') {
539
+ return payload.text;
559
540
  }
560
- if (conversation.type === 'private' || conversation.type === 'bot') {
561
- return AX_CONVERSATION_DEFAULT_USER_ICON;
541
+ if ('caption' in payload && typeof payload.caption === 'string') {
542
+ return payload.caption;
562
543
  }
563
- return undefined;
544
+ return '';
564
545
  }
565
- /**
566
- * Font Awesome icon for a participant when there is no avatar image.
567
- */
568
- static getParticipantAvatarIcon(participant) {
569
- if (AXConversationMessageUtilsService.normalizeOptionalMediaValue(participant?.avatar)) {
570
- return undefined;
546
+ static getPreviewText(message, maxLength) {
547
+ const type = message.type;
548
+ let text = AXConversationMessageUtilsService.getMessageText(message);
549
+ if (maxLength && text.length > maxLength) {
550
+ text = text.substring(0, maxLength) + '...';
571
551
  }
572
- const explicit = AXConversationMessageUtilsService.normalizeOptionalMediaValue(participant?.icon);
573
- if (explicit) {
574
- return explicit;
552
+ switch (type) {
553
+ case 'image':
554
+ return { value: text, type: 'image', icon: 'fa-light fa-image' };
555
+ case 'video':
556
+ return { value: text, type: 'video', icon: 'fa-light fa-video' };
557
+ case 'audio':
558
+ case 'voice':
559
+ return { value: text, type: type, icon: 'fa-light fa-microphone' };
560
+ case 'file':
561
+ return { value: text, type: 'file', icon: 'fa-light fa-file' };
562
+ case 'location':
563
+ return { value: text, type: 'location', icon: 'fa-light fa-location-dot' };
564
+ case 'sticker':
565
+ return { value: text, type: 'sticker', icon: 'fa-light fa-note-sticky' };
566
+ default:
567
+ return { value: text, type: 'text', icon: 'fa-light fa-message' };
575
568
  }
576
- return AX_CONVERSATION_DEFAULT_USER_ICON;
577
569
  }
578
- /**
579
- * Get sender name from message
580
- */
570
+ static isOwnMessage(message, currentUserId) {
571
+ return message.senderId === currentUserId;
572
+ }
581
573
  static getSenderName(message, conversation) {
582
574
  const participant = conversation.participants.find((p) => p.id === message.senderId);
583
- return participant?.name || translateSync('@acorex:chat.fallbacks.unknown-user');
575
+ return participant?.name ?? translateSync('@acorex:chat.fallbacks.unknown-user');
584
576
  }
585
- /**
586
- * Get sender avatar image URL (takes precedence over {@link getSenderAvatarIcon}).
587
- */
588
577
  static getSenderAvatar(message, conversation) {
589
- const participant = conversation.participants.find((p) => p.id === message.senderId);
590
- return AXConversationMessageUtilsService.normalizeOptionalMediaValue(participant?.avatar);
578
+ return conversation.participants.find((p) => p.id === message.senderId)?.avatar;
591
579
  }
592
- /**
593
- * Font Awesome icon class(es) for the sender when there is no avatar image:
594
- * participant `icon` first, then conversation-level `icon`.
595
- */
596
580
  static getSenderAvatarIcon(message, conversation) {
597
- const participant = conversation.participants.find((p) => p.id === message.senderId);
598
- if (AXConversationMessageUtilsService.normalizeOptionalMediaValue(participant?.avatar)) {
599
- return undefined;
600
- }
601
- return (AXConversationMessageUtilsService.getParticipantAvatarIcon(participant) ??
602
- AXConversationMessageUtilsService.getConversationAvatarIcon(conversation));
581
+ return conversation.participants.find((p) => p.id === message.senderId)?.icon;
603
582
  }
604
- /**
605
- * Get initials from name
606
- */
607
- static getInitials(name) {
608
- if (!name)
609
- return '?';
610
- return name
611
- .split(' ')
612
- .map((n) => n[0])
613
- .join('')
614
- .toUpperCase()
615
- .substring(0, 2);
583
+ static getConversationAvatar(conversation) {
584
+ const avatar = conversation.avatar?.trim();
585
+ return avatar && avatar.length > 0 ? avatar : undefined;
616
586
  }
617
- /**
618
- * Type guard for text payload
619
- */
620
- static isTextPayload(payload) {
621
- return 'text' in payload && typeof payload.text === 'string';
587
+ static getConversationAvatarIcon(conversation) {
588
+ const icon = conversation.icon?.trim();
589
+ return icon && icon.length > 0 ? icon : undefined;
622
590
  }
623
- /**
624
- * Get message text content
625
- */
626
- static getMessageText(message) {
627
- if (message.type === 'text' && AXConversationMessageUtilsService.isTextPayload(message.payload)) {
628
- return message.payload.text;
629
- }
630
- return `[${message.type}]`;
591
+ static getStatusIcon(message) {
592
+ return AXConversationMessageUtilsService.getDeliveryStatusIcon(message.status);
631
593
  }
632
- /**
633
- * Format message preview text
634
- */
635
- static getPreviewText(message, maxLength = 50) {
636
- // Handle different message types
637
- switch (message.type) {
638
- case 'text': {
639
- const textPayload = message.payload;
640
- const text = textPayload.text || '';
641
- const truncatedText = text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
642
- return {
643
- value: truncatedText,
644
- type: 'text',
645
- icon: 'fa-light fa-message',
646
- };
647
- }
648
- case 'image': {
649
- const imagePayload = message.payload;
650
- const images = Array.isArray(imagePayload.images) ? imagePayload.images : [];
651
- const first = images[0];
652
- const label = imagePayload.caption?.trim() ||
653
- (images.length > 1 ? `${images.length} images` : '');
654
- return {
655
- value: label || first?.thumbnailUrl || first?.url || '',
656
- type: 'image',
657
- icon: 'fa-light fa-image',
658
- };
659
- }
660
- case 'video': {
661
- const videoPayload = message.payload;
662
- const videos = Array.isArray(videoPayload.videos) ? videoPayload.videos : [];
663
- const first = videos[0];
664
- const label = videoPayload.caption?.trim() ||
665
- (videos.length > 1 ? `${videos.length} videos` : '');
666
- return {
667
- value: label || first?.url || '',
668
- type: 'video',
669
- icon: 'fa-light fa-video',
670
- };
671
- }
672
- case 'audio': {
673
- const audioPayload = message.payload;
674
- const audios = Array.isArray(audioPayload.audios) ? audioPayload.audios : [];
675
- const names = audios.map((a) => a.title).filter(Boolean).join(', ');
676
- const first = audios[0];
677
- const label = audioPayload.caption?.trim() ||
678
- (audios.length > 1 ? `${audios.length} audio files` : names);
679
- return {
680
- value: label || first?.url || '',
681
- type: 'audio',
682
- icon: 'fa-light fa-music',
683
- };
684
- }
685
- case 'voice': {
686
- const voicePayload = message.payload;
687
- return {
688
- value: voicePayload.url || '',
689
- type: 'voice',
690
- icon: 'fa-light fa-microphone',
691
- };
692
- }
693
- case 'file': {
694
- const filePayload = message.payload;
695
- const files = Array.isArray(filePayload.files) ? filePayload.files : [];
696
- const names = files.map((f) => f.name).join(', ');
697
- const label = filePayload.caption?.trim() ||
698
- (files.length > 1 ? `${files.length} files` : names);
699
- return {
700
- value: label || names,
701
- type: 'file',
702
- icon: 'fa-light fa-file',
703
- };
704
- }
705
- case 'location': {
706
- const locationPayload = message.payload;
707
- return {
708
- value: locationPayload.latitude && locationPayload.longitude
709
- ? `${locationPayload.latitude},${locationPayload.longitude}`
710
- : '',
711
- type: 'location',
712
- icon: 'fa-light fa-location-dot',
713
- };
714
- }
715
- case 'sticker': {
716
- const stickerPayload = message.payload;
717
- return {
718
- value: stickerPayload.url || '',
719
- type: 'sticker',
720
- icon: 'fa-light fa-face-smile',
721
- };
722
- }
723
- default:
724
- return {
725
- value: '',
726
- type: message.type,
727
- icon: 'fa-light fa-message',
728
- };
594
+ static getConversationStatus(conversation, presence) {
595
+ if (conversation.type !== 'private') {
596
+ return undefined;
729
597
  }
598
+ return presence?.status;
730
599
  }
731
- /**
732
- * Check if message is from current user
733
- */
734
- static isOwnMessage(message, currentUserId) {
735
- return message.senderId === currentUserId;
736
- }
737
- /**
738
- * Get message status icon class (Font Awesome)
739
- */
740
- static getStatusIcon(message) {
741
- switch (message.status) {
600
+ static getDeliveryStatusIcon(status) {
601
+ switch (status) {
742
602
  case 'sending':
743
603
  return 'fa-light fa-clock';
744
604
  case 'sent':
@@ -750,67 +610,34 @@ class AXConversationMessageUtilsService {
750
610
  case 'failed':
751
611
  return 'fa-light fa-circle-exclamation';
752
612
  default:
753
- return 'fa-light fa-check';
754
- }
755
- }
756
- /**
757
- * Check if message should show avatar
758
- */
759
- static shouldShowAvatar(message, previousMessage, conversation) {
760
- // Always show avatar for group conversations
761
- if (conversation.type === 'group' || conversation.type === 'channel') {
762
- // Don't show if same sender as previous message within 5 minutes
763
- if (previousMessage && previousMessage.senderId === message.senderId) {
764
- const timeDiff = message.timestamp.getTime() - previousMessage.timestamp.getTime();
765
- return timeDiff > 5 * 60 * 1000; // 5 minutes
766
- }
767
- return true;
613
+ return '';
768
614
  }
769
- return false;
770
615
  }
771
- /**
772
- * Group messages by sender for consecutive messages
773
- */
774
- static shouldGroupWithPrevious(message, previousMessage) {
616
+ static shouldGroupMessages(message, previousMessage) {
775
617
  if (!previousMessage)
776
618
  return false;
777
- // Same sender
778
619
  if (message.senderId !== previousMessage.senderId)
779
620
  return false;
780
- // Within 5 minutes
781
621
  const timeDiff = message.timestamp.getTime() - previousMessage.timestamp.getTime();
782
622
  return timeDiff < 5 * 60 * 1000;
783
623
  }
784
- /**
785
- * Get conversation status for avatar (private conversations only)
786
- */
787
- static getConversationStatus(conversation) {
788
- if (conversation.type === 'private') {
789
- return conversation.status.presence;
790
- }
791
- return undefined;
624
+ static getUserPresenceStatus(presence) {
625
+ return presence?.status;
792
626
  }
793
- /**
794
- * Get typing indicator text for conversation
795
- */
796
- static getTypingText(conversation) {
797
- const typingUsers = conversation.status.typingUsers;
798
- if (typingUsers.length === 0)
627
+ static getTypingText(conversation, typingUserIds) {
628
+ if (typingUserIds.length === 0)
799
629
  return '';
800
630
  if (conversation.type === 'private') {
801
631
  return translateSync('@acorex:chat.status.typing');
802
632
  }
803
- const firstUser = conversation.participants.find((p) => p.id === typingUsers[0]);
804
- if (typingUsers.length === 1) {
633
+ const firstUser = conversation.participants.find((p) => p.id === typingUserIds[0]);
634
+ if (typingUserIds.length === 1) {
805
635
  return translateSync('@acorex:chat.status.user-is-typing', {
806
636
  params: { userName: firstUser?.name || translateSync('@acorex:chat.fallbacks.someone') },
807
637
  });
808
638
  }
809
- return translateSync('@acorex:chat.status.people-typing', { params: { count: typingUsers.length } });
639
+ return translateSync('@acorex:chat.status.people-typing', { params: { count: typingUserIds.length } });
810
640
  }
811
- /**
812
- * Format last seen time
813
- */
814
641
  static formatLastSeen(date) {
815
642
  const now = new Date();
816
643
  const diff = now.getTime() - date.getTime();
@@ -825,24 +652,26 @@ class AXConversationMessageUtilsService {
825
652
  return translateSync('@acorex:chat.time.days-ago', { params: { count: Math.floor(seconds / 86400) } });
826
653
  return date.toLocaleDateString();
827
654
  }
828
- /**
829
- * Get conversation subtitle (status or member count)
830
- */
831
- static getConversationSubtitle(conversation) {
832
- if (conversation.status.isTyping) {
833
- return AXConversationMessageUtilsService.getTypingText(conversation);
655
+ static getPrivateChatSubtitle(conversation, presence, currentUserId) {
656
+ const peerPresence = presence;
657
+ if (peerPresence?.status === 'online') {
658
+ return translateSync('@acorex:chat.status.online');
659
+ }
660
+ if (peerPresence?.lastSeen) {
661
+ return translateSync('@acorex:chat.status.last-seen', {
662
+ params: { value: AXConversationMessageUtilsService.formatLastSeen(peerPresence.lastSeen) },
663
+ });
664
+ }
665
+ return translateSync('@acorex:chat.status.offline');
666
+ }
667
+ static getConversationSubtitle(conversation, options) {
668
+ const typingUserIds = options?.typingUserIds ?? [];
669
+ if (typingUserIds.length > 0) {
670
+ return AXConversationMessageUtilsService.getTypingText(conversation, typingUserIds);
834
671
  }
835
672
  switch (conversation.type) {
836
673
  case 'private':
837
- if (conversation.status.presence === 'online') {
838
- return translateSync('@acorex:chat.status.online');
839
- }
840
- if (conversation.status.lastSeen) {
841
- return translateSync('@acorex:chat.status.last-seen', {
842
- params: { value: AXConversationMessageUtilsService.formatLastSeen(conversation.status.lastSeen) },
843
- });
844
- }
845
- return translateSync('@acorex:chat.status.offline');
674
+ return AXConversationMessageUtilsService.getPrivateChatSubtitle(conversation, options?.peerPresence, options?.currentUserId);
846
675
  case 'group':
847
676
  return translateSync('@acorex:chat.members.count', { params: { count: conversation.participants.length } });
848
677
  case 'channel':
@@ -1473,6 +1302,24 @@ async function toUploaderReference$2(payload) {
1473
1302
  return mod.toUploaderReference(payload);
1474
1303
  }
1475
1304
 
1305
+ /**
1306
+ * Per-user preferences for a specific conversation (mute, notifications, etc.).
1307
+ * Stored on the user account, keyed by conversation ID — not on the room entity.
1308
+ */
1309
+ const AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES = {
1310
+ notifications: true,
1311
+ showPreview: true,
1312
+ };
1313
+
1314
+ function mergeRoomPreferences(preferences) {
1315
+ return {
1316
+ ...AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES,
1317
+ ...preferences,
1318
+ notifications: preferences?.notifications ?? AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES.notifications,
1319
+ showPreview: preferences?.showPreview ?? AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES.showPreview,
1320
+ };
1321
+ }
1322
+
1476
1323
  /**
1477
1324
  * In-memory conversation and message graph (signal-based).
1478
1325
  * Plain class — not DI-registered; instantiated by `AXConversationService`.
@@ -1485,6 +1332,9 @@ class AXConversationState {
1485
1332
  bumpInboxRevision() {
1486
1333
  this._inboxRevision.update((revision) => revision + 1);
1487
1334
  }
1335
+ bumpTypingRevision() {
1336
+ this._typingRevision.update((revision) => revision + 1);
1337
+ }
1488
1338
  constructor(config) {
1489
1339
  this.config = config;
1490
1340
  this._conversations = signal(new Map(), /* @ts-ignore */
@@ -1493,15 +1343,34 @@ class AXConversationState {
1493
1343
  ...(ngDevMode ? [{ debugName: "_messages" }] : /* istanbul ignore next */ []));
1494
1344
  this._conversationMessages = signal(new Map(), /* @ts-ignore */
1495
1345
  ...(ngDevMode ? [{ debugName: "_conversationMessages" }] : /* istanbul ignore next */ []));
1496
- /** Bumped on every inbox mutation so derived lists always recompute. */
1346
+ this._userPresence = signal(new Map(), /* @ts-ignore */
1347
+ ...(ngDevMode ? [{ debugName: "_userPresence" }] : /* istanbul ignore next */ []));
1348
+ this._typingExpiry = signal(new Map(), /* @ts-ignore */
1349
+ ...(ngDevMode ? [{ debugName: "_typingExpiry" }] : /* istanbul ignore next */ []));
1350
+ this._roomPreferences = signal(new Map(), /* @ts-ignore */
1351
+ ...(ngDevMode ? [{ debugName: "_roomPreferences" }] : /* istanbul ignore next */ []));
1352
+ this._presenceTimeTick = signal(0, /* @ts-ignore */
1353
+ ...(ngDevMode ? [{ debugName: "_presenceTimeTick" }] : /* istanbul ignore next */ []));
1354
+ this._typingRevision = signal(0, /* @ts-ignore */
1355
+ ...(ngDevMode ? [{ debugName: "_typingRevision" }] : /* istanbul ignore next */ []));
1497
1356
  this._inboxRevision = signal(0, /* @ts-ignore */
1498
1357
  ...(ngDevMode ? [{ debugName: "_inboxRevision" }] : /* istanbul ignore next */ []));
1499
1358
  this.conversations = computed(() => {
1500
1359
  this._inboxRevision();
1501
- const convMap = this._conversations();
1502
- return Array.from(convMap.values());
1360
+ return Array.from(this._conversations().values());
1503
1361
  }, /* @ts-ignore */
1504
1362
  ...(ngDevMode ? [{ debugName: "conversations" }] : /* istanbul ignore next */ []));
1363
+ this.userPresenceMap = computed(() => this._userPresence(), /* @ts-ignore */
1364
+ ...(ngDevMode ? [{ debugName: "userPresenceMap" }] : /* istanbul ignore next */ []));
1365
+ this.presenceTimeTick = this._presenceTimeTick.asReadonly();
1366
+ this.typingRevision = computed(() => {
1367
+ this._typingRevision();
1368
+ return this._typingExpiry();
1369
+ }, /* @ts-ignore */
1370
+ ...(ngDevMode ? [{ debugName: "typingRevision" }] : /* istanbul ignore next */ []));
1371
+ }
1372
+ bumpPresenceTimeTick() {
1373
+ this._presenceTimeTick.update((tick) => tick + 1);
1505
1374
  }
1506
1375
  setConversations(conversations) {
1507
1376
  const convMap = new Map();
@@ -1560,6 +1429,12 @@ class AXConversationState {
1560
1429
  newMap.delete(conversationId);
1561
1430
  return newMap;
1562
1431
  });
1432
+ this._typingExpiry.update((map) => {
1433
+ const next = new Map(map);
1434
+ next.delete(conversationId);
1435
+ return next;
1436
+ });
1437
+ this.bumpTypingRevision();
1563
1438
  }
1564
1439
  updateLastMessage(message) {
1565
1440
  this.updateConversation(message.conversationId, {
@@ -1577,15 +1452,6 @@ class AXConversationState {
1577
1452
  resetUnreadCount(conversationId) {
1578
1453
  this.updateConversation(conversationId, { unreadCount: 0 });
1579
1454
  }
1580
- updateSettings(conversationId, settings) {
1581
- const conversation = this._conversations().get(conversationId);
1582
- if (!conversation)
1583
- return;
1584
- this.updateConversation(conversationId, {
1585
- settings: { ...conversation.settings, ...settings },
1586
- updatedAt: new Date(),
1587
- });
1588
- }
1589
1455
  updateTitle(conversationId, title) {
1590
1456
  this.updateConversation(conversationId, { title, updatedAt: new Date() });
1591
1457
  }
@@ -1598,42 +1464,141 @@ class AXConversationState {
1598
1464
  updatedAt: new Date(),
1599
1465
  });
1600
1466
  }
1601
- updateTypingIndicator(conversationId, userId, isTyping) {
1602
- const conversation = this._conversations().get(conversationId);
1603
- if (!conversation)
1604
- return;
1605
- let typingUsers = [...conversation.status.typingUsers];
1606
- if (isTyping) {
1607
- if (!typingUsers.includes(userId)) {
1608
- typingUsers.push(userId);
1467
+ updateUserPresence(update) {
1468
+ const lastSeen = update.lastSeen instanceof Date
1469
+ ? update.lastSeen
1470
+ : update.lastSeen
1471
+ ? new Date(update.lastSeen)
1472
+ : undefined;
1473
+ this._userPresence.update((map) => {
1474
+ const next = new Map(map);
1475
+ next.set(update.userId, {
1476
+ userId: update.userId,
1477
+ status: update.status,
1478
+ lastSeen,
1479
+ statusText: update.statusText,
1480
+ updatedAt: new Date(),
1481
+ });
1482
+ return next;
1483
+ });
1484
+ }
1485
+ bulkSetUserPresence(updates) {
1486
+ if (updates.length === 0)
1487
+ return;
1488
+ this._userPresence.update((map) => {
1489
+ const next = new Map(map);
1490
+ for (const update of updates) {
1491
+ const lastSeen = update.lastSeen instanceof Date
1492
+ ? update.lastSeen
1493
+ : update.lastSeen
1494
+ ? new Date(update.lastSeen)
1495
+ : undefined;
1496
+ next.set(update.userId, {
1497
+ userId: update.userId,
1498
+ status: update.status,
1499
+ lastSeen,
1500
+ statusText: update.statusText,
1501
+ updatedAt: new Date(),
1502
+ });
1609
1503
  }
1610
- }
1611
- else {
1612
- typingUsers = typingUsers.filter((id) => id !== userId);
1613
- }
1614
- this.updateConversation(conversationId, {
1615
- status: {
1616
- ...conversation.status,
1617
- isTyping: typingUsers.length > 0,
1618
- typingUsers,
1619
- },
1504
+ return next;
1620
1505
  });
1621
1506
  }
1622
- updateParticipantPresence(userId, status, lastSeen) {
1623
- this._conversations.update((conversations) => {
1624
- const newConversations = new Map(conversations);
1625
- for (const [id, conv] of conversations) {
1626
- const participant = conv.participants.find((p) => p.id === userId);
1627
- if (participant) {
1628
- const updatedConversation = {
1629
- ...conv,
1630
- participants: conv.participants.map((p) => (p.id === userId ? { ...p, status, lastSeen } : p)),
1631
- status: conv.type === 'private' ? { ...conv.status, presence: status, lastSeen } : conv.status,
1632
- };
1633
- newConversations.set(id, updatedConversation);
1507
+ getUserPresence(userId) {
1508
+ return this._userPresence().get(userId);
1509
+ }
1510
+ setTypingActive(conversationId, userId, displayDurationMs) {
1511
+ const expiresAt = Date.now() + displayDurationMs;
1512
+ this._typingExpiry.update((map) => {
1513
+ const next = new Map(map);
1514
+ const room = new Map(next.get(conversationId) ?? []);
1515
+ room.set(userId, expiresAt);
1516
+ next.set(conversationId, room);
1517
+ return next;
1518
+ });
1519
+ this.bumpTypingRevision();
1520
+ }
1521
+ clearTypingUser(conversationId, userId) {
1522
+ this._typingExpiry.update((map) => {
1523
+ const room = map.get(conversationId);
1524
+ if (!room?.has(userId)) {
1525
+ return map;
1526
+ }
1527
+ const next = new Map(map);
1528
+ const nextRoom = new Map(room);
1529
+ nextRoom.delete(userId);
1530
+ if (nextRoom.size === 0) {
1531
+ next.delete(conversationId);
1532
+ }
1533
+ else {
1534
+ next.set(conversationId, nextRoom);
1535
+ }
1536
+ return next;
1537
+ });
1538
+ this.bumpTypingRevision();
1539
+ }
1540
+ getActiveTypingUserIds(conversationId) {
1541
+ const now = Date.now();
1542
+ const room = this._typingExpiry().get(conversationId);
1543
+ if (!room)
1544
+ return [];
1545
+ const active = [];
1546
+ for (const [userId, expiresAt] of room) {
1547
+ if (expiresAt > now) {
1548
+ active.push(userId);
1549
+ }
1550
+ }
1551
+ return active;
1552
+ }
1553
+ isAnyoneTyping(conversationId) {
1554
+ return this.getActiveTypingUserIds(conversationId).length > 0;
1555
+ }
1556
+ pruneExpiredTyping() {
1557
+ const now = Date.now();
1558
+ let changed = false;
1559
+ this._typingExpiry.update((map) => {
1560
+ const next = new Map();
1561
+ for (const [conversationId, room] of map) {
1562
+ const activeRoom = new Map();
1563
+ for (const [userId, expiresAt] of room) {
1564
+ if (expiresAt > now) {
1565
+ activeRoom.set(userId, expiresAt);
1566
+ }
1567
+ else {
1568
+ changed = true;
1569
+ }
1570
+ }
1571
+ if (activeRoom.size > 0) {
1572
+ next.set(conversationId, activeRoom);
1573
+ }
1574
+ else if (room.size > 0) {
1575
+ changed = true;
1634
1576
  }
1635
1577
  }
1636
- return newConversations;
1578
+ return changed ? next : map;
1579
+ });
1580
+ if (changed) {
1581
+ this.bumpTypingRevision();
1582
+ }
1583
+ }
1584
+ setRoomPreferencesBulk(preferences) {
1585
+ this._roomPreferences.update(() => {
1586
+ const next = new Map();
1587
+ for (const [conversationId, prefs] of Object.entries(preferences)) {
1588
+ next.set(conversationId, mergeRoomPreferences(prefs));
1589
+ }
1590
+ return next;
1591
+ });
1592
+ }
1593
+ getRoomPreferences(conversationId) {
1594
+ return this._roomPreferences().get(conversationId) ?? { ...AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES };
1595
+ }
1596
+ updateRoomPreferences(conversationId, updates) {
1597
+ this._roomPreferences.update((map) => {
1598
+ const next = new Map(map);
1599
+ const current = next.get(conversationId) ?? { ...AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES };
1600
+ next.set(conversationId, mergeRoomPreferences({ ...current, ...updates }));
1601
+ return next;
1637
1602
  });
1638
1603
  }
1639
1604
  addMessage(message) {
@@ -1660,9 +1625,6 @@ class AXConversationState {
1660
1625
  return newMap;
1661
1626
  });
1662
1627
  }
1663
- /**
1664
- * Replace all messages for a conversation (initial page load).
1665
- */
1666
1628
  setConversationMessages(conversationId, messages) {
1667
1629
  const sorted = [...messages]
1668
1630
  .map(withNormalizedPayload)
@@ -3213,6 +3175,8 @@ class AXConversationService {
3213
3175
  ...(ngDevMode ? [{ debugName: "_loading" }] : /* istanbul ignore next */ []));
3214
3176
  this._loadingActiveMessages = signal(false, /* @ts-ignore */
3215
3177
  ...(ngDevMode ? [{ debugName: "_loadingActiveMessages" }] : /* istanbul ignore next */ []));
3178
+ this._isForwardingMessage = signal(false, /* @ts-ignore */
3179
+ ...(ngDevMode ? [{ debugName: "_isForwardingMessage" }] : /* istanbul ignore next */ []));
3216
3180
  this._error = signal(null, /* @ts-ignore */
3217
3181
  ...(ngDevMode ? [{ debugName: "_error" }] : /* istanbul ignore next */ []));
3218
3182
  this._conversationsPagination = signal({ page: 0, hasMore: true }, /* @ts-ignore */
@@ -3255,6 +3219,8 @@ class AXConversationService {
3255
3219
  this.loading = this._loading.asReadonly();
3256
3220
  /** Loading state for the active conversation's message history */
3257
3221
  this.loadingActiveMessages = this._loadingActiveMessages.asReadonly();
3222
+ /** Whether a message forward operation is in progress. */
3223
+ this.isForwardingMessage = this._isForwardingMessage.asReadonly();
3258
3224
  /** Sidebar conversation list pagination */
3259
3225
  this.conversationsPagination = this._conversationsPagination.asReadonly();
3260
3226
  /** Active conversation message pagination */
@@ -3283,6 +3249,15 @@ class AXConversationService {
3283
3249
  this._currentUser = signal(null, /* @ts-ignore */
3284
3250
  ...(ngDevMode ? [{ debugName: "_currentUser" }] : /* istanbul ignore next */ []));
3285
3251
  this.currentUser = this._currentUser.asReadonly();
3252
+ this.userPresenceMap = computed(() => this.state.userPresenceMap(), /* @ts-ignore */
3253
+ ...(ngDevMode ? [{ debugName: "userPresenceMap" }] : /* istanbul ignore next */ []));
3254
+ this.presenceTimeTick = computed(() => {
3255
+ this.state.presenceTimeTick();
3256
+ return this.state.userPresenceMap();
3257
+ }, /* @ts-ignore */
3258
+ ...(ngDevMode ? [{ debugName: "presenceTimeTick" }] : /* istanbul ignore next */ []));
3259
+ this.typingRevision = computed(() => this.state.typingRevision(), /* @ts-ignore */
3260
+ ...(ngDevMode ? [{ debugName: "typingRevision" }] : /* istanbul ignore next */ []));
3286
3261
  /** One-time async initialization (connect, user, conversations, realtime). */
3287
3262
  this.initPromise = null;
3288
3263
  /** Generation counter — stale page-0 loads are ignored after conversation switches. */
@@ -3291,9 +3266,12 @@ class AXConversationService {
3291
3266
  this.conversationListLoadGeneration = 0;
3292
3267
  /** Batched read-receipt queue keyed by conversation ID. */
3293
3268
  this.readQueue = new Map();
3269
+ this.isTypingActiveForConversation = false;
3294
3270
  /** Session cache for available reaction emojis. */
3295
3271
  this.availableReactionsCache = null;
3296
3272
  this.availableReactionsPromise = null;
3273
+ this.presenceTickHandle = setInterval(() => this.state.bumpPresenceTimeTick(), 60_000);
3274
+ this.typingPruneHandle = setInterval(() => this.state.pruneExpiredTyping(), 1_000);
3297
3275
  this.destroyRef.onDestroy(() => {
3298
3276
  this._conversationSwitch$.next();
3299
3277
  this._conversationSwitch$.complete();
@@ -3302,7 +3280,17 @@ class AXConversationService {
3302
3280
  if (this.readFlushHandle) {
3303
3281
  clearTimeout(this.readFlushHandle);
3304
3282
  }
3283
+ if (this.presenceTickHandle) {
3284
+ clearInterval(this.presenceTickHandle);
3285
+ }
3286
+ if (this.typingPruneHandle) {
3287
+ clearInterval(this.typingPruneHandle);
3288
+ }
3289
+ if (this.typingStopHandle) {
3290
+ clearTimeout(this.typingStopHandle);
3291
+ }
3305
3292
  void this.flushReadQueue();
3293
+ void this.userApi.updatePresence('offline').catch(() => undefined);
3306
3294
  });
3307
3295
  }
3308
3296
  /** Log and invoke an async API method from AXConversationService. */
@@ -3337,10 +3325,16 @@ class AXConversationService {
3337
3325
  // Load current user
3338
3326
  const currentUser = await this.callApi('initializeService', 'userApi', 'getCurrentUser', () => this.userApi.getCurrentUser());
3339
3327
  this._currentUser.set(currentUser);
3328
+ if (currentUser.conversationPreferences) {
3329
+ this.state.setRoomPreferencesBulk(currentUser.conversationPreferences);
3330
+ }
3340
3331
  // Subscribe to real-time events
3341
3332
  this.subscribeToEvents();
3333
+ void this.userApi.updatePresence('online').catch(() => undefined);
3342
3334
  // Load initial data
3343
3335
  await this.loadConversations();
3336
+ await this.hydrateUserPresence();
3337
+ await this.loadRoomPreferences();
3344
3338
  }
3345
3339
  catch (error) {
3346
3340
  const handledError = this.errorHandler.handle(error, 'initializeService');
@@ -3428,6 +3422,113 @@ class AXConversationService {
3428
3422
  this.handleNewMessage(message);
3429
3423
  this._messageReceived$.next(message);
3430
3424
  });
3425
+ this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToMessageReactions');
3426
+ this.realtimeApi
3427
+ .subscribeToMessageReactions()
3428
+ .pipe(takeUntil(this.destroy$), catchError((error) => {
3429
+ this.errorHandler.handle(error, 'subscribeToMessageReactions');
3430
+ return EMPTY;
3431
+ }))
3432
+ .subscribe((message) => {
3433
+ this.handleMessageUpdate(message);
3434
+ this._messageUpdated$.next(message);
3435
+ });
3436
+ this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToConversationCreated');
3437
+ this.realtimeApi
3438
+ .subscribeToConversationCreated()
3439
+ .pipe(takeUntil(this.destroy$), catchError((error) => {
3440
+ this.errorHandler.handle(error, 'subscribeToConversationCreated');
3441
+ return EMPTY;
3442
+ }))
3443
+ .subscribe((conversation) => {
3444
+ this.handleConversationCreated(conversation);
3445
+ });
3446
+ this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToConversationDeleted');
3447
+ this.realtimeApi
3448
+ .subscribeToConversationDeleted()
3449
+ .pipe(takeUntil(this.destroy$), catchError((error) => {
3450
+ this.errorHandler.handle(error, 'subscribeToConversationDeleted');
3451
+ return EMPTY;
3452
+ }))
3453
+ .subscribe((conversationId) => {
3454
+ this.handleConversationDeleted(conversationId);
3455
+ });
3456
+ this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToReadReceipts');
3457
+ this.realtimeApi
3458
+ .subscribeToReadReceipts()
3459
+ .pipe(takeUntil(this.destroy$), catchError((error) => {
3460
+ this.errorHandler.handle(error, 'subscribeToReadReceipts');
3461
+ return EMPTY;
3462
+ }))
3463
+ .subscribe((receipt) => {
3464
+ this.handleReadReceipt(receipt);
3465
+ });
3466
+ this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToMessageStatusChanges');
3467
+ this.realtimeApi
3468
+ .subscribeToMessageStatusChanges()
3469
+ .pipe(takeUntil(this.destroy$), catchError((error) => {
3470
+ this.errorHandler.handle(error, 'subscribeToMessageStatusChanges');
3471
+ return EMPTY;
3472
+ }))
3473
+ .subscribe((change) => {
3474
+ this.handleMessageStatusChange(change);
3475
+ });
3476
+ this.logApi('subscribeToEvents', 'realtimeApi', 'subscribeToConversationSettingsChanges');
3477
+ this.realtimeApi
3478
+ .subscribeToConversationSettingsChanges()
3479
+ .pipe(takeUntil(this.destroy$), catchError((error) => {
3480
+ this.errorHandler.handle(error, 'subscribeToConversationSettingsChanges');
3481
+ return EMPTY;
3482
+ }))
3483
+ .subscribe((change) => {
3484
+ this.handleRoomPreferencesChange(change);
3485
+ });
3486
+ }
3487
+ getUserPresence(userId) {
3488
+ return this.state.getUserPresence(userId);
3489
+ }
3490
+ getRoomPreferences(conversationId) {
3491
+ return this.state.getRoomPreferences(conversationId);
3492
+ }
3493
+ isAnyoneTyping(conversationId) {
3494
+ return this.state.isAnyoneTyping(conversationId);
3495
+ }
3496
+ getActiveTypingUserIds(conversationId) {
3497
+ return this.state.getActiveTypingUserIds(conversationId);
3498
+ }
3499
+ getPeerPresence(conversation) {
3500
+ const peerId = resolveConversationPeerUserId(conversation, this._currentUser()?.id);
3501
+ return peerId ? this.getUserPresence(peerId) : undefined;
3502
+ }
3503
+ async hydrateUserPresence() {
3504
+ const currentUserId = this._currentUser()?.id;
3505
+ const userIds = new Set();
3506
+ for (const conversation of this.state.conversations()) {
3507
+ for (const participant of conversation.participants) {
3508
+ if (participant.id !== currentUserId) {
3509
+ userIds.add(participant.id);
3510
+ }
3511
+ }
3512
+ }
3513
+ if (userIds.size === 0) {
3514
+ return;
3515
+ }
3516
+ try {
3517
+ const updates = await this.callApi('hydrateUserPresence', 'userApi', 'getUsersPresence', () => this.userApi.getUsersPresence([...userIds]), [...userIds]);
3518
+ this.state.bulkSetUserPresence(updates);
3519
+ }
3520
+ catch (error) {
3521
+ this.errorHandler.handle(error, 'hydrateUserPresence');
3522
+ }
3523
+ }
3524
+ async loadRoomPreferences() {
3525
+ try {
3526
+ const preferences = await this.callApi('loadRoomPreferences', 'userApi', 'getConversationPreferences', () => this.userApi.getConversationPreferences());
3527
+ this.state.setRoomPreferencesBulk(preferences);
3528
+ }
3529
+ catch (error) {
3530
+ this.errorHandler.handle(error, 'loadRoomPreferences');
3531
+ }
3431
3532
  }
3432
3533
  /**
3433
3534
  * Load conversations from server
@@ -3455,6 +3556,7 @@ class AXConversationService {
3455
3556
  hasMore: result.hasMore,
3456
3557
  nextCursor: result.nextCursor,
3457
3558
  });
3559
+ await this.hydrateUserPresence();
3458
3560
  }
3459
3561
  catch (error) {
3460
3562
  const handledError = this.errorHandler.handle(error, 'loadConversations');
@@ -3497,16 +3599,22 @@ class AXConversationService {
3497
3599
  */
3498
3600
  async selectConversation(conversationId) {
3499
3601
  await this.ensureInitialized();
3602
+ const isAlreadyActive = this._activeConversationId() === conversationId;
3603
+ const hasCachedMessages = this.state.getConversationMessages(conversationId).length > 0;
3500
3604
  try {
3501
- this._conversationSwitch$.next();
3502
- this.messageLoadGeneration++;
3503
- this._activeConversationId.set(conversationId);
3504
- this._loadingActiveMessages.set(true);
3505
- try {
3506
- await this.loadMessages(conversationId, 0);
3507
- }
3508
- finally {
3509
- this._loadingActiveMessages.set(false);
3605
+ if (!isAlreadyActive) {
3606
+ this._conversationSwitch$.next();
3607
+ this.messageLoadGeneration++;
3608
+ this._activeConversationId.set(conversationId);
3609
+ }
3610
+ if (!isAlreadyActive || !hasCachedMessages) {
3611
+ this._loadingActiveMessages.set(true);
3612
+ try {
3613
+ await this.loadMessages(conversationId, 0);
3614
+ }
3615
+ finally {
3616
+ this._loadingActiveMessages.set(false);
3617
+ }
3510
3618
  }
3511
3619
  if (this.config.markConversationReadOnSelect) {
3512
3620
  const conversation = this.state.getConversation(conversationId);
@@ -3545,7 +3653,12 @@ class AXConversationService {
3545
3653
  return empty;
3546
3654
  }
3547
3655
  if (page === 0) {
3548
- this.state.setConversationMessages(conversationId, result.items);
3656
+ const pendingLocal = this.state
3657
+ .getConversationMessages(conversationId)
3658
+ .filter((m) => m.isLocal || m.status === 'sending');
3659
+ const serverIds = new Set(result.items.map((m) => m.id));
3660
+ const localsToKeep = pendingLocal.filter((m) => !serverIds.has(m.id));
3661
+ this.state.setConversationMessages(conversationId, [...result.items, ...localsToKeep]);
3549
3662
  }
3550
3663
  else if (result.items.length > 0) {
3551
3664
  this.state.addMessages(result.items);
@@ -3657,9 +3770,7 @@ class AXConversationService {
3657
3770
  };
3658
3771
  this.state.updateMessage(tempMessageId, { payload: sendCommand.payload });
3659
3772
  const sentMessage = await this.callApi('sendMessage', 'messageApi', 'sendMessage', () => this.messageApi.sendMessage(sendCommand), sendCommand);
3660
- this.state.deleteMessage(tempMessageId);
3661
- this.state.addMessage(sentMessage);
3662
- this.updateConversationLastMessage(sentMessage);
3773
+ this.finalizeSentMessage(tempMessageId, sentMessage);
3663
3774
  if (localPreviewUrl?.startsWith('blob:')) {
3664
3775
  await revokeObjectUrl$1(this.platformId, localPreviewUrl);
3665
3776
  }
@@ -3694,9 +3805,7 @@ class AXConversationService {
3694
3805
  };
3695
3806
  this.state.addMessage(tempMessage);
3696
3807
  const sentMessage = await this.callApi('sendMessage', 'messageApi', 'sendMessage', () => this.messageApi.sendMessage(sendCommand), sendCommand);
3697
- this.state.deleteMessage(tempMessageId);
3698
- this.state.addMessage(sentMessage);
3699
- this.updateConversationLastMessage(sentMessage);
3808
+ this.finalizeSentMessage(tempMessageId, sentMessage);
3700
3809
  }
3701
3810
  catch (error) {
3702
3811
  this.state.updateMessage(tempMessageId, { status: 'failed' });
@@ -3731,11 +3840,8 @@ class AXConversationService {
3731
3840
  };
3732
3841
  // Send to server
3733
3842
  const sentMessage = await this.callApi('retryFailedMessage', 'messageApi', 'sendMessage', () => this.messageApi.sendMessage(command), command);
3734
- // Replace with real message
3735
- this.state.deleteMessage(messageId);
3736
- this.state.addMessage(sentMessage);
3737
- // Update conversation's last message
3738
- this.updateConversationLastMessage(sentMessage);
3843
+ // Replace with real message (keep same DOM row when server echoes tempId)
3844
+ this.finalizeSentMessage(messageId, sentMessage);
3739
3845
  }
3740
3846
  catch (error) {
3741
3847
  // Mark as failed again
@@ -3758,7 +3864,8 @@ class AXConversationService {
3758
3864
  editedAt: new Date(),
3759
3865
  });
3760
3866
  // Sync with server
3761
- await this.callApi('editMessage', 'messageApi', 'editMessage', () => this.messageApi.editMessage(messageId, payload), messageId, payload);
3867
+ const updatedMessage = await this.callApi('editMessage', 'messageApi', 'editMessage', () => this.messageApi.editMessage(messageId, payload), messageId, payload);
3868
+ this.state.updateMessage(messageId, updatedMessage);
3762
3869
  }
3763
3870
  catch (error) {
3764
3871
  // Rollback on failure
@@ -3807,11 +3914,22 @@ class AXConversationService {
3807
3914
  * Adds reaction optimistically, server update comes via subscription
3808
3915
  */
3809
3916
  async reactToMessage(messageId, emoji) {
3917
+ const message = this.state.getMessage(messageId);
3918
+ const currentUserId = this._currentUser()?.id;
3919
+ if (!message || !currentUserId) {
3920
+ return;
3921
+ }
3922
+ const originalReactions = [...message.reactions];
3923
+ const hasReaction = message.reactions.some((r) => r.emoji === emoji && r.userId === currentUserId);
3924
+ const optimisticReactions = hasReaction
3925
+ ? message.reactions.filter((r) => !(r.emoji === emoji && r.userId === currentUserId))
3926
+ : [...message.reactions, { emoji, userId: currentUserId, timestamp: new Date() }];
3927
+ this.state.updateMessage(messageId, { reactions: optimisticReactions });
3810
3928
  try {
3811
3929
  await this.callApi('reactToMessage', 'messageApi', 'addReaction', () => this.messageApi.addReaction(messageId, emoji), messageId, emoji);
3812
- // Update will come through subscribeToMessageUpdates
3813
3930
  }
3814
3931
  catch (error) {
3932
+ this.state.updateMessage(messageId, { reactions: originalReactions });
3815
3933
  this.errorHandler.handle(error, 'reactToMessage', { messageId, emoji });
3816
3934
  throw error;
3817
3935
  }
@@ -3850,8 +3968,12 @@ class AXConversationService {
3850
3968
  if (!message || message.status === 'read') {
3851
3969
  return;
3852
3970
  }
3971
+ const existingQueue = this.readQueue.get(message.conversationId);
3972
+ if (existingQueue?.has(messageId)) {
3973
+ return;
3974
+ }
3853
3975
  this.state.updateMessage(messageId, { status: 'read' });
3854
- let queue = this.readQueue.get(message.conversationId);
3976
+ let queue = existingQueue;
3855
3977
  if (!queue) {
3856
3978
  queue = new Set();
3857
3979
  this.readQueue.set(message.conversationId, queue);
@@ -3969,10 +4091,17 @@ class AXConversationService {
3969
4091
  await this.callApi('sendTypingIndicator', 'messageApi', 'sendTypingIndicator', () => this.messageApi.sendTypingIndicator(conversationId), conversationId);
3970
4092
  }
3971
4093
  catch (error) {
3972
- // Log but don't throw - typing indicators are not critical
3973
4094
  this.errorHandler.handle(error, 'sendTypingIndicator', { conversationId });
3974
4095
  }
3975
4096
  }
4097
+ async stopTypingIndicator(conversationId) {
4098
+ try {
4099
+ await this.callApi('stopTypingIndicator', 'messageApi', 'stopTypingIndicator', () => this.messageApi.stopTypingIndicator(conversationId), conversationId);
4100
+ }
4101
+ catch (error) {
4102
+ this.errorHandler.handle(error, 'stopTypingIndicator', { conversationId });
4103
+ }
4104
+ }
3976
4105
  /**
3977
4106
  * Search conversations
3978
4107
  * Returns empty array on failure
@@ -3990,15 +4119,22 @@ class AXConversationService {
3990
4119
  * Handle new message received
3991
4120
  */
3992
4121
  handleNewMessage(message) {
4122
+ if (message.status === 'read') {
4123
+ return;
4124
+ }
3993
4125
  if (this.state.getMessage(message.id)) {
3994
4126
  return;
3995
4127
  }
4128
+ this.state.clearTypingUser(message.conversationId, message.senderId);
3996
4129
  this.state.addMessage(message);
3997
4130
  this.state.updateLastMessage(message);
3998
4131
  const currentId = this._currentUser()?.id ?? 'current-user';
3999
4132
  const isFromOtherUser = message.senderId !== currentId;
4000
4133
  const isActiveConversation = message.conversationId === this._activeConversationId();
4001
- if (isFromOtherUser && !isActiveConversation) {
4134
+ if (isFromOtherUser && isActiveConversation) {
4135
+ this.queueMessageAsRead(message.id);
4136
+ }
4137
+ else if (isFromOtherUser && !isActiveConversation) {
4002
4138
  this.state.incrementUnreadCount(message.conversationId);
4003
4139
  }
4004
4140
  this.syncMessageCountFromRealtime(message, isActiveConversation);
@@ -4046,22 +4182,21 @@ class AXConversationService {
4046
4182
  * Handle typing indicator
4047
4183
  */
4048
4184
  handleTypingIndicator(indicator) {
4049
- // Ignore typing indicators from the current user
4050
4185
  const currentUser = this._currentUser();
4051
4186
  if (currentUser && indicator.userId === currentUser.id) {
4052
4187
  return;
4053
4188
  }
4054
- this.state.updateTypingIndicator(indicator.conversationId, indicator.userId, true);
4055
- // Clear typing indicator after timeout
4056
- setTimeout(() => {
4057
- this.state.updateTypingIndicator(indicator.conversationId, indicator.userId, false);
4058
- }, this.config.typingIndicatorTimeout ?? 3000);
4189
+ if (indicator.isTyping === false) {
4190
+ this.state.clearTypingUser(indicator.conversationId, indicator.userId);
4191
+ return;
4192
+ }
4193
+ this.state.setTypingActive(indicator.conversationId, indicator.userId, this.config.typingDisplayDuration ?? 4000);
4059
4194
  }
4060
4195
  /**
4061
4196
  * Handle presence update
4062
4197
  */
4063
4198
  handlePresenceUpdate(update) {
4064
- this.state.updateParticipantPresence(update.userId, update.status, update.lastSeen);
4199
+ this.state.updateUserPresence(update);
4065
4200
  }
4066
4201
  /**
4067
4202
  * Handle conversation update
@@ -4070,6 +4205,43 @@ class AXConversationService {
4070
4205
  handleConversationUpdate(conversation) {
4071
4206
  this.syncConversationToInbox(conversation);
4072
4207
  }
4208
+ handleConversationCreated(conversation) {
4209
+ this.syncConversationToInbox(conversation, true);
4210
+ }
4211
+ handleConversationDeleted(conversationId) {
4212
+ this.state.deleteConversation(conversationId);
4213
+ this.readQueue.delete(conversationId);
4214
+ if (this._activeConversationId() === conversationId) {
4215
+ this._activeConversationId.set(undefined);
4216
+ }
4217
+ }
4218
+ handleReadReceipt(receipt) {
4219
+ const currentUserId = this._currentUser()?.id;
4220
+ const message = this.state.getMessage(receipt.messageId);
4221
+ if (!message || !currentUserId) {
4222
+ return;
4223
+ }
4224
+ if (receipt.userId === currentUserId) {
4225
+ return;
4226
+ }
4227
+ if (message.senderId === currentUserId && message.status !== 'read') {
4228
+ this.state.updateMessage(receipt.messageId, { status: 'read' });
4229
+ }
4230
+ }
4231
+ handleMessageStatusChange(change) {
4232
+ const message = this.state.getMessage(change.messageId);
4233
+ if (!message || message.status === change.status) {
4234
+ return;
4235
+ }
4236
+ this.state.updateMessage(change.messageId, { status: change.status });
4237
+ }
4238
+ handleRoomPreferencesChange(change) {
4239
+ const currentUserId = this._currentUser()?.id;
4240
+ if (!currentUserId) {
4241
+ return;
4242
+ }
4243
+ this.state.updateRoomPreferences(change.conversationId, change.settings);
4244
+ }
4073
4245
  /**
4074
4246
  * Insert or refresh a conversation in the in-memory inbox.
4075
4247
  * @param promote When true, bumps activity so the chat sorts to the top (create / reopen).
@@ -4085,6 +4257,16 @@ class AXConversationService {
4085
4257
  updatedAt: conversation.updatedAt ?? now,
4086
4258
  });
4087
4259
  }
4260
+ finalizeSentMessage(tempMessageId, sentMessage) {
4261
+ if (sentMessage.id === tempMessageId) {
4262
+ this.state.updateMessage(tempMessageId, { ...sentMessage, isLocal: false });
4263
+ }
4264
+ else {
4265
+ this.state.deleteMessage(tempMessageId);
4266
+ this.state.addMessage(sentMessage);
4267
+ }
4268
+ this.updateConversationLastMessage(sentMessage);
4269
+ }
4088
4270
  /**
4089
4271
  * Update conversation's last message
4090
4272
  */
@@ -4138,8 +4320,8 @@ class AXConversationService {
4138
4320
  */
4139
4321
  async updateConversationSettings(conversationId, settings) {
4140
4322
  try {
4141
- await this.callApi('updateConversationSettings', 'conversationApi', 'updateConversationSettings', () => this.conversationApi.updateConversationSettings(conversationId, settings), conversationId, settings);
4142
- this.state.updateSettings(conversationId, settings);
4323
+ const updated = await this.callApi('updateConversationSettings', 'userApi', 'updateConversationPreferences', () => this.userApi.updateConversationPreferences(conversationId, settings), conversationId, settings);
4324
+ this.state.updateRoomPreferences(conversationId, updated);
4143
4325
  }
4144
4326
  catch (error) {
4145
4327
  this.errorHandler.handle(error, 'updateConversationSettings', { conversationId });
@@ -4420,9 +4602,8 @@ class AXConversationService {
4420
4602
  */
4421
4603
  async muteConversation(conversationId, duration) {
4422
4604
  try {
4423
- await this.callApi('muteConversation', 'conversationApi', 'muteConversation', () => this.conversationApi.muteConversation(conversationId, duration), conversationId, duration);
4424
- const mutedUntil = duration ? new Date(Date.now() + duration) : undefined;
4425
- this.state.updateSettings(conversationId, { mutedUntil, notifications: false });
4605
+ const mutedUntil = duration ? new Date(Date.now() + duration) : new Date('2099-12-31');
4606
+ await this.updateConversationSettings(conversationId, { mutedUntil, notifications: false });
4426
4607
  }
4427
4608
  catch (error) {
4428
4609
  this.errorHandler.handle(error, 'muteConversation', { conversationId, duration });
@@ -4435,8 +4616,7 @@ class AXConversationService {
4435
4616
  */
4436
4617
  async unmuteConversation(conversationId) {
4437
4618
  try {
4438
- await this.callApi('unmuteConversation', 'conversationApi', 'unmuteConversation', () => this.conversationApi.unmuteConversation(conversationId), conversationId);
4439
- this.state.updateSettings(conversationId, { mutedUntil: undefined, notifications: true });
4619
+ await this.updateConversationSettings(conversationId, { mutedUntil: undefined, notifications: true });
4440
4620
  }
4441
4621
  catch (error) {
4442
4622
  this.errorHandler.handle(error, 'unmuteConversation', { conversationId });
@@ -4498,7 +4678,6 @@ class AXConversationService {
4498
4678
  async saveDraft(conversationId, draft) {
4499
4679
  try {
4500
4680
  await this.callApi('saveDraft', 'conversationApi', 'saveDraft', () => this.conversationApi.saveDraft(conversationId, draft), conversationId, draft);
4501
- this.state.updateConversation(conversationId, { draft });
4502
4681
  }
4503
4682
  catch (error) {
4504
4683
  this.errorHandler.handle(error, 'saveDraft', { conversationId });
@@ -4512,7 +4691,6 @@ class AXConversationService {
4512
4691
  async clearDraft(conversationId) {
4513
4692
  try {
4514
4693
  await this.callApi('clearDraft', 'conversationApi', 'clearDraft', () => this.conversationApi.clearDraft(conversationId), conversationId);
4515
- this.state.updateConversation(conversationId, { draft: undefined });
4516
4694
  }
4517
4695
  catch (error) {
4518
4696
  this.errorHandler.handle(error, 'clearDraft', { conversationId });
@@ -4559,18 +4737,35 @@ class AXConversationService {
4559
4737
  * @param caption - Optional caption
4560
4738
  */
4561
4739
  async forwardMessage(messageId, conversationIds, caption) {
4740
+ await this.runWithForwardingLock(async () => {
4741
+ try {
4742
+ const forwardCommand = {
4743
+ messageId,
4744
+ conversationIds,
4745
+ caption,
4746
+ };
4747
+ await this.callApi('forwardMessage', 'messageApi', 'forwardMessage', () => this.messageApi.forwardMessage(forwardCommand), forwardCommand);
4748
+ this.bumpMessageCount(messageId, 'forwardCount', conversationIds.length);
4749
+ }
4750
+ catch (error) {
4751
+ this.errorHandler.handle(error, 'forwardMessage', { messageId, conversationIds });
4752
+ throw error;
4753
+ }
4754
+ });
4755
+ }
4756
+ /**
4757
+ * Runs a forward operation while locking all forward actions until it completes.
4758
+ */
4759
+ async runWithForwardingLock(task) {
4760
+ if (this._isForwardingMessage()) {
4761
+ throw new Error('A message forward is already in progress.');
4762
+ }
4763
+ this._isForwardingMessage.set(true);
4562
4764
  try {
4563
- const forwardCommand = {
4564
- messageId,
4565
- conversationIds,
4566
- caption,
4567
- };
4568
- await this.callApi('forwardMessage', 'messageApi', 'forwardMessage', () => this.messageApi.forwardMessage(forwardCommand), forwardCommand);
4569
- this.bumpMessageCount(messageId, 'forwardCount', conversationIds.length);
4765
+ return await task();
4570
4766
  }
4571
- catch (error) {
4572
- this.errorHandler.handle(error, 'forwardMessage', { messageId, conversationIds });
4573
- throw error;
4767
+ finally {
4768
+ this._isForwardingMessage.set(false);
4574
4769
  }
4575
4770
  }
4576
4771
  /**
@@ -5892,22 +6087,32 @@ class AXConversationRegistryComponentOutletComponent {
5892
6087
  ...(ngDevMode ? [{ debugName: "resolvedComponent" }] : /* istanbul ignore next */ []));
5893
6088
  this.loading = signal(false, /* @ts-ignore */
5894
6089
  ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
6090
+ /** Avoid re-loading when the parent re-binds the same lazy loader reference. */
6091
+ this.activeLoader = null;
5895
6092
  effect(() => {
5896
6093
  const direct = this.component();
5897
6094
  const loader = this.componentLoader();
5898
6095
  if (direct) {
6096
+ this.activeLoader = null;
5899
6097
  this.resolvedComponent.set(direct);
5900
6098
  this.loading.set(false);
5901
6099
  return;
5902
6100
  }
5903
6101
  if (!loader) {
6102
+ this.activeLoader = null;
5904
6103
  this.resolvedComponent.set(null);
5905
6104
  this.loading.set(false);
5906
6105
  return;
5907
6106
  }
6107
+ if (this.resolvedComponent() && this.activeLoader === loader) {
6108
+ return;
6109
+ }
6110
+ this.activeLoader = loader;
5908
6111
  this.loading.set(true);
5909
- this.resolvedComponent.set(null);
5910
6112
  void loader().then((loaded) => {
6113
+ if (this.activeLoader !== loader) {
6114
+ return;
6115
+ }
5911
6116
  this.resolvedComponent.set(loaded);
5912
6117
  this.loading.set(false);
5913
6118
  });
@@ -6002,9 +6207,6 @@ class AXConversationComposerService {
6002
6207
  /** Attachments */
6003
6208
  this.attachments = signal([], /* @ts-ignore */
6004
6209
  ...(ngDevMode ? [{ debugName: "attachments" }] : /* istanbul ignore next */ []));
6005
- /** Show typing indicator */
6006
- this.showTypingIndicator = signal(false, /* @ts-ignore */
6007
- ...(ngDevMode ? [{ debugName: "showTypingIndicator" }] : /* istanbul ignore next */ []));
6008
6210
  /** Incremented to request focus on the composer text area (handled by AXConversationComposerComponent). */
6009
6211
  this._focusRequest = signal(0, /* @ts-ignore */
6010
6212
  ...(ngDevMode ? [{ debugName: "_focusRequest" }] : /* istanbul ignore next */ []));
@@ -6318,8 +6520,6 @@ class AXConversationComposerComponent {
6318
6520
  /** Replying to message */
6319
6521
  this.replyingToMessage = signal(null, /* @ts-ignore */
6320
6522
  ...(ngDevMode ? [{ debugName: "replyingToMessage" }] : /* istanbul ignore next */ []));
6321
- /** Show typing indicator - use service */
6322
- this.showTypingIndicator = this.composerService.showTypingIndicator;
6323
6523
  /** Message sent event */
6324
6524
  this.messageSent = output();
6325
6525
  /** Emitted when the user cancels an in-progress generation from the composer. */
@@ -6430,7 +6630,7 @@ class AXConversationComposerComponent {
6430
6630
  /** Default end action (voice/send morph) */
6431
6631
  this.defaultAction = this.composerService.defaultAction;
6432
6632
  this.typingSubject
6433
- .pipe(throttleTime(this.config.typingIndicatorThrottle ?? 2000), takeUntilDestroyed())
6633
+ .pipe(throttleTime(this.config.typingIndicatorThrottle ?? 3000), takeUntilDestroyed())
6434
6634
  .subscribe((conversationId) => {
6435
6635
  this.conversationService.sendTypingIndicator(conversationId);
6436
6636
  });
@@ -6467,17 +6667,37 @@ class AXConversationComposerComponent {
6467
6667
  const conversation = this.activeConversation();
6468
6668
  if (!conversation)
6469
6669
  return;
6470
- // Emit to throttled subject
6471
- this.typingSubject.next(conversation.id);
6670
+ const conversationId = conversation.id;
6671
+ const draft = this.draftText().trim();
6672
+ if (!draft) {
6673
+ this.stopTypingIndicator(conversationId);
6674
+ return;
6675
+ }
6676
+ this.typingSubject.next(conversationId);
6677
+ if (this.typingStopHandle) {
6678
+ clearTimeout(this.typingStopHandle);
6679
+ }
6680
+ this.typingStopHandle = window.setTimeout(() => {
6681
+ this.stopTypingIndicator(conversationId);
6682
+ }, this.config.typingIndicatorTimeout ?? 3000);
6683
+ }
6684
+ stopTypingIndicator(conversationId) {
6685
+ if (this.typingStopHandle) {
6686
+ clearTimeout(this.typingStopHandle);
6687
+ this.typingStopHandle = undefined;
6688
+ }
6689
+ void this.conversationService.stopTypingIndicator(conversationId);
6472
6690
  }
6473
6691
  /** Cleanup on destroy */
6474
6692
  ngOnDestroy() {
6475
- this.typingSubject.complete();
6476
- // Save draft before destroying
6477
6693
  const conversation = this.activeConversation();
6478
- if (conversation?.id && !this.composerService.editMessage()) {
6479
- this.composerService.saveDraft(conversation.id, this.draftText());
6694
+ if (conversation?.id) {
6695
+ this.stopTypingIndicator(conversation.id);
6696
+ if (!this.composerService.editMessage()) {
6697
+ this.composerService.saveDraft(conversation.id, this.draftText());
6698
+ }
6480
6699
  }
6700
+ this.typingSubject.complete();
6481
6701
  // Clear timeout
6482
6702
  if (this.draftSaveTimeout) {
6483
6703
  clearTimeout(this.draftSaveTimeout);
@@ -6514,6 +6734,7 @@ class AXConversationComposerComponent {
6514
6734
  };
6515
6735
  this.editingMessage.set(null);
6516
6736
  this.replyingToMessage.set(null);
6737
+ this.stopTypingIndicator(conversation.id);
6517
6738
  void this.composerService
6518
6739
  .sendMessage(command)
6519
6740
  .then(() => {
@@ -6851,7 +7072,7 @@ class AXConversationComposerComponent {
6851
7072
  }
6852
7073
  }
6853
7074
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationComposerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6854
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationComposerComponent, isStandalone: true, selector: "ax-conversation-composer", outputs: { messageSent: "messageSent", generationCancelled: "generationCancelled", emojiClick: "emojiClick", attachClick: "attachClick", voiceClick: "voiceClick" }, viewQueries: [{ propertyName: "textAreaRef", first: true, predicate: ["inputElement"], descendants: true, read: AXTextAreaComponent, isSignal: true }, { propertyName: "emojiPopoverRef", first: true, predicate: ["emojiPopover"], descendants: true, isSignal: true }, { propertyName: "attachPopoverRef", first: true, predicate: ["attachPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (activeConversation()) {\n <div class=\"composer\">\n <!-- Edit/Reply Banner -->\n @if (editingMessage() || replyingToMessage()) {\n <div\n class=\"ax-conversation-composer-banner\"\n [class.ax-conversation-composer-banner--edit]=\"!!editingMessage()\"\n [class.ax-conversation-composer-banner--reply]=\"!!replyingToMessage()\"\n >\n <div class=\"ax-conversation-composer-banner__accent\" aria-hidden=\"true\"></div>\n @if (editingMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-pen-to-square\"></i\n ></span>\n <div class=\"ax-conversation-composer-banner__body\">\n <span class=\"ax-conversation-composer-banner__label\">{{\n '@acorex:chat.composer.editing-message' | translate | async\n }}</span>\n @if (getEditingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n } @else if (replyingToMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-reply\"></i\n ></span>\n <div\n class=\"ax-conversation-composer-banner__body ax-conversation-composer-banner__body--clickable\"\n (click)=\"onReplyPreviewClick()\"\n >\n <span class=\"ax-conversation-composer-banner__label\">\n {{ '@acorex:chat.composer.replying-to' | translate | async }} {{ getReplyingSenderName() }}\n </span>\n @if (getReplyingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n }\n <button\n type=\"button\"\n class=\"ax-conversation-composer-banner__close\"\n (click)=\"cancelEditReply()\"\n [attr.aria-label]=\"'@acorex:chat.actions.cancel' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <!-- Input Area -->\n <div class=\"composer-input-container\">\n <!-- Start actions -->\n <div class=\"composer-actions-left\">\n @if (startMenuActions().length > 0) {\n <ax-button\n class=\"rounded-full text-xl\"\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"('@acorex:chat.tooltips.attach-file' | translate | async) ?? ''\"\n (onClick)=\"onAttachMenuClick($event)\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-paperclip\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n @for (action of startInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n </div>\n\n <!-- Text Input -->\n <div class=\"composer-input-wrapper\">\n <ax-text-area\n #inputElement\n [(ngModel)]=\"draftText\"\n (onKeyDown)=\"onKeyDown($event)\"\n (onValueChanged)=\"onInput()\"\n [placeholder]=\"placeholder()\"\n (onKeyDown)=\"onEnter($event)\"\n [rows]=\"inputRows()\"\n ></ax-text-area>\n </div>\n\n <!-- End actions -->\n <div class=\"composer-actions-right\">\n @for (action of endInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n <ax-button\n class=\"rounded-full text-xl\"\n [class.ax-conversation-composer-primary--stopping]=\"primaryButtonMode() === 'stopping'\"\n color=\"primary\"\n look=\"solid\"\n [iconOnly]=\"true\"\n [text]=\"getPrimaryButtonLabel()\"\n [disabled]=\"isPrimaryButtonDisabled()\"\n (onClick)=\"onPrimaryButtonClick()\"\n >\n <ax-prefix>\n <i [class]=\"getPrimaryButtonIcon()\"></i>\n </ax-prefix>\n </ax-button>\n </div>\n </div>\n\n <!-- Attachments Preview -->\n @if (attachments().length > 0) {\n <div class=\"composer-attachments\">\n @for (attachment of attachments(); track $index) {\n <div class=\"attachment-item\">\n <span class=\"attachment-icon\"><i class=\"fa-light fa-paperclip\"></i></span>\n <span class=\"attachment-name\">{{ attachment.name }}</span>\n <button\n type=\"button\"\n class=\"attachment-remove\"\n (click)=\"removeAttachment($index)\"\n [attr.aria-label]=\"'@acorex:chat.actions.remove-attachment' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Typing Indicator -->\n @if (showTypingIndicator()) {\n <div class=\"typing-indicator-container\">\n <span class=\"typing-indicator\">{{ '@acorex:chat.status.someone-typing' | translate | async }}</span>\n </div>\n }\n </div>\n}\n\n<!-- Popover for attachment menu -->\n@if (attachPopoverTarget()) {\n <ax-popover\n #attachPopover\n [target]=\"attachPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n (onClosed)=\"onAttachPopoverClosed()\"\n >\n <ax-button-item-list>\n @for (action of startMenuActions(); track action.id) {\n <ax-button-item\n [text]=\"getActionLabel(action)\"\n (click)=\"onAttachMenuAction(action.id)\"\n [disabled]=\"!isActionEnabled(action)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-popover>\n}\n\n<!-- Popover for emoji/sticker picker -->\n@if (emojiPopoverTarget()) {\n <ax-popover\n #emojiPopover\n [target]=\"emojiPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n panelClass=\"composer-emoji-popover-panel\"\n (onClosed)=\"onEmojiPopoverClosed()\"\n >\n <div class=\"composer-emoji-popover\">\n <ax-conversation-registry-component-outlet\n [componentLoader]=\"composerPopupLoader\"\n [inputs]=\"getEmojiPopupInputs()\"\n />\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-composer{display:block;width:100%;@keyframes ax-conversation-composer-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}ax-conversation-composer .ax-conversation-composer-banner{display:flex;min-height:2.75rem;align-items:stretch;gap:calc(var(--spacing, .25rem) * 0);border-block-style:var(--tw-border-style);border-block-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-composer .ax-conversation-composer-banner__accent{width:3px;flex-shrink:0;border-start-end-radius:var(--radius-sm, .25rem);border-end-end-radius:var(--radius-sm, .25rem);background-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__accent{background-color:rgba(var(--ax-sys-color-secondary-500))}ax-conversation-composer .ax-conversation-composer-banner__content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2.5);padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-composer .ax-conversation-composer-banner__icon{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);flex-shrink:0;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600));background:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__icon{color:rgba(var(--ax-sys-color-secondary-600));background:rgba(var(--ax-sys-color-secondary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner__body{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}ax-conversation-composer .ax-conversation-composer-banner__body--clickable{cursor:pointer;border-radius:var(--ax-sys-border-radius);transition:opacity .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__body--clickable:hover{opacity:.85}}ax-conversation-composer .ax-conversation-composer-banner__label{font-size:.6875rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-primary-600));text-transform:uppercase}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__label{color:rgba(var(--ax-sys-color-secondary-600))}ax-conversation-composer .ax-conversation-composer-banner__preview{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);overflow:hidden;font-size:.8125rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:.88}ax-conversation-composer .ax-conversation-composer-banner__preview i{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .ax-conversation-composer-banner__close{margin-inline-end:calc(var(--spacing, .25rem) * 1.5);display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;align-self:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.55);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__close:hover{color:rgba(var(--ax-sys-color-on-surface));background:rgba(var(--ax-sys-color-on-surface),.06)}}ax-conversation-composer .ax-conversation-composer-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .emoji-icon{flex-shrink:0;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)))}ax-conversation-composer .composer-input-container{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}ax-conversation-composer .composer-actions-left,ax-conversation-composer .composer-actions-right{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-composer .composer-input-wrapper{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-composer .composer-input-wrapper .ax-editor-container{padding:calc(var(--spacing, .25rem) * 0)}ax-conversation-composer .composer-input{max-height:120px;min-height:calc(var(--spacing, .25rem) * 10);width:100%;resize:none;border-radius:1.25rem;border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);--tw-outline-style: none;outline-style:none;transition:border-color .2s}ax-conversation-composer .composer-input:focus{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .composer-attachments{display:flex;flex-wrap:wrap;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 4)}ax-conversation-composer .attachment-item{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}ax-conversation-composer .attachment-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ))}ax-conversation-composer .attachment-name{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-composer .attachment-remove{display:flex;height:calc(var(--spacing, .25rem) * 5);width:calc(var(--spacing, .25rem) * 5);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:background .2s}@media(hover:hover){ax-conversation-composer .attachment-remove:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}}ax-conversation-composer .typing-indicator-container{padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 2);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .composer-component-fullwidth{min-height:72px;width:100%;background-color:rgba(var(--ax-sys-color-lightest-surface))}ax-conversation-composer .composer-emoji-popover{width:100%}ax-conversation-composer .ax-conversation-composer-primary--stopping .fa-spinner{animation:ax-conversation-composer-spin .75s linear infinite}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial;--tw-tracking: initial;--tw-leading: initial;--tw-outline-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXTextAreaComponent, selector: "ax-text-area", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "placeholder", "maxLength", "look", "rows", "allowResize", "showCounter", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXCommonModule }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
7075
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationComposerComponent, isStandalone: true, selector: "ax-conversation-composer", outputs: { messageSent: "messageSent", generationCancelled: "generationCancelled", emojiClick: "emojiClick", attachClick: "attachClick", voiceClick: "voiceClick" }, viewQueries: [{ propertyName: "textAreaRef", first: true, predicate: ["inputElement"], descendants: true, read: AXTextAreaComponent, isSignal: true }, { propertyName: "emojiPopoverRef", first: true, predicate: ["emojiPopover"], descendants: true, isSignal: true }, { propertyName: "attachPopoverRef", first: true, predicate: ["attachPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (activeConversation()) {\n <div class=\"composer\">\n <!-- Edit/Reply Banner -->\n @if (editingMessage() || replyingToMessage()) {\n <div\n class=\"ax-conversation-composer-banner\"\n [class.ax-conversation-composer-banner--edit]=\"!!editingMessage()\"\n [class.ax-conversation-composer-banner--reply]=\"!!replyingToMessage()\"\n >\n <div class=\"ax-conversation-composer-banner__accent\" aria-hidden=\"true\"></div>\n @if (editingMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-pen-to-square\"></i\n ></span>\n <div class=\"ax-conversation-composer-banner__body\">\n <span class=\"ax-conversation-composer-banner__label\">{{\n '@acorex:chat.composer.editing-message' | translate | async\n }}</span>\n @if (getEditingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n } @else if (replyingToMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-reply\"></i\n ></span>\n <div\n class=\"ax-conversation-composer-banner__body ax-conversation-composer-banner__body--clickable\"\n (click)=\"onReplyPreviewClick()\"\n >\n <span class=\"ax-conversation-composer-banner__label\">\n {{ '@acorex:chat.composer.replying-to' | translate | async }} {{ getReplyingSenderName() }}\n </span>\n @if (getReplyingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n }\n <button\n type=\"button\"\n class=\"ax-conversation-composer-banner__close\"\n (click)=\"cancelEditReply()\"\n [attr.aria-label]=\"'@acorex:chat.actions.cancel' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <!-- Input Area -->\n <div class=\"composer-input-container\">\n <!-- Start actions -->\n <div class=\"composer-actions-left\">\n @if (startMenuActions().length > 0) {\n <ax-button\n class=\"rounded-full text-xl\"\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"('@acorex:chat.tooltips.attach-file' | translate | async) ?? ''\"\n (onClick)=\"onAttachMenuClick($event)\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-paperclip\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n @for (action of startInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n </div>\n\n <!-- Text Input -->\n <div class=\"composer-input-wrapper\">\n <ax-text-area\n #inputElement\n [(ngModel)]=\"draftText\"\n (onKeyDown)=\"onKeyDown($event)\"\n (onValueChanged)=\"onInput()\"\n [placeholder]=\"placeholder()\"\n (onKeyDown)=\"onEnter($event)\"\n [rows]=\"inputRows()\"\n ></ax-text-area>\n </div>\n\n <!-- End actions -->\n <div class=\"composer-actions-right\">\n @for (action of endInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n <ax-button\n class=\"rounded-full text-xl\"\n [class.ax-conversation-composer-primary--stopping]=\"primaryButtonMode() === 'stopping'\"\n color=\"primary\"\n look=\"solid\"\n [iconOnly]=\"true\"\n [text]=\"getPrimaryButtonLabel()\"\n [disabled]=\"isPrimaryButtonDisabled()\"\n (onClick)=\"onPrimaryButtonClick()\"\n >\n <ax-prefix>\n <i [class]=\"getPrimaryButtonIcon()\"></i>\n </ax-prefix>\n </ax-button>\n </div>\n </div>\n\n <!-- Attachments Preview -->\n @if (attachments().length > 0) {\n <div class=\"composer-attachments\">\n @for (attachment of attachments(); track $index) {\n <div class=\"attachment-item\">\n <span class=\"attachment-icon\"><i class=\"fa-light fa-paperclip\"></i></span>\n <span class=\"attachment-name\">{{ attachment.name }}</span>\n <button\n type=\"button\"\n class=\"attachment-remove\"\n (click)=\"removeAttachment($index)\"\n [attr.aria-label]=\"'@acorex:chat.actions.remove-attachment' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n }\n </div>\n}\n\n<!-- Popover for attachment menu -->\n@if (attachPopoverTarget()) {\n <ax-popover\n #attachPopover\n [target]=\"attachPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n (onClosed)=\"onAttachPopoverClosed()\"\n >\n <ax-button-item-list>\n @for (action of startMenuActions(); track action.id) {\n <ax-button-item\n [text]=\"getActionLabel(action)\"\n (click)=\"onAttachMenuAction(action.id)\"\n [disabled]=\"!isActionEnabled(action)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-popover>\n}\n\n<!-- Popover for emoji/sticker picker -->\n@if (emojiPopoverTarget()) {\n <ax-popover\n #emojiPopover\n [target]=\"emojiPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n panelClass=\"composer-emoji-popover-panel\"\n (onClosed)=\"onEmojiPopoverClosed()\"\n >\n <div class=\"composer-emoji-popover\">\n <ax-conversation-registry-component-outlet\n [componentLoader]=\"composerPopupLoader\"\n [inputs]=\"getEmojiPopupInputs()\"\n />\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-composer{display:block;width:100%;@keyframes ax-conversation-composer-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}ax-conversation-composer .ax-conversation-composer-banner{display:flex;min-height:2.75rem;align-items:stretch;gap:calc(var(--spacing, .25rem) * 0);border-block-style:var(--tw-border-style);border-block-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-composer .ax-conversation-composer-banner__accent{width:3px;flex-shrink:0;border-start-end-radius:var(--radius-sm, .25rem);border-end-end-radius:var(--radius-sm, .25rem);background-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__accent{background-color:rgba(var(--ax-sys-color-secondary-500))}ax-conversation-composer .ax-conversation-composer-banner__content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2.5);padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-composer .ax-conversation-composer-banner__icon{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);flex-shrink:0;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600));background:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__icon{color:rgba(var(--ax-sys-color-secondary-600));background:rgba(var(--ax-sys-color-secondary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner__body{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}ax-conversation-composer .ax-conversation-composer-banner__body--clickable{cursor:pointer;border-radius:var(--ax-sys-border-radius);transition:opacity .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__body--clickable:hover{opacity:.85}}ax-conversation-composer .ax-conversation-composer-banner__label{font-size:.6875rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-primary-600));text-transform:uppercase}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__label{color:rgba(var(--ax-sys-color-secondary-600))}ax-conversation-composer .ax-conversation-composer-banner__preview{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);overflow:hidden;font-size:.8125rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:.88}ax-conversation-composer .ax-conversation-composer-banner__preview i{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .ax-conversation-composer-banner__close{margin-inline-end:calc(var(--spacing, .25rem) * 1.5);display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;align-self:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.55);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__close:hover{color:rgba(var(--ax-sys-color-on-surface));background:rgba(var(--ax-sys-color-on-surface),.06)}}ax-conversation-composer .ax-conversation-composer-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .emoji-icon{flex-shrink:0;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)))}ax-conversation-composer .composer-input-container{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}ax-conversation-composer .composer-actions-left,ax-conversation-composer .composer-actions-right{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-composer .composer-input-wrapper{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-composer .composer-input-wrapper .ax-editor-container{padding:calc(var(--spacing, .25rem) * 0)}ax-conversation-composer .composer-input{max-height:120px;min-height:calc(var(--spacing, .25rem) * 10);width:100%;resize:none;border-radius:1.25rem;border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);--tw-outline-style: none;outline-style:none;transition:border-color .2s}ax-conversation-composer .composer-input:focus{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .composer-attachments{display:flex;flex-wrap:wrap;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 4)}ax-conversation-composer .attachment-item{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}ax-conversation-composer .attachment-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ))}ax-conversation-composer .attachment-name{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-composer .attachment-remove{display:flex;height:calc(var(--spacing, .25rem) * 5);width:calc(var(--spacing, .25rem) * 5);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:background .2s}@media(hover:hover){ax-conversation-composer .attachment-remove:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}}ax-conversation-composer .composer-component-fullwidth{min-height:72px;width:100%;background-color:rgba(var(--ax-sys-color-lightest-surface))}ax-conversation-composer .composer-emoji-popover{width:100%}ax-conversation-composer .ax-conversation-composer-primary--stopping .fa-spinner{animation:ax-conversation-composer-spin .75s linear infinite}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial;--tw-tracking: initial;--tw-leading: initial;--tw-outline-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXTextAreaComponent, selector: "ax-text-area", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "placeholder", "maxLength", "look", "rows", "allowResize", "showCounter", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXCommonModule }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
6855
7076
  }
6856
7077
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationComposerComponent, decorators: [{
6857
7078
  type: Component,
@@ -6867,7 +7088,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
6867
7088
  AXTranslationModule,
6868
7089
  AXButtonItemComponent,
6869
7090
  AXButtonItemListComponent,
6870
- ], template: "@if (activeConversation()) {\n <div class=\"composer\">\n <!-- Edit/Reply Banner -->\n @if (editingMessage() || replyingToMessage()) {\n <div\n class=\"ax-conversation-composer-banner\"\n [class.ax-conversation-composer-banner--edit]=\"!!editingMessage()\"\n [class.ax-conversation-composer-banner--reply]=\"!!replyingToMessage()\"\n >\n <div class=\"ax-conversation-composer-banner__accent\" aria-hidden=\"true\"></div>\n @if (editingMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-pen-to-square\"></i\n ></span>\n <div class=\"ax-conversation-composer-banner__body\">\n <span class=\"ax-conversation-composer-banner__label\">{{\n '@acorex:chat.composer.editing-message' | translate | async\n }}</span>\n @if (getEditingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n } @else if (replyingToMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-reply\"></i\n ></span>\n <div\n class=\"ax-conversation-composer-banner__body ax-conversation-composer-banner__body--clickable\"\n (click)=\"onReplyPreviewClick()\"\n >\n <span class=\"ax-conversation-composer-banner__label\">\n {{ '@acorex:chat.composer.replying-to' | translate | async }} {{ getReplyingSenderName() }}\n </span>\n @if (getReplyingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n }\n <button\n type=\"button\"\n class=\"ax-conversation-composer-banner__close\"\n (click)=\"cancelEditReply()\"\n [attr.aria-label]=\"'@acorex:chat.actions.cancel' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <!-- Input Area -->\n <div class=\"composer-input-container\">\n <!-- Start actions -->\n <div class=\"composer-actions-left\">\n @if (startMenuActions().length > 0) {\n <ax-button\n class=\"rounded-full text-xl\"\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"('@acorex:chat.tooltips.attach-file' | translate | async) ?? ''\"\n (onClick)=\"onAttachMenuClick($event)\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-paperclip\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n @for (action of startInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n </div>\n\n <!-- Text Input -->\n <div class=\"composer-input-wrapper\">\n <ax-text-area\n #inputElement\n [(ngModel)]=\"draftText\"\n (onKeyDown)=\"onKeyDown($event)\"\n (onValueChanged)=\"onInput()\"\n [placeholder]=\"placeholder()\"\n (onKeyDown)=\"onEnter($event)\"\n [rows]=\"inputRows()\"\n ></ax-text-area>\n </div>\n\n <!-- End actions -->\n <div class=\"composer-actions-right\">\n @for (action of endInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n <ax-button\n class=\"rounded-full text-xl\"\n [class.ax-conversation-composer-primary--stopping]=\"primaryButtonMode() === 'stopping'\"\n color=\"primary\"\n look=\"solid\"\n [iconOnly]=\"true\"\n [text]=\"getPrimaryButtonLabel()\"\n [disabled]=\"isPrimaryButtonDisabled()\"\n (onClick)=\"onPrimaryButtonClick()\"\n >\n <ax-prefix>\n <i [class]=\"getPrimaryButtonIcon()\"></i>\n </ax-prefix>\n </ax-button>\n </div>\n </div>\n\n <!-- Attachments Preview -->\n @if (attachments().length > 0) {\n <div class=\"composer-attachments\">\n @for (attachment of attachments(); track $index) {\n <div class=\"attachment-item\">\n <span class=\"attachment-icon\"><i class=\"fa-light fa-paperclip\"></i></span>\n <span class=\"attachment-name\">{{ attachment.name }}</span>\n <button\n type=\"button\"\n class=\"attachment-remove\"\n (click)=\"removeAttachment($index)\"\n [attr.aria-label]=\"'@acorex:chat.actions.remove-attachment' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Typing Indicator -->\n @if (showTypingIndicator()) {\n <div class=\"typing-indicator-container\">\n <span class=\"typing-indicator\">{{ '@acorex:chat.status.someone-typing' | translate | async }}</span>\n </div>\n }\n </div>\n}\n\n<!-- Popover for attachment menu -->\n@if (attachPopoverTarget()) {\n <ax-popover\n #attachPopover\n [target]=\"attachPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n (onClosed)=\"onAttachPopoverClosed()\"\n >\n <ax-button-item-list>\n @for (action of startMenuActions(); track action.id) {\n <ax-button-item\n [text]=\"getActionLabel(action)\"\n (click)=\"onAttachMenuAction(action.id)\"\n [disabled]=\"!isActionEnabled(action)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-popover>\n}\n\n<!-- Popover for emoji/sticker picker -->\n@if (emojiPopoverTarget()) {\n <ax-popover\n #emojiPopover\n [target]=\"emojiPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n panelClass=\"composer-emoji-popover-panel\"\n (onClosed)=\"onEmojiPopoverClosed()\"\n >\n <div class=\"composer-emoji-popover\">\n <ax-conversation-registry-component-outlet\n [componentLoader]=\"composerPopupLoader\"\n [inputs]=\"getEmojiPopupInputs()\"\n />\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-composer{display:block;width:100%;@keyframes ax-conversation-composer-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}ax-conversation-composer .ax-conversation-composer-banner{display:flex;min-height:2.75rem;align-items:stretch;gap:calc(var(--spacing, .25rem) * 0);border-block-style:var(--tw-border-style);border-block-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-composer .ax-conversation-composer-banner__accent{width:3px;flex-shrink:0;border-start-end-radius:var(--radius-sm, .25rem);border-end-end-radius:var(--radius-sm, .25rem);background-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__accent{background-color:rgba(var(--ax-sys-color-secondary-500))}ax-conversation-composer .ax-conversation-composer-banner__content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2.5);padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-composer .ax-conversation-composer-banner__icon{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);flex-shrink:0;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600));background:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__icon{color:rgba(var(--ax-sys-color-secondary-600));background:rgba(var(--ax-sys-color-secondary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner__body{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}ax-conversation-composer .ax-conversation-composer-banner__body--clickable{cursor:pointer;border-radius:var(--ax-sys-border-radius);transition:opacity .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__body--clickable:hover{opacity:.85}}ax-conversation-composer .ax-conversation-composer-banner__label{font-size:.6875rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-primary-600));text-transform:uppercase}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__label{color:rgba(var(--ax-sys-color-secondary-600))}ax-conversation-composer .ax-conversation-composer-banner__preview{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);overflow:hidden;font-size:.8125rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:.88}ax-conversation-composer .ax-conversation-composer-banner__preview i{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .ax-conversation-composer-banner__close{margin-inline-end:calc(var(--spacing, .25rem) * 1.5);display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;align-self:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.55);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__close:hover{color:rgba(var(--ax-sys-color-on-surface));background:rgba(var(--ax-sys-color-on-surface),.06)}}ax-conversation-composer .ax-conversation-composer-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .emoji-icon{flex-shrink:0;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)))}ax-conversation-composer .composer-input-container{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}ax-conversation-composer .composer-actions-left,ax-conversation-composer .composer-actions-right{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-composer .composer-input-wrapper{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-composer .composer-input-wrapper .ax-editor-container{padding:calc(var(--spacing, .25rem) * 0)}ax-conversation-composer .composer-input{max-height:120px;min-height:calc(var(--spacing, .25rem) * 10);width:100%;resize:none;border-radius:1.25rem;border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);--tw-outline-style: none;outline-style:none;transition:border-color .2s}ax-conversation-composer .composer-input:focus{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .composer-attachments{display:flex;flex-wrap:wrap;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 4)}ax-conversation-composer .attachment-item{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}ax-conversation-composer .attachment-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ))}ax-conversation-composer .attachment-name{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-composer .attachment-remove{display:flex;height:calc(var(--spacing, .25rem) * 5);width:calc(var(--spacing, .25rem) * 5);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:background .2s}@media(hover:hover){ax-conversation-composer .attachment-remove:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}}ax-conversation-composer .typing-indicator-container{padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 2);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .composer-component-fullwidth{min-height:72px;width:100%;background-color:rgba(var(--ax-sys-color-lightest-surface))}ax-conversation-composer .composer-emoji-popover{width:100%}ax-conversation-composer .ax-conversation-composer-primary--stopping .fa-spinner{animation:ax-conversation-composer-spin .75s linear infinite}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial;--tw-tracking: initial;--tw-leading: initial;--tw-outline-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
7091
+ ], template: "@if (activeConversation()) {\n <div class=\"composer\">\n <!-- Edit/Reply Banner -->\n @if (editingMessage() || replyingToMessage()) {\n <div\n class=\"ax-conversation-composer-banner\"\n [class.ax-conversation-composer-banner--edit]=\"!!editingMessage()\"\n [class.ax-conversation-composer-banner--reply]=\"!!replyingToMessage()\"\n >\n <div class=\"ax-conversation-composer-banner__accent\" aria-hidden=\"true\"></div>\n @if (editingMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-pen-to-square\"></i\n ></span>\n <div class=\"ax-conversation-composer-banner__body\">\n <span class=\"ax-conversation-composer-banner__label\">{{\n '@acorex:chat.composer.editing-message' | translate | async\n }}</span>\n @if (getEditingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n } @else if (replyingToMessage()) {\n <div class=\"ax-conversation-composer-banner__content\">\n <span class=\"ax-conversation-composer-banner__icon\" aria-hidden=\"true\"\n ><i class=\"fa-light fa-reply\"></i\n ></span>\n <div\n class=\"ax-conversation-composer-banner__body ax-conversation-composer-banner__body--clickable\"\n (click)=\"onReplyPreviewClick()\"\n >\n <span class=\"ax-conversation-composer-banner__label\">\n {{ '@acorex:chat.composer.replying-to' | translate | async }} {{ getReplyingSenderName() }}\n </span>\n @if (getReplyingPreview(); as preview) {\n <span class=\"ax-conversation-composer-banner__preview\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n {{ getComposerPreviewLabel(preview) }}\n </span>\n }\n </div>\n </div>\n }\n <button\n type=\"button\"\n class=\"ax-conversation-composer-banner__close\"\n (click)=\"cancelEditReply()\"\n [attr.aria-label]=\"'@acorex:chat.actions.cancel' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n\n <!-- Input Area -->\n <div class=\"composer-input-container\">\n <!-- Start actions -->\n <div class=\"composer-actions-left\">\n @if (startMenuActions().length > 0) {\n <ax-button\n class=\"rounded-full text-xl\"\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"('@acorex:chat.tooltips.attach-file' | translate | async) ?? ''\"\n (onClick)=\"onAttachMenuClick($event)\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-paperclip\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n @for (action of startInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n </div>\n\n <!-- Text Input -->\n <div class=\"composer-input-wrapper\">\n <ax-text-area\n #inputElement\n [(ngModel)]=\"draftText\"\n (onKeyDown)=\"onKeyDown($event)\"\n (onValueChanged)=\"onInput()\"\n [placeholder]=\"placeholder()\"\n (onKeyDown)=\"onEnter($event)\"\n [rows]=\"inputRows()\"\n ></ax-text-area>\n </div>\n\n <!-- End actions -->\n <div class=\"composer-actions-right\">\n @for (action of endInlineActions(); track action.id) {\n <ax-button\n look=\"blank\"\n [iconOnly]=\"true\"\n [text]=\"getActionLabel(action)\"\n [disabled]=\"!isActionEnabled(action)\"\n [class]=\"getActionButtonClass(action)\"\n (onClick)=\"onActionClick(action.id, $event)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button>\n }\n\n <ax-button\n class=\"rounded-full text-xl\"\n [class.ax-conversation-composer-primary--stopping]=\"primaryButtonMode() === 'stopping'\"\n color=\"primary\"\n look=\"solid\"\n [iconOnly]=\"true\"\n [text]=\"getPrimaryButtonLabel()\"\n [disabled]=\"isPrimaryButtonDisabled()\"\n (onClick)=\"onPrimaryButtonClick()\"\n >\n <ax-prefix>\n <i [class]=\"getPrimaryButtonIcon()\"></i>\n </ax-prefix>\n </ax-button>\n </div>\n </div>\n\n <!-- Attachments Preview -->\n @if (attachments().length > 0) {\n <div class=\"composer-attachments\">\n @for (attachment of attachments(); track $index) {\n <div class=\"attachment-item\">\n <span class=\"attachment-icon\"><i class=\"fa-light fa-paperclip\"></i></span>\n <span class=\"attachment-name\">{{ attachment.name }}</span>\n <button\n type=\"button\"\n class=\"attachment-remove\"\n (click)=\"removeAttachment($index)\"\n [attr.aria-label]=\"'@acorex:chat.actions.remove-attachment' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n }\n </div>\n}\n\n<!-- Popover for attachment menu -->\n@if (attachPopoverTarget()) {\n <ax-popover\n #attachPopover\n [target]=\"attachPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n (onClosed)=\"onAttachPopoverClosed()\"\n >\n <ax-button-item-list>\n @for (action of startMenuActions(); track action.id) {\n <ax-button-item\n [text]=\"getActionLabel(action)\"\n (click)=\"onAttachMenuAction(action.id)\"\n [disabled]=\"!isActionEnabled(action)\"\n >\n <ax-prefix>\n <i [class]=\"action.icon\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-popover>\n}\n\n<!-- Popover for emoji/sticker picker -->\n@if (emojiPopoverTarget()) {\n <ax-popover\n #emojiPopover\n [target]=\"emojiPopoverTarget()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"'top-start'\"\n panelClass=\"composer-emoji-popover-panel\"\n (onClosed)=\"onEmojiPopoverClosed()\"\n >\n <div class=\"composer-emoji-popover\">\n <ax-conversation-registry-component-outlet\n [componentLoader]=\"composerPopupLoader\"\n [inputs]=\"getEmojiPopupInputs()\"\n />\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-composer{display:block;width:100%;@keyframes ax-conversation-composer-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}ax-conversation-composer .ax-conversation-composer-banner{display:flex;min-height:2.75rem;align-items:stretch;gap:calc(var(--spacing, .25rem) * 0);border-block-style:var(--tw-border-style);border-block-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-composer .ax-conversation-composer-banner__accent{width:3px;flex-shrink:0;border-start-end-radius:var(--radius-sm, .25rem);border-end-end-radius:var(--radius-sm, .25rem);background-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__accent{background-color:rgba(var(--ax-sys-color-secondary-500))}ax-conversation-composer .ax-conversation-composer-banner__content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 2.5);padding-inline:calc(var(--spacing, .25rem) * 2.5);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-composer .ax-conversation-composer-banner__icon{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);flex-shrink:0;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600));background:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__icon{color:rgba(var(--ax-sys-color-secondary-600));background:rgba(var(--ax-sys-color-secondary-500),.1)}ax-conversation-composer .ax-conversation-composer-banner__body{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}ax-conversation-composer .ax-conversation-composer-banner__body--clickable{cursor:pointer;border-radius:var(--ax-sys-border-radius);transition:opacity .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__body--clickable:hover{opacity:.85}}ax-conversation-composer .ax-conversation-composer-banner__label{font-size:.6875rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-primary-600));text-transform:uppercase}ax-conversation-composer .ax-conversation-composer-banner--reply .ax-conversation-composer-banner__label{color:rgba(var(--ax-sys-color-secondary-600))}ax-conversation-composer .ax-conversation-composer-banner__preview{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);overflow:hidden;font-size:.8125rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:.88}ax-conversation-composer .ax-conversation-composer-banner__preview i{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));opacity:70%}ax-conversation-composer .ax-conversation-composer-banner__close{margin-inline-end:calc(var(--spacing, .25rem) * 1.5);display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;align-self:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.55);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-composer .ax-conversation-composer-banner__close:hover{color:rgba(var(--ax-sys-color-on-surface));background:rgba(var(--ax-sys-color-on-surface),.06)}}ax-conversation-composer .ax-conversation-composer-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .emoji-icon{flex-shrink:0;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)))}ax-conversation-composer .composer-input-container{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}ax-conversation-composer .composer-actions-left,ax-conversation-composer .composer-actions-right{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-composer .composer-input-wrapper{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-composer .composer-input-wrapper .ax-editor-container{padding:calc(var(--spacing, .25rem) * 0)}ax-conversation-composer .composer-input{max-height:120px;min-height:calc(var(--spacing, .25rem) * 10);width:100%;resize:none;border-radius:1.25rem;border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);--tw-outline-style: none;outline-style:none;transition:border-color .2s}ax-conversation-composer .composer-input:focus{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-composer .composer-attachments{display:flex;flex-wrap:wrap;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 4)}ax-conversation-composer .attachment-item{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-light-surface));padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}ax-conversation-composer .attachment-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ))}ax-conversation-composer .attachment-name{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-composer .attachment-remove{display:flex;height:calc(var(--spacing, .25rem) * 5);width:calc(var(--spacing, .25rem) * 5);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:background .2s}@media(hover:hover){ax-conversation-composer .attachment-remove:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}}ax-conversation-composer .composer-component-fullwidth{min-height:72px;width:100%;background-color:rgba(var(--ax-sys-color-lightest-surface))}ax-conversation-composer .composer-emoji-popover{width:100%}ax-conversation-composer .ax-conversation-composer-primary--stopping .fa-spinner{animation:ax-conversation-composer-spin .75s linear infinite}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial;--tw-tracking: initial;--tw-leading: initial;--tw-outline-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
6871
7092
  }], ctorParameters: () => [], propDecorators: { textAreaRef: [{ type: i0.ViewChild, args: ['inputElement', { ...{ read: AXTextAreaComponent }, isSignal: true }] }], messageSent: [{ type: i0.Output, args: ["messageSent"] }], generationCancelled: [{ type: i0.Output, args: ["generationCancelled"] }], emojiClick: [{ type: i0.Output, args: ["emojiClick"] }], attachClick: [{ type: i0.Output, args: ["attachClick"] }], voiceClick: [{ type: i0.Output, args: ["voiceClick"] }], emojiPopoverRef: [{ type: i0.ViewChild, args: ['emojiPopover', { isSignal: true }] }], attachPopoverRef: [{ type: i0.ViewChild, args: ['attachPopover', { isSignal: true }] }] } });
6872
7093
 
6873
7094
  /**
@@ -7130,9 +7351,19 @@ class AXConversationAvatarComponent {
7130
7351
  displayIcon: explicitIcon ?? resolved.icon,
7131
7352
  };
7132
7353
  }
7354
+ const conversation = this.conversation();
7355
+ const explicitName = this.name();
7356
+ const explicitAvatar = this.avatar();
7357
+ const explicitIcon = this.icon();
7358
+ const resolved = conversation
7359
+ ? resolveConversationAvatarDisplay(conversation, this.currentUserId())
7360
+ : { name: explicitName ?? '?', avatar: explicitAvatar, icon: explicitIcon };
7133
7361
  return {
7134
- conversationId: this.conversation()?.id ?? '',
7362
+ conversationId: conversation?.id ?? '',
7135
7363
  size: this.size(),
7364
+ displayName: explicitName ?? resolved.name,
7365
+ displayAvatar: explicitAvatar ?? resolved.avatar,
7366
+ displayIcon: explicitIcon ?? resolved.icon,
7136
7367
  };
7137
7368
  }, /* @ts-ignore */
7138
7369
  ...(ngDevMode ? [{ debugName: "customInputs" }] : /* istanbul ignore next */ []));
@@ -7175,14 +7406,14 @@ class AXConversationAvatarComponent {
7175
7406
  this.fallbackInitials = computed(() => AXConversationMessageUtilsService.getInitials(this.fallbackDisplay().name), /* @ts-ignore */
7176
7407
  ...(ngDevMode ? [{ debugName: "fallbackInitials" }] : /* istanbul ignore next */ []));
7177
7408
  this.resolvedStatus = computed(() => {
7178
- const conversation = this.conversation();
7179
- if (!conversation || !this.showStatus()) {
7409
+ const userId = this.resolvedUserId();
7410
+ if (!userId || !this.showStatus()) {
7180
7411
  return undefined;
7181
7412
  }
7182
- return AXConversationMessageUtilsService.getConversationStatus(conversation);
7413
+ const presence = this.conversationService?.getUserPresence(userId);
7414
+ return AXConversationMessageUtilsService.getUserPresenceStatus(presence);
7183
7415
  }, /* @ts-ignore */
7184
7416
  ...(ngDevMode ? [{ debugName: "resolvedStatus" }] : /* istanbul ignore next */ []));
7185
- /** Hide presence badge when a registered custom avatar component is rendered. */
7186
7417
  this.statusBadgePresence = computed(() => {
7187
7418
  if (this.customComponent()) {
7188
7419
  return undefined;
@@ -7192,13 +7423,13 @@ class AXConversationAvatarComponent {
7192
7423
  ...(ngDevMode ? [{ debugName: "statusBadgePresence" }] : /* istanbul ignore next */ []));
7193
7424
  }
7194
7425
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationAvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7195
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationAvatarComponent, isStandalone: true, selector: "ax-conversation-avatar", inputs: { kind: { classPropertyName: "kind", publicName: "kind", isSignal: true, isRequired: false, transformFunction: null }, userId: { classPropertyName: "userId", publicName: "userId", isSignal: true, isRequired: false, transformFunction: null }, conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showStatus: { classPropertyName: "showStatus", publicName: "showStatus", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, avatar: { classPropertyName: "avatar", publicName: "avatar", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--ax-conversation-avatar-size.px": "size()" } }, ngImport: i0, template: "<div class=\"ax-conversation-avatar\">\n @if (customComponent(); as component) {\n <ng-container *ngComponentOutlet=\"component; inputs: filteredCustomInputs()\" />\n } @else {\n <ax-avatar [size]=\"size()\">\n @if (fallbackDisplay().avatar; as avatarSrc) {\n <ax-image [src]=\"avatarSrc\" [alt]=\"fallbackDisplay().name\"></ax-image>\n } @else if (fallbackDisplay().icon; as iconClass) {\n <ax-icon><i [class]=\"iconClass\" aria-hidden=\"true\"></i></ax-icon>\n } @else {\n <ax-label>{{ fallbackInitials() }}</ax-label>\n }\n </ax-avatar>\n }\n\n @if (statusBadgePresence(); as presence) {\n <span\n class=\"ax-conversation-avatar-status\"\n [class.status-online]=\"presence === 'online'\"\n [class.status-offline]=\"presence === 'offline'\"\n [class.status-away]=\"presence === 'away'\"\n ></span>\n }\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-avatar{display:inline-flex}ax-conversation-avatar .ax-conversation-avatar{position:relative;display:inline-flex}ax-conversation-avatar .ax-conversation-avatar-status{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * .5);bottom:calc(var(--spacing, .25rem) * .5);height:calc(var(--spacing, .25rem) * 3);width:calc(var(--spacing, .25rem) * 3);border-radius:calc(infinity * 1px)}ax-conversation-avatar .ax-conversation-avatar-status.status-online{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-success-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-away{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-warning-500))}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AXAvatarComponent, selector: "ax-avatar", inputs: ["color", "size", "shape", "look"], outputs: ["sizeChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: AXImageComponent, selector: "ax-image", inputs: ["width", "height", "overlayMode", "src", "alt", "priority", "lazy"], outputs: ["onLoad", "onError"] }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }], encapsulation: i0.ViewEncapsulation.None }); }
7426
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationAvatarComponent, isStandalone: true, selector: "ax-conversation-avatar", inputs: { kind: { classPropertyName: "kind", publicName: "kind", isSignal: true, isRequired: false, transformFunction: null }, userId: { classPropertyName: "userId", publicName: "userId", isSignal: true, isRequired: false, transformFunction: null }, conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showStatus: { classPropertyName: "showStatus", publicName: "showStatus", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, avatar: { classPropertyName: "avatar", publicName: "avatar", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--ax-conversation-avatar-size.px": "size()" } }, ngImport: i0, template: "<div class=\"ax-conversation-avatar\">\n @if (customComponent(); as component) {\n <ng-container *ngComponentOutlet=\"component; inputs: filteredCustomInputs()\" />\n } @else {\n <ax-avatar [size]=\"size()\">\n @if (fallbackDisplay().avatar; as avatarSrc) {\n <ax-image [src]=\"avatarSrc\" [alt]=\"fallbackDisplay().name\"></ax-image>\n } @else if (fallbackDisplay().icon; as iconClass) {\n <ax-icon><i [class]=\"iconClass\" aria-hidden=\"true\"></i></ax-icon>\n } @else {\n <ax-label>{{ fallbackInitials() }}</ax-label>\n }\n </ax-avatar>\n }\n\n @if (statusBadgePresence(); as presence) {\n <span\n class=\"ax-conversation-avatar-status\"\n [class.status-online]=\"presence === 'online'\"\n [class.status-offline]=\"presence === 'offline'\"\n [class.status-away]=\"presence === 'away'\"\n [class.status-busy]=\"presence === 'busy'\"\n ></span>\n }\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-avatar{display:inline-flex}ax-conversation-avatar .ax-conversation-avatar{position:relative;display:inline-flex}ax-conversation-avatar .ax-conversation-avatar-status{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * .5);bottom:calc(var(--spacing, .25rem) * .5);height:calc(var(--spacing, .25rem) * 3);width:calc(var(--spacing, .25rem) * 3);border-radius:calc(infinity * 1px)}ax-conversation-avatar .ax-conversation-avatar-status.status-online{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-success-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-away{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-warning-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-offline{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:var(--color-neutral-400, oklch(70.8% 0 0))}ax-conversation-avatar .ax-conversation-avatar-status.status-busy{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-danger-500))}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AXAvatarComponent, selector: "ax-avatar", inputs: ["color", "size", "shape", "look"], outputs: ["sizeChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: AXImageComponent, selector: "ax-image", inputs: ["width", "height", "overlayMode", "src", "alt", "priority", "lazy"], outputs: ["onLoad", "onError"] }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }], encapsulation: i0.ViewEncapsulation.None }); }
7196
7427
  }
7197
7428
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationAvatarComponent, decorators: [{
7198
7429
  type: Component,
7199
7430
  args: [{ selector: 'ax-conversation-avatar', encapsulation: ViewEncapsulation.None, imports: [NgComponentOutlet, AXAvatarComponent, AXDecoratorModule, AXImageComponent, AXLabelComponent], host: {
7200
7431
  '[style.--ax-conversation-avatar-size.px]': 'size()',
7201
- }, template: "<div class=\"ax-conversation-avatar\">\n @if (customComponent(); as component) {\n <ng-container *ngComponentOutlet=\"component; inputs: filteredCustomInputs()\" />\n } @else {\n <ax-avatar [size]=\"size()\">\n @if (fallbackDisplay().avatar; as avatarSrc) {\n <ax-image [src]=\"avatarSrc\" [alt]=\"fallbackDisplay().name\"></ax-image>\n } @else if (fallbackDisplay().icon; as iconClass) {\n <ax-icon><i [class]=\"iconClass\" aria-hidden=\"true\"></i></ax-icon>\n } @else {\n <ax-label>{{ fallbackInitials() }}</ax-label>\n }\n </ax-avatar>\n }\n\n @if (statusBadgePresence(); as presence) {\n <span\n class=\"ax-conversation-avatar-status\"\n [class.status-online]=\"presence === 'online'\"\n [class.status-offline]=\"presence === 'offline'\"\n [class.status-away]=\"presence === 'away'\"\n ></span>\n }\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-avatar{display:inline-flex}ax-conversation-avatar .ax-conversation-avatar{position:relative;display:inline-flex}ax-conversation-avatar .ax-conversation-avatar-status{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * .5);bottom:calc(var(--spacing, .25rem) * .5);height:calc(var(--spacing, .25rem) * 3);width:calc(var(--spacing, .25rem) * 3);border-radius:calc(infinity * 1px)}ax-conversation-avatar .ax-conversation-avatar-status.status-online{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-success-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-away{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-warning-500))}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
7432
+ }, template: "<div class=\"ax-conversation-avatar\">\n @if (customComponent(); as component) {\n <ng-container *ngComponentOutlet=\"component; inputs: filteredCustomInputs()\" />\n } @else {\n <ax-avatar [size]=\"size()\">\n @if (fallbackDisplay().avatar; as avatarSrc) {\n <ax-image [src]=\"avatarSrc\" [alt]=\"fallbackDisplay().name\"></ax-image>\n } @else if (fallbackDisplay().icon; as iconClass) {\n <ax-icon><i [class]=\"iconClass\" aria-hidden=\"true\"></i></ax-icon>\n } @else {\n <ax-label>{{ fallbackInitials() }}</ax-label>\n }\n </ax-avatar>\n }\n\n @if (statusBadgePresence(); as presence) {\n <span\n class=\"ax-conversation-avatar-status\"\n [class.status-online]=\"presence === 'online'\"\n [class.status-offline]=\"presence === 'offline'\"\n [class.status-away]=\"presence === 'away'\"\n [class.status-busy]=\"presence === 'busy'\"\n ></span>\n }\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-avatar{display:inline-flex}ax-conversation-avatar .ax-conversation-avatar{position:relative;display:inline-flex}ax-conversation-avatar .ax-conversation-avatar-status{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * .5);bottom:calc(var(--spacing, .25rem) * .5);height:calc(var(--spacing, .25rem) * 3);width:calc(var(--spacing, .25rem) * 3);border-radius:calc(infinity * 1px)}ax-conversation-avatar .ax-conversation-avatar-status.status-online{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-success-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-away{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-warning-500))}ax-conversation-avatar .ax-conversation-avatar-status.status-offline{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:var(--color-neutral-400, oklch(70.8% 0 0))}ax-conversation-avatar .ax-conversation-avatar-status.status-busy{border-style:var(--tw-border-style);border-width:2px;border-color:rgba(var(--ax-sys-color-surface));background-color:rgba(var(--ax-sys-color-danger-500))}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
7202
7433
  }], propDecorators: { kind: [{ type: i0.Input, args: [{ isSignal: true, alias: "kind", required: false }] }], userId: [{ type: i0.Input, args: [{ isSignal: true, alias: "userId", required: false }] }], conversation: [{ type: i0.Input, args: [{ isSignal: true, alias: "conversation", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "showStatus", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], avatar: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatar", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }] } });
7203
7434
 
7204
7435
  /**
@@ -7469,33 +7700,21 @@ class AXConversationInfoBarComponent {
7469
7700
  this.platform = inject(AXPlatform);
7470
7701
  this.destroyRef = inject(DestroyRef);
7471
7702
  this.customUserAvatarComponent = inject(AX_CONVERSATION_USER_AVATAR_COMPONENT, { optional: true });
7472
- /** Bumps when viewport changes so dynamic action locations re-resolve. */
7473
7703
  this.layoutTick = signal(0, /* @ts-ignore */
7474
7704
  ...(ngDevMode ? [{ debugName: "layoutTick" }] : /* istanbul ignore next */ []));
7475
- /** Whether a custom user avatar component is registered via conversation config. */
7476
7705
  this.hasCustomUserAvatar = computed(() => !!this.customUserAvatarComponent, /* @ts-ignore */
7477
7706
  ...(ngDevMode ? [{ debugName: "hasCustomUserAvatar" }] : /* istanbul ignore next */ []));
7478
- /** Active conversation */
7479
7707
  this.activeConversation = this.infoBar.activeConversation;
7480
- /** Active component from service */
7481
7708
  this.activeComponent = this.infoBar.activeComponent;
7482
- /** Active banner from service */
7483
7709
  this.activeBanner = this.infoBar.activeBanner;
7484
- /** Members popover target element — retained for API compatibility */
7485
7710
  this.membersPopoverTarget = signal(null, /* @ts-ignore */
7486
7711
  ...(ngDevMode ? [{ debugName: "membersPopoverTarget" }] : /* istanbul ignore next */ []));
7487
- /** Loading state for async actions */
7488
7712
  this.actionLoading = signal(false, /* @ts-ignore */
7489
7713
  ...(ngDevMode ? [{ debugName: "actionLoading" }] : /* istanbul ignore next */ []));
7490
- /** Info area clicked event — host apps can open a custom conversation details UI */
7491
7714
  this.infoClick = output();
7492
- /** Search clicked event */
7493
7715
  this.searchClick = output();
7494
- /** Search query changed event */
7495
7716
  this.searchQuery = output();
7496
- /** Menu item clicked event */
7497
7717
  this.menuItemAction = output();
7498
- /** Inline action buttons from registry */
7499
7718
  this.inlineActions = computed(() => {
7500
7719
  this.layoutTick();
7501
7720
  const conversation = this.activeConversation();
@@ -7504,24 +7723,25 @@ class AXConversationInfoBarComponent {
7504
7723
  return this.registry.infoBarActions.getInlineActions(conversation);
7505
7724
  }, /* @ts-ignore */
7506
7725
  ...(ngDevMode ? [{ debugName: "inlineActions" }] : /* istanbul ignore next */ []));
7507
- /** Dropdown menu items from registry */
7508
7726
  this.menuItems = computed(() => {
7509
7727
  this.layoutTick();
7510
7728
  const conversation = this.activeConversation();
7511
7729
  if (!conversation)
7512
7730
  return [];
7513
- // Get menu actions from registry
7514
7731
  const actions = this.registry.infoBarActions.getMenuActions(conversation);
7515
- // Convert actions to dropdown menu items
7516
- const result = actions.map((action) => ({
7517
- id: action.id,
7518
- label: this.registry.infoBarActions.getActionLabel(action, conversation),
7519
- icon: this.registry.infoBarActions.getActionIcon(action, conversation),
7520
- divider: action.divider,
7521
- destructive: action.destructive,
7522
- disabled: !this.registry.infoBarActions.isActionEnabled(action, { conversation }),
7523
- }));
7524
- return result;
7732
+ return actions.map((action) => {
7733
+ const originalIndex = actions.findIndex((a) => a.id === action.id);
7734
+ const nextAction = actions[originalIndex + 1];
7735
+ const hasBreakAfter = nextAction?.divider === true;
7736
+ return {
7737
+ id: action.id,
7738
+ label: this.registry.infoBarActions.getActionLabel(action, conversation),
7739
+ icon: this.registry.infoBarActions.getActionIcon(action, conversation),
7740
+ divider: action.divider,
7741
+ destructive: action.destructive,
7742
+ disabled: !this.registry.infoBarActions.isActionEnabled(action, { conversation }),
7743
+ };
7744
+ });
7525
7745
  }, /* @ts-ignore */
7526
7746
  ...(ngDevMode ? [{ debugName: "menuItems" }] : /* istanbul ignore next */ []));
7527
7747
  const resizeSub = this.platform.resize.subscribe(() => {
@@ -7529,23 +7749,24 @@ class AXConversationInfoBarComponent {
7529
7749
  });
7530
7750
  this.destroyRef.onDestroy(() => resizeSub.unsubscribe());
7531
7751
  }
7532
- // Access registry through conversation service
7533
7752
  get registry() {
7534
7753
  return this.conversationService.registry;
7535
7754
  }
7536
- /** Get conversation status - delegate to utils */
7537
7755
  getStatus(conversation) {
7538
- return AXConversationMessageUtilsService.getConversationStatus(conversation);
7756
+ return AXConversationMessageUtilsService.getConversationStatus(conversation, this.conversationService.getPeerPresence(conversation));
7539
7757
  }
7540
- /** Get subtitle text - delegate to utils */
7541
7758
  getSubtitle(conversation) {
7542
- return AXConversationMessageUtilsService.getConversationSubtitle(conversation);
7759
+ this.conversationService.presenceTimeTick();
7760
+ this.conversationService.typingRevision();
7761
+ return AXConversationMessageUtilsService.getConversationSubtitle(conversation, {
7762
+ typingUserIds: this.conversationService.getActiveTypingUserIds(conversation.id),
7763
+ peerPresence: this.conversationService.getPeerPresence(conversation),
7764
+ currentUserId: this.conversationService.currentUser()?.id,
7765
+ });
7543
7766
  }
7544
- /** Info area clicked — emits for host apps to open a custom conversation details UI */
7545
7767
  onInfoLeftClick() {
7546
7768
  this.infoClick.emit();
7547
7769
  }
7548
- /** Handle inline action click */
7549
7770
  async onInlineActionClick(actionId) {
7550
7771
  const conversation = this.activeConversation();
7551
7772
  if (!conversation)
@@ -7581,7 +7802,6 @@ class AXConversationInfoBarComponent {
7581
7802
  this.actionLoading.set(false);
7582
7803
  }
7583
7804
  }
7584
- /** Get inputs for dynamic component */
7585
7805
  getComponentInputs() {
7586
7806
  const activeComp = this.activeComponent();
7587
7807
  if (!activeComp)
@@ -7604,7 +7824,6 @@ class AXConversationInfoBarComponent {
7604
7824
  return false;
7605
7825
  return activeComp.action.fullWidthComponent !== false;
7606
7826
  }
7607
- /** Handle close component */
7608
7827
  onCloseComponent() {
7609
7828
  this.infoBar.hideComponent();
7610
7829
  }
@@ -7620,7 +7839,6 @@ class AXConversationInfoBarComponent {
7620
7839
  onCloseBanner() {
7621
7840
  this.infoBar.hideMessageBanner();
7622
7841
  }
7623
- /** Handle menu item click */
7624
7842
  async onMenuItemClick(item) {
7625
7843
  const conversation = this.activeConversation();
7626
7844
  if (!conversation)
@@ -7632,7 +7850,7 @@ class AXConversationInfoBarComponent {
7632
7850
  this.menuItemAction.emit(item.id);
7633
7851
  }
7634
7852
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationInfoBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7635
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationInfoBarComponent, isStandalone: true, selector: "ax-conversation-info-bar", outputs: { infoClick: "infoClick", searchClick: "searchClick", searchQuery: "searchQuery", menuItemAction: "menuItemAction" }, ngImport: i0, template: "@if (activeConversation(); as conversation) {\n <div class=\"info-bar\">\n <!-- Left: Avatar and Info -->\n <div class=\"info-prefix\" (click)=\"$event.stopPropagation()\">\n <ng-content select=\"ax-prefix\"></ng-content>\n </div>\n <div\n class=\"info-left\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onInfoLeftClick()\"\n (keydown.enter)=\"onInfoLeftClick()\"\n (keydown.space)=\"$event.preventDefault(); onInfoLeftClick()\"\n >\n <div class=\"avatar-wrapper\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"conversation\"\n [size]=\"48\"\n [showStatus]=\"conversation.type === 'private'\"\n />\n </div>\n\n <div class=\"info-details\">\n <p class=\"info-title\">{{ conversation.title }}</p>\n @if (conversation.type !== 'private') {\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n } @else {\n <div class=\"info-subtitle-with-status\">\n @if (getStatus(conversation) === 'online' && !hasCustomUserAvatar()) {\n <span class=\"online-badge\">\u25CF</span>\n }\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Right: Actions or Full-Width Component -->\n @if (!activeComponent() || !isActiveComponentFullWidth()) {\n <div class=\"info-actions\" (click)=\"$event.stopPropagation()\">\n <!-- Inline action buttons from registry -->\n @for (action of inlineActions(); track action.id) {\n @if ((action.component || action.componentLoader) && action.fullWidthComponent === false) {\n <ax-conversation-registry-component-outlet\n [component]=\"action.component\"\n [componentLoader]=\"action.componentLoader\"\n [inputs]=\"getInlineComponentInputs()\"\n />\n } @else {\n <ax-button class=\"action-button\" (onClick)=\"onInlineActionClick(action.id)\" look=\"ghost\">\n <ax-icon [icon]=\"registry.infoBarActions.getActionIcon(action, activeConversation()!)\"></ax-icon>\n </ax-button>\n }\n }\n\n <ax-button look=\"blank\">\n <ax-icon><i class=\"fa-light fa-ellipsis-vertical\"></i></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of menuItems(); track item.id) {\n @if (item.divider) {\n <ax-divider></ax-divider>\n } @else {\n <ax-button-item\n [text]=\"item.label\"\n [disabled]=\"item.disabled\"\n [color]=\"item.destructive ? 'danger' : 'default'\"\n (onClick)=\"onMenuItemClick(item)\"\n >\n @if (item.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n }\n @if (item.shortcut) {\n <ax-suffix>\n <ax-label class=\"shortcut\">{{ item.shortcut }}</ax-label>\n </ax-suffix>\n }\n </ax-button-item>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n\n @if (activeComponent() && isActiveComponentFullWidth()) {\n <!-- Full-width component mode (e.g., search) - takes entire info-bar -->\n <div\n class=\"info-component-fullwidth\"\n animate.enter=\"slide-in\"\n animate.leave=\"slide-out\"\n (click)=\"$event.stopPropagation()\"\n >\n <ax-conversation-registry-component-outlet\n [component]=\"activeComponent()!.component\"\n [componentLoader]=\"activeComponent()!.componentLoader\"\n [inputs]=\"getComponentInputs()\"\n />\n <ax-button class=\"action-button close-button\" (onClick)=\"onCloseComponent()\" [look]=\"'ghost'\">\n <ax-icon><i class=\"fa-light fa-xmark\"></i></ax-icon>\n </ax-button>\n </div>\n }\n </div>\n\n @if (activeBanner()) {\n <div class=\"ax-conversation-info-banner\" (click)=\"$event.stopPropagation()\">\n <div class=\"ax-conversation-info-banner__content\">\n <ax-conversation-registry-component-outlet\n [component]=\"activeBanner()!.component\"\n [componentLoader]=\"activeBanner()!.componentLoader\"\n [inputs]=\"getBannerInputs()\"\n />\n </div>\n <button\n type=\"button\"\n class=\"ax-conversation-info-banner__close\"\n (click)=\"onCloseBanner()\"\n [attr.aria-label]=\"'Close'\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n}\n", styles: ["@layer properties;@layer components{ax-conversation-info-bar{display:block;max-width:100%;@keyframes axInfoBarPulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes axInfoBarSlideIn{0%{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%))}to{opacity:1;transform:translate(0)}}}ax-conversation-info-bar .info-bar{position:relative;display:flex;min-height:calc(var(--spacing, .25rem) * 16);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);overflow:hidden;padding:calc(var(--spacing, .25rem) * 2);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-info-bar .ax-conversation-info-banner{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:calc(var(--spacing, .25rem) * 2);padding-inline-start:calc(var(--spacing, .25rem) * 3);padding-inline-end:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .ax-conversation-info-banner__content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .ax-conversation-info-banner__close{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.65);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-info-bar .ax-conversation-info-banner__close:hover{color:rgba(var(--ax-sys-color-on-primary-lightest-surface));background:rgba(var(--ax-sys-color-primary-500),.12)}}ax-conversation-info-bar .ax-conversation-info-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-info-bar .info-bar-empty{justify-content:center;opacity:60%}ax-conversation-info-bar .info-prefix{flex-shrink:0}ax-conversation-info-bar .info-left{margin-inline:calc(var(--spacing, .25rem) * -1.5);margin-block:calc(var(--spacing, .25rem) * -1);display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:calc(var(--spacing, .25rem) * 1);transition:background-color .15s ease}ax-conversation-info-bar .info-left:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-500))}ax-conversation-info-bar .avatar-wrapper{flex-shrink:0}ax-conversation-info-bar .info-details{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .info-title{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}ax-conversation-info-bar .info-subtitle-with-status{margin-top:calc(var(--spacing, .25rem) * .5);margin-bottom:calc(var(--spacing, .25rem) * 0);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5)}ax-conversation-info-bar .online-badge{font-size:.625rem;--tw-leading: 1;line-height:1;color:rgba(var(--ax-sys-color-success-500));animation:axInfoBarPulse 2s cubic-bezier(.4,0,.6,1) infinite}ax-conversation-info-bar .info-subtitle{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.85rem;--tw-tracking: .02rem;letter-spacing:.02rem;text-overflow:ellipsis;white-space:nowrap;opacity:70%}ax-conversation-info-bar .info-actions{display:flex;flex-shrink:0;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .info-component-fullwidth{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);inset-block:calc(var(--spacing, .25rem) * 0);z-index:10;display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);background-color:rgba(var(--ax-sys-color-lightest-surface));padding:calc(var(--spacing, .25rem) * 4)}ax-conversation-info-bar .slide-in{animation:axInfoBarSlideIn var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-info-bar .slide-out{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%));transition:opacity .25s cubic-bezier(.4,0,1,1),transform .25s cubic-bezier(.4,0,1,1)}ax-conversation-info-bar .info-component-fullwidth>*:first-child{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .action-button{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--radius-lg, .5rem);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)));transition:background .2s}ax-conversation-info-bar .action-button:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-info-bar .search-container{display:flex;width:100%;min-width:calc(var(--spacing, .25rem) * 48);align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .search-input{min-width:calc(var(--spacing, .25rem) * 0);flex:1}[dir=rtl] ax-conversation-info-bar{--ax-info-bar-slide-distance: -100%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-border-style: solid;--tw-outline-style: solid;--tw-font-weight: initial;--tw-tracking: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "component", type: AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }], encapsulation: i0.ViewEncapsulation.None }); }
7853
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationInfoBarComponent, isStandalone: true, selector: "ax-conversation-info-bar", outputs: { infoClick: "infoClick", searchClick: "searchClick", searchQuery: "searchQuery", menuItemAction: "menuItemAction" }, ngImport: i0, template: "@if (activeConversation(); as conversation) {\n <div class=\"info-bar\">\n <!-- Left: Avatar and Info -->\n <div class=\"info-prefix\" (click)=\"$event.stopPropagation()\">\n <ng-content select=\"ax-prefix\"></ng-content>\n </div>\n <div\n class=\"info-left\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onInfoLeftClick()\"\n (keydown.enter)=\"onInfoLeftClick()\"\n (keydown.space)=\"$event.preventDefault(); onInfoLeftClick()\"\n >\n <div class=\"avatar-wrapper\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"conversation\"\n [size]=\"48\"\n [showStatus]=\"conversation.type === 'private' && !hasCustomUserAvatar()\"\n />\n </div>\n\n <div class=\"info-details\">\n <p class=\"info-title\">{{ conversation.title }}</p>\n @if (conversation.type !== 'private') {\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n } @else {\n <div class=\"info-subtitle-with-status\">\n @if (getStatus(conversation) === 'online' && !hasCustomUserAvatar()) {\n <span class=\"online-badge\">\u25CF</span>\n }\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Right: Actions or Full-Width Component -->\n @if (!activeComponent() || !isActiveComponentFullWidth()) {\n <div class=\"info-actions\" (click)=\"$event.stopPropagation()\">\n <!-- Inline action buttons from registry -->\n @for (action of inlineActions(); track action.id) {\n @if ((action.component || action.componentLoader) && action.fullWidthComponent === false) {\n <ax-conversation-registry-component-outlet\n [component]=\"action.component\"\n [componentLoader]=\"action.componentLoader\"\n [inputs]=\"getInlineComponentInputs()\"\n />\n } @else {\n <ax-button class=\"action-button\" (onClick)=\"onInlineActionClick(action.id)\" look=\"ghost\">\n <ax-icon [icon]=\"registry.infoBarActions.getActionIcon(action, activeConversation()!)\"></ax-icon>\n </ax-button>\n }\n }\n\n <ax-button look=\"blank\">\n <ax-icon><i class=\"fa-light fa-ellipsis-vertical\"></i></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of menuItems(); track item.id) {\n @if (item.divider) {\n <ax-divider></ax-divider>\n } @else {\n <ax-button-item\n [text]=\"item.label\"\n [disabled]=\"item.disabled\"\n [color]=\"item.destructive ? 'danger' : 'default'\"\n (onClick)=\"onMenuItemClick(item)\"\n >\n @if (item.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n }\n @if (item.shortcut) {\n <ax-suffix>\n <ax-label class=\"shortcut\">{{ item.shortcut }}</ax-label>\n </ax-suffix>\n }\n </ax-button-item>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n\n @if (activeComponent() && isActiveComponentFullWidth()) {\n <!-- Full-width component mode (e.g., search) - takes entire info-bar -->\n <div\n class=\"info-component-fullwidth\"\n animate.enter=\"slide-in\"\n animate.leave=\"slide-out\"\n (click)=\"$event.stopPropagation()\"\n >\n <ax-conversation-registry-component-outlet\n [component]=\"activeComponent()!.component\"\n [componentLoader]=\"activeComponent()!.componentLoader\"\n [inputs]=\"getComponentInputs()\"\n />\n <ax-button class=\"action-button close-button\" (onClick)=\"onCloseComponent()\" [look]=\"'ghost'\">\n <ax-icon><i class=\"fa-light fa-xmark\"></i></ax-icon>\n </ax-button>\n </div>\n }\n </div>\n\n @if (activeBanner()) {\n <div class=\"ax-conversation-info-banner\" (click)=\"$event.stopPropagation()\">\n <div class=\"ax-conversation-info-banner__content\">\n <ax-conversation-registry-component-outlet\n [component]=\"activeBanner()!.component\"\n [componentLoader]=\"activeBanner()!.componentLoader\"\n [inputs]=\"getBannerInputs()\"\n />\n </div>\n <button\n type=\"button\"\n class=\"ax-conversation-info-banner__close\"\n (click)=\"onCloseBanner()\"\n [attr.aria-label]=\"'Close'\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n}\n", styles: ["@layer properties;@layer components{ax-conversation-info-bar{display:block;max-width:100%;@keyframes axInfoBarPulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes axInfoBarSlideIn{0%{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%))}to{opacity:1;transform:translate(0)}}}ax-conversation-info-bar .info-bar{position:relative;display:flex;min-height:calc(var(--spacing, .25rem) * 16);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);overflow:hidden;padding:calc(var(--spacing, .25rem) * 2);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-info-bar .ax-conversation-info-banner{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:calc(var(--spacing, .25rem) * 2);padding-inline-start:calc(var(--spacing, .25rem) * 3);padding-inline-end:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .ax-conversation-info-banner__content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .ax-conversation-info-banner__close{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.65);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-info-bar .ax-conversation-info-banner__close:hover{color:rgba(var(--ax-sys-color-on-primary-lightest-surface));background:rgba(var(--ax-sys-color-primary-500),.12)}}ax-conversation-info-bar .ax-conversation-info-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-info-bar .info-bar-empty{justify-content:center;opacity:60%}ax-conversation-info-bar .info-prefix{flex-shrink:0}ax-conversation-info-bar .info-left{margin-inline:calc(var(--spacing, .25rem) * -1.5);margin-block:calc(var(--spacing, .25rem) * -1);display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:calc(var(--spacing, .25rem) * 1);transition:background-color .15s ease}ax-conversation-info-bar .info-left:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-500))}ax-conversation-info-bar .avatar-wrapper{flex-shrink:0}ax-conversation-info-bar .info-details{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .info-title{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}ax-conversation-info-bar .info-subtitle-with-status{margin-top:calc(var(--spacing, .25rem) * .5);margin-bottom:calc(var(--spacing, .25rem) * 0);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5)}ax-conversation-info-bar .online-badge{font-size:.625rem;--tw-leading: 1;line-height:1;color:rgba(var(--ax-sys-color-success-500));animation:axInfoBarPulse 2s cubic-bezier(.4,0,.6,1) infinite}ax-conversation-info-bar .info-subtitle{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.85rem;--tw-tracking: .02rem;letter-spacing:.02rem;text-overflow:ellipsis;white-space:nowrap;opacity:70%}ax-conversation-info-bar .info-actions{display:flex;flex-shrink:0;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .info-component-fullwidth{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);inset-block:calc(var(--spacing, .25rem) * 0);z-index:10;display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);background-color:rgba(var(--ax-sys-color-lightest-surface));padding:calc(var(--spacing, .25rem) * 4)}ax-conversation-info-bar .slide-in{animation:axInfoBarSlideIn var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-info-bar .slide-out{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%));transition:opacity .25s cubic-bezier(.4,0,1,1),transform .25s cubic-bezier(.4,0,1,1)}ax-conversation-info-bar .info-component-fullwidth>*:first-child{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .action-button{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--radius-lg, .5rem);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)));transition:background .2s}ax-conversation-info-bar .action-button:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-info-bar .search-container{display:flex;width:100%;min-width:calc(var(--spacing, .25rem) * 48);align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .search-input{min-width:calc(var(--spacing, .25rem) * 0);flex:1}[dir=rtl] ax-conversation-info-bar{--ax-info-bar-slide-distance: -100%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-border-style: solid;--tw-outline-style: solid;--tw-font-weight: initial;--tw-tracking: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "component", type: AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }], encapsulation: i0.ViewEncapsulation.None }); }
7636
7854
  }
7637
7855
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationInfoBarComponent, decorators: [{
7638
7856
  type: Component,
@@ -7646,7 +7864,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
7646
7864
  AXLabelComponent,
7647
7865
  AXConversationAvatarComponent,
7648
7866
  AXConversationRegistryComponentOutletComponent,
7649
- ], template: "@if (activeConversation(); as conversation) {\n <div class=\"info-bar\">\n <!-- Left: Avatar and Info -->\n <div class=\"info-prefix\" (click)=\"$event.stopPropagation()\">\n <ng-content select=\"ax-prefix\"></ng-content>\n </div>\n <div\n class=\"info-left\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onInfoLeftClick()\"\n (keydown.enter)=\"onInfoLeftClick()\"\n (keydown.space)=\"$event.preventDefault(); onInfoLeftClick()\"\n >\n <div class=\"avatar-wrapper\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"conversation\"\n [size]=\"48\"\n [showStatus]=\"conversation.type === 'private'\"\n />\n </div>\n\n <div class=\"info-details\">\n <p class=\"info-title\">{{ conversation.title }}</p>\n @if (conversation.type !== 'private') {\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n } @else {\n <div class=\"info-subtitle-with-status\">\n @if (getStatus(conversation) === 'online' && !hasCustomUserAvatar()) {\n <span class=\"online-badge\">\u25CF</span>\n }\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Right: Actions or Full-Width Component -->\n @if (!activeComponent() || !isActiveComponentFullWidth()) {\n <div class=\"info-actions\" (click)=\"$event.stopPropagation()\">\n <!-- Inline action buttons from registry -->\n @for (action of inlineActions(); track action.id) {\n @if ((action.component || action.componentLoader) && action.fullWidthComponent === false) {\n <ax-conversation-registry-component-outlet\n [component]=\"action.component\"\n [componentLoader]=\"action.componentLoader\"\n [inputs]=\"getInlineComponentInputs()\"\n />\n } @else {\n <ax-button class=\"action-button\" (onClick)=\"onInlineActionClick(action.id)\" look=\"ghost\">\n <ax-icon [icon]=\"registry.infoBarActions.getActionIcon(action, activeConversation()!)\"></ax-icon>\n </ax-button>\n }\n }\n\n <ax-button look=\"blank\">\n <ax-icon><i class=\"fa-light fa-ellipsis-vertical\"></i></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of menuItems(); track item.id) {\n @if (item.divider) {\n <ax-divider></ax-divider>\n } @else {\n <ax-button-item\n [text]=\"item.label\"\n [disabled]=\"item.disabled\"\n [color]=\"item.destructive ? 'danger' : 'default'\"\n (onClick)=\"onMenuItemClick(item)\"\n >\n @if (item.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n }\n @if (item.shortcut) {\n <ax-suffix>\n <ax-label class=\"shortcut\">{{ item.shortcut }}</ax-label>\n </ax-suffix>\n }\n </ax-button-item>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n\n @if (activeComponent() && isActiveComponentFullWidth()) {\n <!-- Full-width component mode (e.g., search) - takes entire info-bar -->\n <div\n class=\"info-component-fullwidth\"\n animate.enter=\"slide-in\"\n animate.leave=\"slide-out\"\n (click)=\"$event.stopPropagation()\"\n >\n <ax-conversation-registry-component-outlet\n [component]=\"activeComponent()!.component\"\n [componentLoader]=\"activeComponent()!.componentLoader\"\n [inputs]=\"getComponentInputs()\"\n />\n <ax-button class=\"action-button close-button\" (onClick)=\"onCloseComponent()\" [look]=\"'ghost'\">\n <ax-icon><i class=\"fa-light fa-xmark\"></i></ax-icon>\n </ax-button>\n </div>\n }\n </div>\n\n @if (activeBanner()) {\n <div class=\"ax-conversation-info-banner\" (click)=\"$event.stopPropagation()\">\n <div class=\"ax-conversation-info-banner__content\">\n <ax-conversation-registry-component-outlet\n [component]=\"activeBanner()!.component\"\n [componentLoader]=\"activeBanner()!.componentLoader\"\n [inputs]=\"getBannerInputs()\"\n />\n </div>\n <button\n type=\"button\"\n class=\"ax-conversation-info-banner__close\"\n (click)=\"onCloseBanner()\"\n [attr.aria-label]=\"'Close'\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n}\n", styles: ["@layer properties;@layer components{ax-conversation-info-bar{display:block;max-width:100%;@keyframes axInfoBarPulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes axInfoBarSlideIn{0%{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%))}to{opacity:1;transform:translate(0)}}}ax-conversation-info-bar .info-bar{position:relative;display:flex;min-height:calc(var(--spacing, .25rem) * 16);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);overflow:hidden;padding:calc(var(--spacing, .25rem) * 2);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-info-bar .ax-conversation-info-banner{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:calc(var(--spacing, .25rem) * 2);padding-inline-start:calc(var(--spacing, .25rem) * 3);padding-inline-end:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .ax-conversation-info-banner__content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .ax-conversation-info-banner__close{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.65);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-info-bar .ax-conversation-info-banner__close:hover{color:rgba(var(--ax-sys-color-on-primary-lightest-surface));background:rgba(var(--ax-sys-color-primary-500),.12)}}ax-conversation-info-bar .ax-conversation-info-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-info-bar .info-bar-empty{justify-content:center;opacity:60%}ax-conversation-info-bar .info-prefix{flex-shrink:0}ax-conversation-info-bar .info-left{margin-inline:calc(var(--spacing, .25rem) * -1.5);margin-block:calc(var(--spacing, .25rem) * -1);display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:calc(var(--spacing, .25rem) * 1);transition:background-color .15s ease}ax-conversation-info-bar .info-left:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-500))}ax-conversation-info-bar .avatar-wrapper{flex-shrink:0}ax-conversation-info-bar .info-details{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .info-title{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}ax-conversation-info-bar .info-subtitle-with-status{margin-top:calc(var(--spacing, .25rem) * .5);margin-bottom:calc(var(--spacing, .25rem) * 0);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5)}ax-conversation-info-bar .online-badge{font-size:.625rem;--tw-leading: 1;line-height:1;color:rgba(var(--ax-sys-color-success-500));animation:axInfoBarPulse 2s cubic-bezier(.4,0,.6,1) infinite}ax-conversation-info-bar .info-subtitle{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.85rem;--tw-tracking: .02rem;letter-spacing:.02rem;text-overflow:ellipsis;white-space:nowrap;opacity:70%}ax-conversation-info-bar .info-actions{display:flex;flex-shrink:0;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .info-component-fullwidth{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);inset-block:calc(var(--spacing, .25rem) * 0);z-index:10;display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);background-color:rgba(var(--ax-sys-color-lightest-surface));padding:calc(var(--spacing, .25rem) * 4)}ax-conversation-info-bar .slide-in{animation:axInfoBarSlideIn var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-info-bar .slide-out{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%));transition:opacity .25s cubic-bezier(.4,0,1,1),transform .25s cubic-bezier(.4,0,1,1)}ax-conversation-info-bar .info-component-fullwidth>*:first-child{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .action-button{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--radius-lg, .5rem);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)));transition:background .2s}ax-conversation-info-bar .action-button:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-info-bar .search-container{display:flex;width:100%;min-width:calc(var(--spacing, .25rem) * 48);align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .search-input{min-width:calc(var(--spacing, .25rem) * 0);flex:1}[dir=rtl] ax-conversation-info-bar{--ax-info-bar-slide-distance: -100%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-border-style: solid;--tw-outline-style: solid;--tw-font-weight: initial;--tw-tracking: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
7867
+ ], template: "@if (activeConversation(); as conversation) {\n <div class=\"info-bar\">\n <!-- Left: Avatar and Info -->\n <div class=\"info-prefix\" (click)=\"$event.stopPropagation()\">\n <ng-content select=\"ax-prefix\"></ng-content>\n </div>\n <div\n class=\"info-left\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onInfoLeftClick()\"\n (keydown.enter)=\"onInfoLeftClick()\"\n (keydown.space)=\"$event.preventDefault(); onInfoLeftClick()\"\n >\n <div class=\"avatar-wrapper\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"conversation\"\n [size]=\"48\"\n [showStatus]=\"conversation.type === 'private' && !hasCustomUserAvatar()\"\n />\n </div>\n\n <div class=\"info-details\">\n <p class=\"info-title\">{{ conversation.title }}</p>\n @if (conversation.type !== 'private') {\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n } @else {\n <div class=\"info-subtitle-with-status\">\n @if (getStatus(conversation) === 'online' && !hasCustomUserAvatar()) {\n <span class=\"online-badge\">\u25CF</span>\n }\n <p class=\"info-subtitle\">{{ getSubtitle(conversation) }}</p>\n </div>\n }\n </div>\n </div>\n\n <!-- Right: Actions or Full-Width Component -->\n @if (!activeComponent() || !isActiveComponentFullWidth()) {\n <div class=\"info-actions\" (click)=\"$event.stopPropagation()\">\n <!-- Inline action buttons from registry -->\n @for (action of inlineActions(); track action.id) {\n @if ((action.component || action.componentLoader) && action.fullWidthComponent === false) {\n <ax-conversation-registry-component-outlet\n [component]=\"action.component\"\n [componentLoader]=\"action.componentLoader\"\n [inputs]=\"getInlineComponentInputs()\"\n />\n } @else {\n <ax-button class=\"action-button\" (onClick)=\"onInlineActionClick(action.id)\" look=\"ghost\">\n <ax-icon [icon]=\"registry.infoBarActions.getActionIcon(action, activeConversation()!)\"></ax-icon>\n </ax-button>\n }\n }\n\n <ax-button look=\"blank\">\n <ax-icon><i class=\"fa-light fa-ellipsis-vertical\"></i></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of menuItems(); track item.id) {\n @if (item.divider) {\n <ax-divider></ax-divider>\n } @else {\n <ax-button-item\n [text]=\"item.label\"\n [disabled]=\"item.disabled\"\n [color]=\"item.destructive ? 'danger' : 'default'\"\n (onClick)=\"onMenuItemClick(item)\"\n >\n @if (item.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n }\n @if (item.shortcut) {\n <ax-suffix>\n <ax-label class=\"shortcut\">{{ item.shortcut }}</ax-label>\n </ax-suffix>\n }\n </ax-button-item>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n\n @if (activeComponent() && isActiveComponentFullWidth()) {\n <!-- Full-width component mode (e.g., search) - takes entire info-bar -->\n <div\n class=\"info-component-fullwidth\"\n animate.enter=\"slide-in\"\n animate.leave=\"slide-out\"\n (click)=\"$event.stopPropagation()\"\n >\n <ax-conversation-registry-component-outlet\n [component]=\"activeComponent()!.component\"\n [componentLoader]=\"activeComponent()!.componentLoader\"\n [inputs]=\"getComponentInputs()\"\n />\n <ax-button class=\"action-button close-button\" (onClick)=\"onCloseComponent()\" [look]=\"'ghost'\">\n <ax-icon><i class=\"fa-light fa-xmark\"></i></ax-icon>\n </ax-button>\n </div>\n }\n </div>\n\n @if (activeBanner()) {\n <div class=\"ax-conversation-info-banner\" (click)=\"$event.stopPropagation()\">\n <div class=\"ax-conversation-info-banner__content\">\n <ax-conversation-registry-component-outlet\n [component]=\"activeBanner()!.component\"\n [componentLoader]=\"activeBanner()!.componentLoader\"\n [inputs]=\"getBannerInputs()\"\n />\n </div>\n <button\n type=\"button\"\n class=\"ax-conversation-info-banner__close\"\n (click)=\"onCloseBanner()\"\n [attr.aria-label]=\"'Close'\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n }\n}\n", styles: ["@layer properties;@layer components{ax-conversation-info-bar{display:block;max-width:100%;@keyframes axInfoBarPulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes axInfoBarSlideIn{0%{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%))}to{opacity:1;transform:translate(0)}}}ax-conversation-info-bar .info-bar{position:relative;display:flex;min-height:calc(var(--spacing, .25rem) * 16);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);overflow:hidden;padding:calc(var(--spacing, .25rem) * 2);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-info-bar .ax-conversation-info-banner{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:calc(var(--spacing, .25rem) * 2);padding-inline-start:calc(var(--spacing, .25rem) * 3);padding-inline-end:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .ax-conversation-info-banner__content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .ax-conversation-info-banner__close{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);flex-shrink:0;cursor:pointer;touch-action:manipulation;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-on-primary-lightest-surface),.65);transition:background-color .15s ease,color .15s ease}@media(hover:hover){ax-conversation-info-bar .ax-conversation-info-banner__close:hover{color:rgba(var(--ax-sys-color-on-primary-lightest-surface));background:rgba(var(--ax-sys-color-primary-500),.12)}}ax-conversation-info-bar .ax-conversation-info-banner__close:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-info-bar .info-bar-empty{justify-content:center;opacity:60%}ax-conversation-info-bar .info-prefix{flex-shrink:0}ax-conversation-info-bar .info-left{margin-inline:calc(var(--spacing, .25rem) * -1.5);margin-block:calc(var(--spacing, .25rem) * -1);display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:calc(var(--spacing, .25rem) * 1);transition:background-color .15s ease}ax-conversation-info-bar .info-left:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-500))}ax-conversation-info-bar .avatar-wrapper{flex-shrink:0}ax-conversation-info-bar .info-details{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .info-title{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}ax-conversation-info-bar .info-subtitle-with-status{margin-top:calc(var(--spacing, .25rem) * .5);margin-bottom:calc(var(--spacing, .25rem) * 0);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5)}ax-conversation-info-bar .online-badge{font-size:.625rem;--tw-leading: 1;line-height:1;color:rgba(var(--ax-sys-color-success-500));animation:axInfoBarPulse 2s cubic-bezier(.4,0,.6,1) infinite}ax-conversation-info-bar .info-subtitle{margin:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.85rem;--tw-tracking: .02rem;letter-spacing:.02rem;text-overflow:ellipsis;white-space:nowrap;opacity:70%}ax-conversation-info-bar .info-actions{display:flex;flex-shrink:0;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .info-component-fullwidth{position:absolute;inset-inline:calc(var(--spacing, .25rem) * 0);inset-block:calc(var(--spacing, .25rem) * 0);z-index:10;display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);background-color:rgba(var(--ax-sys-color-lightest-surface));padding:calc(var(--spacing, .25rem) * 4)}ax-conversation-info-bar .slide-in{animation:axInfoBarSlideIn var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-info-bar .slide-out{opacity:0;transform:translate(var(--ax-info-bar-slide-distance, 100%));transition:opacity .25s cubic-bezier(.4,0,1,1),transform .25s cubic-bezier(.4,0,1,1)}ax-conversation-info-bar .info-component-fullwidth>*:first-child{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-info-bar .action-button{display:flex;height:calc(var(--spacing, .25rem) * 9);width:calc(var(--spacing, .25rem) * 9);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--radius-lg, .5rem);--tw-border-style: none;border-style:none;background-color:transparent;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)));transition:background .2s}ax-conversation-info-bar .action-button:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-info-bar .search-container{display:flex;width:100%;min-width:calc(var(--spacing, .25rem) * 48);align-items:center;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-info-bar .search-input{min-width:calc(var(--spacing, .25rem) * 0);flex:1}[dir=rtl] ax-conversation-info-bar{--ax-info-bar-slide-distance: -100%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-border-style: solid;--tw-outline-style: solid;--tw-font-weight: initial;--tw-tracking: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
7650
7868
  }], ctorParameters: () => [], propDecorators: { infoClick: [{ type: i0.Output, args: ["infoClick"] }], searchClick: [{ type: i0.Output, args: ["searchClick"] }], searchQuery: [{ type: i0.Output, args: ["searchQuery"] }], menuItemAction: [{ type: i0.Output, args: ["menuItemAction"] }] } });
7651
7869
 
7652
7870
  class AXConversationForwardMessageDialogComponent {
@@ -7681,7 +7899,9 @@ class AXConversationForwardMessageDialogComponent {
7681
7899
  },
7682
7900
  byKey: (key) => Promise.resolve(this.allConversations().find((c) => c.id === key) ?? null),
7683
7901
  });
7684
- this.canForward = computed(() => this.selectedConversationIds().length > 0, /* @ts-ignore */
7902
+ this.isForwarding = computed(() => this.conversationService?.isForwardingMessage() ?? false, /* @ts-ignore */
7903
+ ...(ngDevMode ? [{ debugName: "isForwarding" }] : /* istanbul ignore next */ []));
7904
+ this.canForward = computed(() => this.selectedConversationIds().length > 0 && !this.isForwarding(), /* @ts-ignore */
7685
7905
  ...(ngDevMode ? [{ debugName: "canForward" }] : /* istanbul ignore next */ []));
7686
7906
  this._syncPopupTitleEffect = effect(() => {
7687
7907
  const popupRef = this.__popup__();
@@ -7728,38 +7948,40 @@ class AXConversationForwardMessageDialogComponent {
7728
7948
  if (!this.conversationService || !this.message)
7729
7949
  return;
7730
7950
  const selectedIds = this.selectedConversationIds();
7731
- if (selectedIds.length === 0)
7951
+ if (selectedIds.length === 0 || this.isForwarding())
7732
7952
  return;
7733
7953
  try {
7734
- const originalConversation = this.conversationService
7735
- .conversations()
7736
- .find((c) => c.id === this.message.conversationId);
7737
- const sender = originalConversation?.participants.find((p) => p.id === this.message.senderId);
7738
- const forwardPromises = selectedIds.map(async (conversationId) => {
7739
- const forwardCommand = {
7740
- conversationId,
7741
- type: this.message.type,
7742
- payload: this.message.payload,
7743
- forwarded: true,
7744
- forwardedFrom: {
7745
- messageId: this.message.id,
7746
- senderId: this.message.senderId,
7747
- senderName: sender?.name || this.translation.translateSync('@acorex:chat.fallbacks.unknown-user'),
7748
- conversationId: this.message.conversationId,
7749
- conversationTitle: originalConversation?.title,
7750
- },
7751
- originalSenderId: this.message.senderId,
7752
- metadata: this.message.metadata,
7753
- };
7754
- return this.conversationService.sendMessage(forwardCommand);
7954
+ await this.conversationService.runWithForwardingLock(async () => {
7955
+ const originalConversation = this.conversationService
7956
+ .conversations()
7957
+ .find((c) => c.id === this.message.conversationId);
7958
+ const sender = originalConversation?.participants.find((p) => p.id === this.message.senderId);
7959
+ const forwardPromises = selectedIds.map(async (conversationId) => {
7960
+ const forwardCommand = {
7961
+ conversationId,
7962
+ type: this.message.type,
7963
+ payload: this.message.payload,
7964
+ forwarded: true,
7965
+ forwardedFrom: {
7966
+ messageId: this.message.id,
7967
+ senderId: this.message.senderId,
7968
+ senderName: sender?.name || this.translation.translateSync('@acorex:chat.fallbacks.unknown-user'),
7969
+ conversationId: this.message.conversationId,
7970
+ conversationTitle: originalConversation?.title,
7971
+ },
7972
+ originalSenderId: this.message.senderId,
7973
+ metadata: this.message.metadata,
7974
+ };
7975
+ return this.conversationService.sendMessage(forwardCommand);
7976
+ });
7977
+ await Promise.all(forwardPromises);
7978
+ const count = selectedIds.length;
7979
+ this.toastService.success(this.translation.translateSync('@acorex:chat.notifications.message-forwarded', { params: { count } }));
7980
+ const event = new AXComponentCloseEvent();
7981
+ event.component = this;
7982
+ event.data = { success: true, count };
7983
+ this.onClosed.emit(event);
7755
7984
  });
7756
- await Promise.all(forwardPromises);
7757
- const count = selectedIds.length;
7758
- this.toastService.success(this.translation.translateSync('@acorex:chat.notifications.message-forwarded', { params: { count } }));
7759
- const event = new AXComponentCloseEvent();
7760
- event.component = this;
7761
- event.data = { success: true, count };
7762
- this.onClosed.emit(event);
7763
7985
  }
7764
7986
  catch (error) {
7765
7987
  console.error('Failed to forward message:', error);
@@ -7773,7 +7995,7 @@ class AXConversationForwardMessageDialogComponent {
7773
7995
  }
7774
7996
  }
7775
7997
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationForwardMessageDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7776
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationForwardMessageDialogComponent, isStandalone: true, selector: "ax-conversation-forward-message-dialog", inputs: { __popup__: { classPropertyName: "__popup__", publicName: "__popup__", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: AXClosableComponent, useExisting: AXConversationForwardMessageDialogComponent }], viewQueries: [{ propertyName: "forwardListEmptyTpl", first: true, predicate: ["forwardListEmpty"], descendants: true, isSignal: true }, { propertyName: "forwardList", first: true, predicate: ["forwardList"], descendants: true, isSignal: true }], ngImport: i0, template: " <div class=\"forward-message-dialog\">\n <ng-template #forwardListEmpty>\n <div class=\"forward-list-empty\">\n @if (forwardSearchQuery()) {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-search' | translate | async }}\n } @else {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-available' | translate | async }}\n }\n </div>\n </ng-template>\n\n <div class=\"dialog-content\">\n <div class=\"forward-list-wrap\">\n <ax-list\n #forwardList\n class=\"forward-list\"\n [dataSource]=\"forwardListDataSource\"\n [multiple]=\"true\"\n [valueField]=\"'id'\"\n [textField]=\"'title'\"\n [checkbox]=\"false\"\n [itemHeight]=\"52\"\n [ngModel]=\"selectedConversationIds()\"\n (ngModelChange)=\"selectedConversationIds.set($event ?? [])\"\n [emptyTemplate]=\"forwardListEmptyTpl()\"\n [itemTemplate]=\"forwardItemTpl\"\n >\n <ax-header class=\"forward-list-header\">\n <div class=\"forward-list-header-inner\">\n <ax-search-box\n [value]=\"forwardSearchQuery()\"\n (valueChange)=\"onForwardSearchChange($event)\"\n [placeholder]=\"'@acorex:chat.placeholders.search-conversations' | translate | async\"\n ></ax-search-box>\n </div>\n </ax-header>\n </ax-list>\n </div>\n </div>\n\n <ng-template #forwardItemTpl let-item>\n @if (conversationFromItem(item); as conversation) {\n <div class=\"forward-item-content\">\n <input class=\"ax-checkbox\" type=\"checkbox\" [checked]=\"isSelected(conversation.id)\" tabindex=\"0\" />\n <ax-conversation-avatar kind=\"auto\" [conversation]=\"conversation\" [size]=\"36\" />\n <span class=\"forward-title-text ax-truncated\">{{ conversation.title }}</span>\n </div>\n }\n </ng-template>\n\n <ax-footer class=\"dialog-footer\">\n <ax-suffix>\n <ax-button\n [text]=\"'@acorex:chat.actions.cancel' | translate | async\"\n [look]=\"'solid'\"\n (onClick)=\"onCancel()\"\n ></ax-button>\n <ax-button\n [text]=\"'@acorex:chat.actions.forward' | translate | async\"\n [look]=\"'solid'\"\n [color]=\"'primary'\"\n [disabled]=\"!canForward()\"\n (onClick)=\"onForward()\"\n ></ax-button>\n </ax-suffix>\n </ax-footer>\n </div>\n", styles: ["@layer properties;@layer components{ax-conversation-forward-message-dialog{display:block}ax-conversation-forward-message-dialog .forward-message-dialog{display:flex;width:100%;flex-direction:column;overflow:hidden}ax-conversation-forward-message-dialog .dialog-content{min-height:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden}ax-conversation-forward-message-dialog .forward-list-wrap{overflow:hidden;height:min(50vh,24rem)}ax-conversation-forward-message-dialog .forward-list{display:block;height:100%}ax-conversation-forward-message-dialog .forward-list-header{position:sticky;top:calc(var(--spacing, .25rem) * 0);z-index:10;display:block;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface))}ax-conversation-forward-message-dialog .forward-list-header-inner{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-forward-message-dialog .forward-item-content{display:flex;height:100%;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding:calc(var(--spacing, .25rem) * 2);transition:background-color .2s ease}ax-conversation-forward-message-dialog .forward-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: calc(var(--spacing, .25rem) * 5);line-height:calc(var(--spacing, .25rem) * 5);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-forward-message-dialog .forward-list-empty{padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 5);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-forward-message-dialog .dialog-footer{flex-shrink:0}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXListComponent, selector: "ax-list", inputs: ["id", "name", "disabled", "readonly", "valueField", "textField", "textTemplate", "disabledField", "multiple", "selectionMode", "isItemTruncated", "showItemTooltip", "dataSource", "itemHeight", "itemTemplate", "emptyTemplate", "loadingTemplate", "checkbox"], outputs: ["onValueChanged", "disabledChange", "readonlyChange", "onBlur", "onFocus", "onItemClick", "onItemSelected", "onScrolledIndexChanged"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
7998
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationForwardMessageDialogComponent, isStandalone: true, selector: "ax-conversation-forward-message-dialog", inputs: { __popup__: { classPropertyName: "__popup__", publicName: "__popup__", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: AXClosableComponent, useExisting: AXConversationForwardMessageDialogComponent }], viewQueries: [{ propertyName: "forwardListEmptyTpl", first: true, predicate: ["forwardListEmpty"], descendants: true, isSignal: true }, { propertyName: "forwardList", first: true, predicate: ["forwardList"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"forward-message-dialog\">\n <ng-template #forwardListEmpty>\n <div class=\"forward-list-empty\">\n @if (forwardSearchQuery()) {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-search' | translate | async }}\n } @else {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-available' | translate | async }}\n }\n </div>\n </ng-template>\n\n <div class=\"dialog-content\">\n <div class=\"forward-list-wrap\">\n <ax-list\n #forwardList\n class=\"forward-list\"\n [dataSource]=\"forwardListDataSource\"\n [multiple]=\"true\"\n [valueField]=\"'id'\"\n [textField]=\"'title'\"\n [checkbox]=\"false\"\n [itemHeight]=\"52\"\n [ngModel]=\"selectedConversationIds()\"\n (ngModelChange)=\"selectedConversationIds.set($event ?? [])\"\n [emptyTemplate]=\"forwardListEmptyTpl()\"\n [itemTemplate]=\"forwardItemTpl\"\n >\n <ax-header class=\"forward-list-header\">\n <div class=\"forward-list-header-inner\">\n <ax-search-box\n [value]=\"forwardSearchQuery()\"\n (valueChange)=\"onForwardSearchChange($event)\"\n [placeholder]=\"'@acorex:chat.placeholders.search-conversations' | translate | async\"\n ></ax-search-box>\n </div>\n </ax-header>\n </ax-list>\n </div>\n </div>\n\n <ng-template #forwardItemTpl let-item>\n @if (conversationFromItem(item); as conversation) {\n <div class=\"forward-item-content\">\n <input class=\"ax-checkbox\" type=\"checkbox\" [checked]=\"isSelected(conversation.id)\" tabindex=\"0\" />\n <ax-conversation-avatar kind=\"auto\" [conversation]=\"conversation\" [size]=\"36\" />\n <span class=\"forward-title-text ax-truncated\">{{ conversation.title }}</span>\n </div>\n }\n </ng-template>\n\n <ax-footer class=\"dialog-footer\">\n <ax-suffix>\n <ax-button\n [text]=\"'@acorex:chat.actions.cancel' | translate | async\"\n [look]=\"'solid'\"\n [disabled]=\"isForwarding()\"\n (onClick)=\"onCancel()\"\n >\n </ax-button>\n <ax-button\n [text]=\"'@acorex:chat.actions.forward' | translate | async\"\n [look]=\"'solid'\"\n [color]=\"'primary'\"\n [disabled]=\"!canForward()\"\n (onClick)=\"onForward()\"\n >\n @if (isForwarding()) {\n <ax-loading></ax-loading>\n }\n </ax-button>\n </ax-suffix>\n </ax-footer>\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-forward-message-dialog{display:block}ax-conversation-forward-message-dialog .forward-message-dialog{display:flex;width:100%;flex-direction:column;overflow:hidden}ax-conversation-forward-message-dialog .dialog-content{min-height:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden}ax-conversation-forward-message-dialog .forward-list-wrap{overflow:hidden;height:min(50vh,24rem)}ax-conversation-forward-message-dialog .forward-list{display:block;height:100%}ax-conversation-forward-message-dialog .forward-list-header{position:sticky;top:calc(var(--spacing, .25rem) * 0);z-index:10;display:block;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface))}ax-conversation-forward-message-dialog .forward-list-header-inner{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-forward-message-dialog .forward-item-content{display:flex;height:100%;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding:calc(var(--spacing, .25rem) * 2);transition:background-color .2s ease}ax-conversation-forward-message-dialog .forward-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: calc(var(--spacing, .25rem) * 5);line-height:calc(var(--spacing, .25rem) * 5);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-forward-message-dialog .forward-list-empty{padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 5);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-forward-message-dialog .dialog-footer{flex-shrink:0}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: AXListComponent, selector: "ax-list", inputs: ["id", "name", "disabled", "readonly", "valueField", "textField", "textTemplate", "disabledField", "multiple", "selectionMode", "isItemTruncated", "showItemTooltip", "dataSource", "itemHeight", "itemTemplate", "emptyTemplate", "loadingTemplate", "checkbox"], outputs: ["onValueChanged", "disabledChange", "readonlyChange", "onBlur", "onFocus", "onItemClick", "onItemSelected", "onScrolledIndexChanged"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "component", type: AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
7777
7999
  }
7778
8000
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationForwardMessageDialogComponent, decorators: [{
7779
8001
  type: Component,
@@ -7785,8 +8007,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
7785
8007
  AXButtonComponent,
7786
8008
  AXDecoratorGenericComponent,
7787
8009
  AXConversationAvatarComponent,
8010
+ AXLoadingComponent,
7788
8011
  AXTranslationModule,
7789
- ], providers: [{ provide: AXClosableComponent, useExisting: AXConversationForwardMessageDialogComponent }], template: " <div class=\"forward-message-dialog\">\n <ng-template #forwardListEmpty>\n <div class=\"forward-list-empty\">\n @if (forwardSearchQuery()) {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-search' | translate | async }}\n } @else {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-available' | translate | async }}\n }\n </div>\n </ng-template>\n\n <div class=\"dialog-content\">\n <div class=\"forward-list-wrap\">\n <ax-list\n #forwardList\n class=\"forward-list\"\n [dataSource]=\"forwardListDataSource\"\n [multiple]=\"true\"\n [valueField]=\"'id'\"\n [textField]=\"'title'\"\n [checkbox]=\"false\"\n [itemHeight]=\"52\"\n [ngModel]=\"selectedConversationIds()\"\n (ngModelChange)=\"selectedConversationIds.set($event ?? [])\"\n [emptyTemplate]=\"forwardListEmptyTpl()\"\n [itemTemplate]=\"forwardItemTpl\"\n >\n <ax-header class=\"forward-list-header\">\n <div class=\"forward-list-header-inner\">\n <ax-search-box\n [value]=\"forwardSearchQuery()\"\n (valueChange)=\"onForwardSearchChange($event)\"\n [placeholder]=\"'@acorex:chat.placeholders.search-conversations' | translate | async\"\n ></ax-search-box>\n </div>\n </ax-header>\n </ax-list>\n </div>\n </div>\n\n <ng-template #forwardItemTpl let-item>\n @if (conversationFromItem(item); as conversation) {\n <div class=\"forward-item-content\">\n <input class=\"ax-checkbox\" type=\"checkbox\" [checked]=\"isSelected(conversation.id)\" tabindex=\"0\" />\n <ax-conversation-avatar kind=\"auto\" [conversation]=\"conversation\" [size]=\"36\" />\n <span class=\"forward-title-text ax-truncated\">{{ conversation.title }}</span>\n </div>\n }\n </ng-template>\n\n <ax-footer class=\"dialog-footer\">\n <ax-suffix>\n <ax-button\n [text]=\"'@acorex:chat.actions.cancel' | translate | async\"\n [look]=\"'solid'\"\n (onClick)=\"onCancel()\"\n ></ax-button>\n <ax-button\n [text]=\"'@acorex:chat.actions.forward' | translate | async\"\n [look]=\"'solid'\"\n [color]=\"'primary'\"\n [disabled]=\"!canForward()\"\n (onClick)=\"onForward()\"\n ></ax-button>\n </ax-suffix>\n </ax-footer>\n </div>\n", styles: ["@layer properties;@layer components{ax-conversation-forward-message-dialog{display:block}ax-conversation-forward-message-dialog .forward-message-dialog{display:flex;width:100%;flex-direction:column;overflow:hidden}ax-conversation-forward-message-dialog .dialog-content{min-height:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden}ax-conversation-forward-message-dialog .forward-list-wrap{overflow:hidden;height:min(50vh,24rem)}ax-conversation-forward-message-dialog .forward-list{display:block;height:100%}ax-conversation-forward-message-dialog .forward-list-header{position:sticky;top:calc(var(--spacing, .25rem) * 0);z-index:10;display:block;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface))}ax-conversation-forward-message-dialog .forward-list-header-inner{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-forward-message-dialog .forward-item-content{display:flex;height:100%;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding:calc(var(--spacing, .25rem) * 2);transition:background-color .2s ease}ax-conversation-forward-message-dialog .forward-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: calc(var(--spacing, .25rem) * 5);line-height:calc(var(--spacing, .25rem) * 5);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-forward-message-dialog .forward-list-empty{padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 5);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-forward-message-dialog .dialog-footer{flex-shrink:0}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
8012
+ ], providers: [{ provide: AXClosableComponent, useExisting: AXConversationForwardMessageDialogComponent }], template: "<div class=\"forward-message-dialog\">\n <ng-template #forwardListEmpty>\n <div class=\"forward-list-empty\">\n @if (forwardSearchQuery()) {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-search' | translate | async }}\n } @else {\n {{ '@acorex:chat.dialog.forward-message.no-conversations-available' | translate | async }}\n }\n </div>\n </ng-template>\n\n <div class=\"dialog-content\">\n <div class=\"forward-list-wrap\">\n <ax-list\n #forwardList\n class=\"forward-list\"\n [dataSource]=\"forwardListDataSource\"\n [multiple]=\"true\"\n [valueField]=\"'id'\"\n [textField]=\"'title'\"\n [checkbox]=\"false\"\n [itemHeight]=\"52\"\n [ngModel]=\"selectedConversationIds()\"\n (ngModelChange)=\"selectedConversationIds.set($event ?? [])\"\n [emptyTemplate]=\"forwardListEmptyTpl()\"\n [itemTemplate]=\"forwardItemTpl\"\n >\n <ax-header class=\"forward-list-header\">\n <div class=\"forward-list-header-inner\">\n <ax-search-box\n [value]=\"forwardSearchQuery()\"\n (valueChange)=\"onForwardSearchChange($event)\"\n [placeholder]=\"'@acorex:chat.placeholders.search-conversations' | translate | async\"\n ></ax-search-box>\n </div>\n </ax-header>\n </ax-list>\n </div>\n </div>\n\n <ng-template #forwardItemTpl let-item>\n @if (conversationFromItem(item); as conversation) {\n <div class=\"forward-item-content\">\n <input class=\"ax-checkbox\" type=\"checkbox\" [checked]=\"isSelected(conversation.id)\" tabindex=\"0\" />\n <ax-conversation-avatar kind=\"auto\" [conversation]=\"conversation\" [size]=\"36\" />\n <span class=\"forward-title-text ax-truncated\">{{ conversation.title }}</span>\n </div>\n }\n </ng-template>\n\n <ax-footer class=\"dialog-footer\">\n <ax-suffix>\n <ax-button\n [text]=\"'@acorex:chat.actions.cancel' | translate | async\"\n [look]=\"'solid'\"\n [disabled]=\"isForwarding()\"\n (onClick)=\"onCancel()\"\n >\n </ax-button>\n <ax-button\n [text]=\"'@acorex:chat.actions.forward' | translate | async\"\n [look]=\"'solid'\"\n [color]=\"'primary'\"\n [disabled]=\"!canForward()\"\n (onClick)=\"onForward()\"\n >\n @if (isForwarding()) {\n <ax-loading></ax-loading>\n }\n </ax-button>\n </ax-suffix>\n </ax-footer>\n</div>\n", styles: ["@layer properties;@layer components{ax-conversation-forward-message-dialog{display:block}ax-conversation-forward-message-dialog .forward-message-dialog{display:flex;width:100%;flex-direction:column;overflow:hidden}ax-conversation-forward-message-dialog .dialog-content{min-height:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden}ax-conversation-forward-message-dialog .forward-list-wrap{overflow:hidden;height:min(50vh,24rem)}ax-conversation-forward-message-dialog .forward-list{display:block;height:100%}ax-conversation-forward-message-dialog .forward-list-header{position:sticky;top:calc(var(--spacing, .25rem) * 0);z-index:10;display:block;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface))}ax-conversation-forward-message-dialog .forward-list-header-inner{padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 2)}ax-conversation-forward-message-dialog .forward-item-content{display:flex;height:100%;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding:calc(var(--spacing, .25rem) * 2);transition:background-color .2s ease}ax-conversation-forward-message-dialog .forward-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: calc(var(--spacing, .25rem) * 5);line-height:calc(var(--spacing, .25rem) * 5);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-forward-message-dialog .forward-list-empty{padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 5);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-forward-message-dialog .dialog-footer{flex-shrink:0}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
7790
8013
  }], propDecorators: { __popup__: [{ type: i0.Input, args: [{ isSignal: true, alias: "__popup__", required: false }] }], forwardListEmptyTpl: [{ type: i0.ViewChild, args: ['forwardListEmpty', { isSignal: true }] }], forwardList: [{ type: i0.ViewChild, args: ['forwardList', { isSignal: true }] }] } });
7791
8014
 
7792
8015
  var forwardMessageDialog_component = /*#__PURE__*/Object.freeze({
@@ -8365,13 +8588,14 @@ class AXConversationMessageListComponent {
8365
8588
  return renderer?.component;
8366
8589
  }
8367
8590
  /** Resolve lazy renderer loader for message */
8591
+ static { this.fallbackRendererLoader = () => Promise.resolve().then(function () { return fallbackRenderer_component; }).then((m) => m.AXConversationFallbackRendererComponent); }
8368
8592
  getRendererComponentLoader(message) {
8369
8593
  const renderer = this.registry.messageRenderers.getRenderer(message);
8370
8594
  if (renderer?.componentLoader) {
8371
8595
  return renderer.componentLoader;
8372
8596
  }
8373
8597
  if (!renderer || !renderer.component) {
8374
- return () => Promise.resolve().then(function () { return fallbackRenderer_component; }).then((m) => m.AXConversationFallbackRendererComponent);
8598
+ return AXConversationMessageListComponent.fallbackRendererLoader;
8375
8599
  }
8376
8600
  return undefined;
8377
8601
  }
@@ -8758,11 +8982,10 @@ class AXConversationMessageListComponent {
8758
8982
  }
8759
8983
  /**
8760
8984
  * TrackBy function for message groups.
8761
- * Include the latest message id so new messages in the same date group re-render.
8985
+ * Track by date only new messages in the same day are handled by the inner message @for.
8762
8986
  */
8763
8987
  trackMessageGroup(index, group) {
8764
- const lastId = group.messages.at(-1)?.id ?? `empty-${index}`;
8765
- return `${group.date}:${lastId}`;
8988
+ return group.date;
8766
8989
  }
8767
8990
  /**
8768
8991
  * TrackBy function for messages
@@ -8772,7 +8995,7 @@ class AXConversationMessageListComponent {
8772
8995
  return message.id;
8773
8996
  }
8774
8997
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationMessageListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8775
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationMessageListComponent, isStandalone: true, selector: "ax-conversation-message-list", outputs: { messageAction: "messageAction" }, viewQueries: [{ propertyName: "reactionPopover", first: true, predicate: ["reactionPopover"], descendants: true, isSignal: true }, { propertyName: "messageListRef", first: true, predicate: ["messageList"], descendants: true, isSignal: true }, { propertyName: "messagesContainerRef", first: true, predicate: ["messagesContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (activeConversation(); as conv) {\n @for (cid of [conv.id]; track cid) {\n <div\n class=\"message-list message-list--conversation-surface\"\n [class.message-list--drag]=\"messageListDragging()\"\n #messageList\n role=\"log\"\n [attr.aria-label]=\"'@acorex:chat.aria.message-list' | translate | async\"\n aria-live=\"polite\"\n [style.background]=\"messageListBackgroundStyle()\"\n axUploaderZone\n [disableBrowse]=\"true\"\n (dragEnter)=\"onMessageListDragEnter()\"\n (dragLeave)=\"onMessageListDragLeave()\"\n (fileChange)=\"onMessageListFilesDropped($event)\"\n >\n @if (loading()) {\n <div\n class=\"list-loading\"\n role=\"status\"\n aria-busy=\"true\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-messages' | translate | async\"\n >\n <div class=\"messages-skeleton\" aria-hidden=\"true\">\n @for (item of loadingSkeletonItems; track item) {\n <div class=\"message-skeleton\" [class.message-skeleton--own]=\"$odd\">\n @if ($even && isGroupConversation()) {\n <ax-skeleton class=\"message-skeleton-avatar\" [animated]=\"true\"></ax-skeleton>\n }\n <ax-skeleton\n class=\"message-skeleton-bubble\"\n [class.message-skeleton-bubble--short]=\"$index % 3 === 1\"\n [class.message-skeleton-bubble--medium]=\"$index % 3 === 2\"\n [animated]=\"true\"\n ></ax-skeleton>\n </div>\n }\n </div>\n </div>\n } @else if (messages().length === 0) {\n <div class=\"list-empty\" role=\"status\" [attr.aria-label]=\"'@acorex:chat.status.no-messages' | translate | async\">\n <ng-content select=\"ax-conversation-message-list-empty, [ax-conversation-message-list-empty]\">\n <ng-container\n *ngComponentOutlet=\"resolvedEmptyStateComponent(); inputs: { conversation: activeConversation()! }\"\n ></ng-container>\n </ng-content>\n </div>\n } @else {\n <div\n class=\"messages-container\"\n (scroll)=\"onScroll($event)\"\n axInfiniteScroll\n [threshold]=\"config.infiniteScrollThreshold\"\n [edge]=\"'top'\"\n [scrollDisabled]=\"loading() || loadingMore() || !hasMoreMessages()\"\n (scrollThreshold)=\"onScrollThreshold($event)\"\n #messagesContainer\n role=\"feed\"\n [attr.aria-label]=\"'@acorex:chat.aria.messages' | translate | async\"\n >\n @if (loadingMore()) {\n <div\n class=\"list-loading-more list-loading-more--prepend\"\n role=\"status\"\n animate.enter=\"load-more-enter\"\n animate.leave=\"load-more-leave\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-older-messages' | translate | async\"\n >\n <div class=\"load-more-indicator\" aria-hidden=\"true\">\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n </div>\n <ax-label class=\"load-more-label\">{{\n '@acorex:chat.status.loading-older-messages' | translate | async\n }}</ax-label>\n </div>\n }\n @for (group of messageGroups(); track trackMessageGroup($index, group)) {\n <!-- Date Separator -->\n <div class=\"date-separator\" role=\"separator\" [attr.aria-label]=\"getDateSeparatorAriaLabel(group.dateLabel)\">\n <span class=\"date-separator__label\">{{ group.dateLabel }}</span>\n </div>\n\n <!-- Messages in this date group -->\n @for (message of group.messages; track trackMessage($index, message)) {\n <div\n [class]=\"getMessageClasses(message)\"\n role=\"article\"\n [attr.aria-label]=\"getMessageAriaLabel(message)\"\n [id]=\"'message-' + message.id\"\n >\n <!-- Avatar (only for group conversations and received messages) -->\n @if (shouldShowAvatar(message)) {\n <div class=\"message-avatar\">\n <ax-conversation-avatar\n kind=\"user\"\n [userId]=\"message.senderId\"\n [conversation]=\"activeConversation()\"\n [message]=\"message\"\n [size]=\"32\"\n />\n </div>\n }\n\n <div class=\"message-content-row\" [class.message-content-row-own]=\"isOwnMessage(message)\">\n @if (messageSupportsReactions(message)) {\n <button\n type=\"button\"\n class=\"add-reaction-button add-reaction-outside\"\n [class.add-reaction-visible]=\"reactionPickerTarget() === message.id\"\n (click)=\"toggleReactionPicker(message, $event)\"\n [attr.aria-label]=\"'@acorex:chat.actions.add-reaction' | translate | async\"\n #reactionButton\n >\n <i class=\"fa-light fa-face-smile\"></i>\n </button>\n }\n\n <div\n class=\"message-bubble-container\"\n [id]=\"'message-bubble-' + message.id\"\n [attr.data-message-id]=\"message.id\"\n >\n <div\n [class]=\"getBubbleClasses(message)\"\n [class.message-bubble-sent]=\"message.senderId === currentUser()?.id\"\n [class.message-bubble-received]=\"message.senderId !== currentUser()?.id\"\n >\n <!-- Sender name (only for group conversations and received messages) -->\n @if (shouldShowSenderName(message)) {\n <div class=\"message-sender\">{{ getSenderName(message) }}:</div>\n }\n\n <!-- Reply Preview -->\n @if (message.replyTo) {\n <div\n class=\"reply-preview\"\n (click)=\"scrollToMessage(message.replyTo.id)\"\n role=\"button\"\n [attr.aria-label]=\"'Reply to ' + getSenderName(message.replyTo)\"\n (keydown.enter)=\"scrollToMessage(message.replyTo.id)\"\n (keydown.space)=\"scrollToMessage(message.replyTo.id)\"\n >\n <div class=\"reply-preview-content\">\n <div class=\"reply-preview-sender\">{{ getSenderName(message.replyTo) }}</div>\n <div class=\"reply-preview-text\">\n @if (getMessagePreviewText(message.replyTo); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i\n >{{ '@acorex:chat.' + preview.type | translate | async }}\n } @else {\n {{ preview.value }}\n }\n </span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Forwarded Indicator -->\n @if (message.forwarded) {\n <div class=\"forwarded-preview\">\n <i class=\"fa-solid fa-share\"></i>\n <span class=\"forwarded-text\">{{ getForwardedText(message) }}</span>\n </div>\n }\n\n <ax-conversation-registry-component-outlet\n [component]=\"getRendererComponent(message)\"\n [componentLoader]=\"getRendererComponentLoader(message)\"\n [inputs]=\"getRendererInputs(message)\"\n />\n\n @if (messageSupportsReactions(message) && message.reactions.length > 0) {\n <div class=\"message-reactions-container\">\n <div class=\"message-reactions-bubbles\">\n @for (reaction of getGroupedReactions(message); track reaction.emoji) {\n <button\n type=\"button\"\n class=\"reaction-bubble\"\n [class.reaction-bubble-active]=\"reaction.hasReacted\"\n (click)=\"onReactionClick(message, reaction.emoji)\"\n [attr.aria-label]=\"reaction.emoji + ' ' + reaction.count\"\n >\n <span class=\"reaction-emoji\">{{ reaction.emoji }}</span>\n @if (reaction.count > 1) {\n <span class=\"reaction-count\">{{ reaction.count }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Message Footer -->\n <div class=\"message-footer\">\n @let replyCount = getReplyCount(message);\n @let forwardCount = getForwardCount(message);\n @if (replyCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"replyCount + ' replies'\">\n <i class=\"fa-solid fa-message\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ replyCount }}</span>\n </span>\n }\n @if (forwardCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"forwardCount + ' forwards'\">\n <i class=\"fa-solid fa-share\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ forwardCount }}</span>\n </span>\n }\n @if (replyCount > 0 || forwardCount > 0) {\n <span class=\"message-footer-split\" aria-hidden=\"true\"></span>\n }\n <span class=\"message-time\">{{ message.timestamp | format: 'timeleft' | async }}</span>\n @if (message.editedAt) {\n <span class=\"edited-indicator\">\n <span>{{ '@acorex:chat.status.edited' | translate | async }}</span>\n </span>\n }\n @if (isOwnMessage(message)) {\n <span [class]=\"getStatusIconClasses(message)\">\n <ax-icon><i [class]=\"getStatusIcon(message)\"></i></ax-icon>\n </span>\n }\n </div>\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Message Actions -->\n <ax-context-menu\n [target]=\"'#message-bubble-' + message.id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleMessageContextMenuOpening($event, message)\"\n (onClose)=\"contextMenuMessageId.set(null)\"\n (onItemClick)=\"handleMessageContextMenuItemClick($event, message)\"\n >\n </ax-context-menu>\n </div>\n }\n }\n </div>\n\n <!-- Scroll to Bottom Button -->\n @if (showScrollButton()) {\n <div\n class=\"scroll-to-bottom-wrapper\"\n animate.enter=\"scroll-to-bottom-enter\"\n animate.leave=\"scroll-to-bottom-leave\"\n >\n <ax-fab\n class=\"scroll-to-bottom\"\n (onClick)=\"scrollToBottom()\"\n [attr.aria-label]=\"'@acorex:chat.actions.scroll-to-bottom' | translate | async\"\n >\n <ax-icon><i class=\"fa-light fa-arrow-down\" aria-hidden=\"true\"></i></ax-icon>\n </ax-fab>\n </div>\n }\n }\n </div>\n }\n\n <!-- Reaction Picker Popover -->\n @if (reactionsEnabled() && reactionPickerTarget()) {\n <ax-popover\n #reactionPopover\n [target]=\"reactionPickerElement()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"reactionPickerPlacement()\"\n (onClose)=\"closeReactionPicker()\"\n >\n <div class=\"reaction-picker-popup\">\n <div class=\"reaction-picker-header\">\n <span class=\"picker-title\">{{ '@acorex:chat.actions.react' | translate | async }}</span>\n <button\n type=\"button\"\n class=\"picker-close\"\n (click)=\"closeReactionPicker()\"\n [attr.aria-label]=\"'@acorex:chat.actions.close' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n <div\n class=\"reaction-picker-emojis\"\n role=\"listbox\"\n [attr.aria-label]=\"'@acorex:chat.actions.choose-reaction' | translate | async\"\n >\n @for (emoji of availableReactions(); track emoji) {\n <button\n type=\"button\"\n class=\"reaction-picker-emoji\"\n [class.reaction-picker-emoji-active]=\"hasUserReactedById(reactionPickerTarget()!, emoji)\"\n (click)=\"onReactionClickById(reactionPickerTarget()!, emoji); closeReactionPicker()\"\n [attr.aria-label]=\"emoji\"\n >\n {{ emoji }}\n </button>\n }\n </div>\n </div>\n </ax-popover>\n }\n} @else {\n <div\n class=\"message-list message-list--no-active\"\n role=\"region\"\n [attr.aria-label]=\"'@acorex:chat.status.no-conversation-selected' | translate | async\"\n >\n <div class=\"list-no-active\">\n <ng-content select=\"ax-conversation-message-list-no-active, [ax-conversation-message-list-no-active]\">\n <ng-container *ngComponentOutlet=\"noActiveFallbackComponent\"></ng-container>\n </ng-content>\n </div>\n </div>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-message-list{position:relative;display:block;height:100%;container-type:inline-size;@keyframes axConversationSurfaceIn{0%{opacity:0}to{opacity:1}}@keyframes axConversationSurfaceInReduced{0%{opacity:.92}to{opacity:1}}@keyframes messagesSkeletonIn{0%{opacity:0;transform:translateY(.75rem)}to{opacity:1;transform:translateY(0)}}@keyframes messagesSkeletonInReduced{0%{opacity:.85}to{opacity:1}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes axChatLoadMoreDot{0%,70%,to{transform:translateY(0) scale(1);opacity:.4}35%{transform:translateY(-.28rem) scale(1.08);opacity:1}}@keyframes axChatLoadMoreEnterPrepend{0%{opacity:0;transform:translateY(-.5rem)}to{opacity:1;transform:translateY(0)}}@keyframes axChatLoadMoreLeavePrepend{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-.35rem)}}@keyframes axScrollToBottomEnter{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes axScrollToBottomLeave{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}}ax-conversation-message-list .message-list{position:relative;display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 0);flex-direction:column;overflow:hidden}ax-conversation-message-list .message-list.ax-drop-zone>.ax-uploader-overlay-state{display:none!important}ax-conversation-message-list .message-list--drag{outline-style:var(--tw-outline-style);outline-width:2px;outline-color:rgba(var(--ax-sys-color-primary-surface));--tw-outline-style: dashed;outline-style:dashed;outline-offset:-2px}ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceIn .36s cubic-bezier(.22,1,.36,1) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceInReduced .18s ease both}}ax-conversation-message-list .list-loading{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;justify-content:flex-end;overflow:hidden}ax-conversation-message-list .messages-skeleton{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 6);animation:messagesSkeletonIn .42s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .message-skeleton{display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-message-list .message-skeleton--own{flex-direction:row-reverse}ax-conversation-message-list .message-skeleton-avatar{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);flex-shrink:0;border-radius:calc(infinity * 1px)}ax-conversation-message-list .message-skeleton-bubble{height:calc(var(--spacing, .25rem) * 10);border-radius:var(--radius-2xl, 1rem);width:min(62%,17.5rem)}ax-conversation-message-list .message-skeleton-bubble--short{height:calc(var(--spacing, .25rem) * 8);width:min(36%,9.5rem)}ax-conversation-message-list .message-skeleton-bubble--medium{height:calc(var(--spacing, .25rem) * 9);width:min(48%,13rem)}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .messages-skeleton{animation:messagesSkeletonInReduced .2s ease both}}ax-conversation-message-list .list-empty{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 5);padding-inline:calc(var(--spacing, .25rem) * 8);padding-block:calc(var(--spacing, .25rem) * 12);text-align:center;animation:fadeInUp .5s ease-out}ax-conversation-message-list .message-list--no-active{height:100%}ax-conversation-message-list .list-no-active{display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 48);flex-direction:column;align-items:center;justify-content:center}ax-conversation-message-list .empty-icon{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:5.5rem;--tw-leading: 1;line-height:1;opacity:35%;filter:grayscale(.2)}ax-conversation-message-list .empty-title{margin:calc(var(--spacing, .25rem) * 0);font-size:1.625rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-tight, -.025em);letter-spacing:var(--tracking-tight, -.025em);color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-message-list .empty-description{margin:calc(var(--spacing, .25rem) * 0);max-width:420px;font-size:1.0625rem;--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgba(var(--ax-sys-color-on-surface));opacity:.65}ax-conversation-message-list .spinner{margin-bottom:calc(var(--spacing, .25rem) * 4);height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:3px;border-color:rgba(var(--ax-sys-color-border-light-surface));border-top-color:rgb(var(--ax-sys-color-primary-500));animation:spin .8s linear infinite}ax-conversation-message-list .list-loading-more{display:flex;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);padding-bottom:calc(var(--spacing, .25rem) * 2);text-align:center;color:rgba(var(--ax-sys-color-on-surface));opacity:85%}ax-conversation-message-list .load-more-indicator{display:flex;min-height:calc(var(--spacing, .25rem) * 5);align-items:center;justify-content:center;gap:.3rem}ax-conversation-message-list .load-more-dot{height:.4rem;width:.4rem;border-radius:calc(infinity * 1px);background-color:rgba(var(--ax-sys-color-primary-500));animation:axChatLoadMoreDot 1s ease-in-out infinite}ax-conversation-message-list .load-more-dot:nth-child(2){animation-delay:.14s}ax-conversation-message-list .load-more-dot:nth-child(3){animation-delay:.28s}ax-conversation-message-list .load-more-label{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%}ax-conversation-message-list .load-more-enter{animation:axChatLoadMoreEnterPrepend .32s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .load-more-leave{animation:axChatLoadMoreLeavePrepend .22s ease both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .load-more-dot{animation:none;opacity:.65}ax-conversation-message-list .load-more-enter,ax-conversation-message-list .load-more-leave{animation:none}}ax-conversation-message-list .messages-container{position:relative;min-height:calc(var(--spacing, .25rem) * 0);width:100%;flex:1;overflow-x:hidden;overflow-y:auto}ax-conversation-message-list .date-separator{pointer-events:none;position:sticky;z-index:150;display:flex;align-items:center;justify-content:center;top:.5rem;padding:.375rem 1rem .625rem;margin-block:.125rem .375rem}ax-conversation-message-list .date-separator__label{pointer-events:auto;display:inline-flex;width:calc(var(--spacing, .25rem) * 32);max-width:min(100%,18rem);align-items:center;justify-content:center;border-radius:calc(infinity * 1px);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1);text-align:center;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-tight, 1.25);line-height:var(--leading-tight, 1.25);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);white-space:nowrap;-webkit-user-select:none;user-select:none;color:rgba(var(--ax-sys-color-on-lightest-surface));background:rgba(var(--ax-sys-color-lightest-surface));border:1px solid rgba(var(--ax-sys-color-on-lightest-surface),.25)}ax-conversation-message-list .unread-separator{margin-block:calc(var(--spacing, .25rem) * 6);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4)}ax-conversation-message-list .unread-separator-line{height:1px;flex:1;background-color:rgba(var(--ax-sys-color-primary-surface));opacity:30%}ax-conversation-message-list .unread-separator-text{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}ax-conversation-message-list .message-item{position:relative;display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 2);--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);transition:background-color .3s ease}ax-conversation-message-list .message-item-context-active{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.09);box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.22)}ax-conversation-message-list .message-own.message-item-context-active{background-color:rgba(var(--ax-sys-color-primary-500),.12)}ax-conversation-message-list .message-highlight{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-message-list .message-item.message-own{flex-direction:row-reverse}ax-conversation-message-list .message-avatar{flex-shrink:0}ax-conversation-message-list .message-avatar-icon{display:flex;height:100%;width:100%;align-items:center;justify-content:center;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: 1;line-height:1}ax-conversation-message-list .message-content-row{position:relative;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:0 1 auto;flex-direction:row;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 1);max-width:min(95%,50rem)}@container (min-width: 768px){ax-conversation-message-list .message-content-row{max-width:min(70%,50rem)}}ax-conversation-message-list .message-content-row-own{justify-content:flex-end}ax-conversation-message-list .message-item:not(.message-own) .message-content-row{justify-content:flex-start}ax-conversation-message-list .message-bubble-container{position:relative;display:flex;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0);flex:1 1 auto;flex-direction:column}ax-conversation-message-list .message-own .message-bubble-container{align-items:flex-end}ax-conversation-message-list .message-sender{margin-bottom:.1rem;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-bubble{position:relative;display:flex;max-width:100%;flex-direction:column;border-radius:var(--radius-2xl, 1rem);background-color:rgba(var(--ax-sys-color-lightest-surface));padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);padding-bottom:.1rem;overflow-wrap:break-word;transition:background-color .3s ease}ax-conversation-message-list .reply-preview{margin-bottom:calc(var(--spacing, .25rem) * 2);cursor:pointer;border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .reply-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .reply-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .reply-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .reply-preview-line{width:3px;flex-shrink:0;border-radius:1.5px;background:currentColor;opacity:.5}ax-conversation-message-list .reply-preview-content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-message-list .reply-preview-sender{margin-bottom:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .reply-preview-text{overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .reply-preview-sender{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .reply-preview-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .last-message{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .forwarded-preview{margin-bottom:.1rem;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .forwarded-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .forwarded-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .forwarded-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .forwarded-preview i{flex-shrink:0;font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .forwarded-text{min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .forwarded-preview i{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .forwarded-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .message-bubble-received{border-end-start-radius:.125rem}ax-conversation-message-list .message-bubble-received:before,ax-conversation-message-list .message-bubble-sent:after{content:\"\";display:block;position:absolute;bottom:0;width:.8rem;height:.8rem;pointer-events:none;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;mask-mode:alpha}ax-conversation-message-list .message-bubble-received:before{background-color:rgba(var(--ax-sys-color-lightest-surface));inset-inline-start:-.7rem;-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list .message-bubble-sent{border-end-end-radius:.125rem}ax-conversation-message-list .message-bubble-sent:after{background:rgb(var(--ax-sys-color-primary-surface));inset-inline-end:-.7rem;-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}[dir=rtl] ax-conversation-message-list .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list:dir(rtl) .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list:dir(rtl) .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}[dir=ltr] ax-conversation-message-list .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}[dir=ltr] ax-conversation-message-list .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list .message-own .message-bubble{background:rgb(var(--ax-sys-color-primary-surface));color:rgb(var(--ax-sys-color-on-primary-surface))}ax-conversation-message-list .message-bubble.message-system{background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);max-width:100%}ax-conversation-message-list .message-bubble.message-system:before,ax-conversation-message-list .message-bubble.message-system:after{display:none}ax-conversation-message-list .message-item:has(.message-system){justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .message-item:has(.message-system) .message-content-row{max-width:100%;justify-content:center}ax-conversation-message-list .message-item:has(.message-system) .message-bubble-container{align-items:center}ax-conversation-message-list .message-content{font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);white-space:pre-wrap}ax-conversation-message-list ax-conversation-registry-component-outlet{display:block;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0)}ax-conversation-message-list .message-footer{margin-top:.1rem;display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 1);padding-inline-start:calc(var(--spacing, .25rem) * 1);font-size:.6875rem;--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%;-webkit-user-select:none;user-select:none}ax-conversation-message-list .message-footer-count{display:inline-flex;align-items:center;gap:.2rem;font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .message-footer-count i{font-size:.625rem;opacity:90%}ax-conversation-message-list .message-footer-count-value{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-footer-split{margin-inline:.2rem;height:.65rem;width:1px;flex-shrink:0;align-self:center;background-color:rgba(var(--ax-sys-color-border-light-surface));opacity:90%}ax-conversation-message-list .message-time{font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .edited-indicator{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1);border-inline-start-style:var(--tw-border-style);border-inline-start-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline-start:.35rem;font-size:.675rem;opacity:75%}ax-conversation-message-list .status-icon{display:inline-flex;align-items:center}ax-conversation-message-list .status-icon i{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}ax-conversation-message-list .status-read{color:rgba(var(--ax-sys-color-primary-200))}ax-conversation-message-list .status-failed{color:rgba(var(--ax-sys-color-danger-200))}ax-conversation-message-list .message-reactions-bubbles{display:flex;flex-wrap:wrap;align-items:center;gap:.2rem}ax-conversation-message-list .reaction-bubble{margin:calc(var(--spacing, .25rem) * 0);display:inline-flex;min-height:1.375rem;cursor:pointer;align-items:center;justify-content:center;gap:.15rem;border-radius:var(--radius-xl, .75rem);padding-inline:.35rem;padding-block:.1rem;color:rgba(var(--ax-sys-color-on-surface));--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);background:rgba(var(--ax-sys-color-on-surface),.06);border:1px solid rgba(var(--ax-sys-color-on-surface),.1);transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}ax-conversation-message-list .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-surface),.1);border-color:rgba(var(--ax-sys-color-on-surface),.18)}ax-conversation-message-list .reaction-bubble-active{background:rgba(var(--ax-sys-color-primary-500),.12);border-color:rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-message-list .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-primary-500),.18);border-color:rgba(var(--ax-sys-color-primary-500),.55)}ax-conversation-message-list .reaction-emoji{display:inline-block;font-size:.8125rem;--tw-leading: 1;line-height:1}ax-conversation-message-list .reaction-count{font-size:.6875rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgba(var(--ax-sys-color-on-surface));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:.65}ax-conversation-message-list .reaction-bubble-active .reaction-count{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600));opacity:95%}ax-conversation-message-list .message-own .reaction-bubble{color:rgba(var(--ax-sys-color-on-primary-surface));background:rgba(var(--ax-sys-color-on-primary-surface),.12);border-color:rgba(var(--ax-sys-color-on-primary-surface),.2)}ax-conversation-message-list .message-own .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.2);border-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .reaction-bubble-active{background:rgba(var(--ax-sys-color-on-primary-surface),.28);border-color:rgba(var(--ax-sys-color-on-primary-surface),.5)}ax-conversation-message-list .message-own .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.34);border-color:rgba(var(--ax-sys-color-on-primary-surface),.6)}ax-conversation-message-list .message-own .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:80%}ax-conversation-message-list .message-own .reaction-bubble-active .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:100%}ax-conversation-message-list .message-reactions-container{margin-top:calc(var(--spacing, .25rem) * 1);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:.2rem}ax-conversation-message-list .message-own .message-reactions-container{justify-content:flex-end}ax-conversation-message-list .message-own .message-footer .edited-indicator{border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .message-footer .message-footer-split{background:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .add-reaction-button.add-reaction-outside{position:absolute;top:50%;margin:calc(var(--spacing, .25rem) * 0);box-sizing:border-box;display:none;height:1.8rem;width:1.8rem;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));padding:calc(var(--spacing, .25rem) * 0);inset-inline-end:-2.25rem;box-shadow:0 1px 2px #0000000f}ax-conversation-message-list .add-reaction-button{padding-inline-start:.05rem}ax-conversation-message-list .message-content-row-own .add-reaction-button.add-reaction-outside{inset-inline-start:-2.25rem;inset-inline-end:auto}ax-conversation-message-list .message-item:hover .add-reaction-button.add-reaction-outside,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{display:inline-flex}ax-conversation-message-list .add-reaction-button.add-reaction-outside:hover,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .add-reaction-button.add-reaction-outside i{font-size:.9rem;color:rgba(var(--ax-sys-color-on-surface));opacity:80%}ax-conversation-message-list .reaction-bubble:focus-visible,ax-conversation-message-list .add-reaction-button:focus-visible,ax-conversation-message-list .action-trigger:focus-visible,ax-conversation-message-list ax-fab.scroll-to-bottom ax-button:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .message-actions{z-index:10;padding-bottom:calc(var(--spacing, .25rem) * 6);opacity:0%;transition:opacity var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .message-item:hover .message-actions{opacity:100%}ax-conversation-message-list .action-trigger{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .action-trigger:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-message-list .shortcut{font-size:.6875rem;opacity:70%}ax-conversation-message-list .scroll-to-bottom-wrapper{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * 4);bottom:calc(var(--spacing, .25rem) * 4);z-index:999}ax-conversation-message-list ax-fab.scroll-to-bottom ax-button{display:flex;height:calc(var(--spacing, .25rem) * 12);width:calc(var(--spacing, .25rem) * 12);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none}ax-conversation-message-list .scroll-to-bottom-enter{animation:axScrollToBottomEnter var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}ax-conversation-message-list .scroll-to-bottom-leave{animation:axScrollToBottomLeave var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .scroll-to-bottom-enter,ax-conversation-message-list .scroll-to-bottom-leave{animation:none}}.reaction-picker-popup{width:max-content;min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;border-radius:.65rem;background-color:rgba(var(--ax-sys-color-lightest-surface));max-width:min(260px,92vw)}.reaction-picker-header{display:flex;min-height:calc(var(--spacing, .25rem) * 0);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:.45rem;padding-inline-start:.7rem;padding-inline-end:calc(var(--spacing, .25rem) * 2)}.picker-title{font-size:.8125rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-on-surface));opacity:85%}.picker-close{display:flex;height:1.6rem;width:1.6rem;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:.95rem;color:rgba(var(--ax-sys-color-on-surface),.55);transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}.picker-close:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}.picker-close:focus-visible,.reaction-picker-emoji:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}.reaction-picker-emojis{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.2rem;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:.45rem;padding-bottom:calc(var(--spacing, .25rem) * 2)}.reaction-picker-emoji{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);cursor:pointer;border-radius:.45rem;border-style:var(--tw-border-style);border-width:1px;border-color:transparent;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:1.15rem;--tw-leading: 1;line-height:1;transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.reaction-picker-emoji:hover{background-color:rgba(var(--ax-sys-color-lighter-surface))}.reaction-picker-emoji-active{background-color:rgba(var(--ax-sys-color-surface))}.reaction-picker-emoji-active:hover{background:rgba(var(--ax-sys-color-primary-500),.25)}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@keyframes spin{to{transform:rotate(360deg)}}@keyframes fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-outline-style: solid;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AXFabComponent, selector: "ax-fab", inputs: ["label", "popupStyle", "popupPlacement", "size"], outputs: ["popupPlacementChange", "onClick", "onOpened", "onClosed"] }, { kind: "component", type: AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "closeOnRouteChange", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "component", type: AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "component", type: AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: AXConversationInfiniteScrollDirective, selector: "[axInfiniteScroll]", inputs: ["threshold", "edge", "scrollDisabled", "cooldownMs"], outputs: ["scrollThreshold"] }, { kind: "directive", type: AXUploaderZoneDirective, selector: "[axUploaderZone]", inputs: ["multiple", "accept", "fileType", "overlayTemplate", "disableBrowse", "disableDragDrop"], outputs: ["fileChange", "onChanged", "dragEnter", "dragLeave", "dragOver", "onFileUploadComplete", "onFilesUploadComplete"] }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
8998
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationMessageListComponent, isStandalone: true, selector: "ax-conversation-message-list", outputs: { messageAction: "messageAction" }, viewQueries: [{ propertyName: "reactionPopover", first: true, predicate: ["reactionPopover"], descendants: true, isSignal: true }, { propertyName: "messageListRef", first: true, predicate: ["messageList"], descendants: true, isSignal: true }, { propertyName: "messagesContainerRef", first: true, predicate: ["messagesContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (activeConversation(); as conv) {\n @for (cid of [conv.id]; track cid) {\n <div\n class=\"message-list message-list--conversation-surface\"\n [class.message-list--drag]=\"messageListDragging()\"\n #messageList\n role=\"log\"\n [attr.aria-label]=\"'@acorex:chat.aria.message-list' | translate | async\"\n aria-live=\"polite\"\n [style.background]=\"messageListBackgroundStyle()\"\n [style.--ax-comp-message-list-surface-bg]=\"messageListBackgroundStyle()\"\n axUploaderZone\n [disableBrowse]=\"true\"\n (dragEnter)=\"onMessageListDragEnter()\"\n (dragLeave)=\"onMessageListDragLeave()\"\n (fileChange)=\"onMessageListFilesDropped($event)\"\n >\n @if (loading()) {\n <div\n class=\"list-loading\"\n role=\"status\"\n aria-busy=\"true\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-messages' | translate | async\"\n >\n <div class=\"messages-skeleton\" aria-hidden=\"true\">\n @for (item of loadingSkeletonItems; track item) {\n <div class=\"message-skeleton\" [class.message-skeleton--own]=\"$odd\">\n @if ($even && isGroupConversation()) {\n <ax-skeleton class=\"message-skeleton-avatar\" [animated]=\"true\"></ax-skeleton>\n }\n <ax-skeleton\n class=\"message-skeleton-bubble\"\n [class.message-skeleton-bubble--short]=\"$index % 3 === 1\"\n [class.message-skeleton-bubble--medium]=\"$index % 3 === 2\"\n [animated]=\"true\"\n ></ax-skeleton>\n </div>\n }\n </div>\n </div>\n } @else if (messages().length === 0) {\n <div class=\"list-empty\" role=\"status\" [attr.aria-label]=\"'@acorex:chat.status.no-messages' | translate | async\">\n <ng-content select=\"ax-conversation-message-list-empty, [ax-conversation-message-list-empty]\">\n <ng-container\n *ngComponentOutlet=\"resolvedEmptyStateComponent(); inputs: { conversation: activeConversation()! }\"\n ></ng-container>\n </ng-content>\n </div>\n } @else {\n <div\n class=\"messages-container\"\n (scroll)=\"onScroll($event)\"\n axInfiniteScroll\n [threshold]=\"config.infiniteScrollThreshold\"\n [edge]=\"'top'\"\n [scrollDisabled]=\"loading() || loadingMore() || !hasMoreMessages()\"\n (scrollThreshold)=\"onScrollThreshold($event)\"\n #messagesContainer\n role=\"feed\"\n [attr.aria-label]=\"'@acorex:chat.aria.messages' | translate | async\"\n >\n @if (loadingMore()) {\n <div\n class=\"list-loading-more list-loading-more--prepend\"\n role=\"status\"\n animate.enter=\"load-more-enter\"\n animate.leave=\"load-more-leave\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-older-messages' | translate | async\"\n >\n <div class=\"load-more-indicator\" aria-hidden=\"true\">\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n </div>\n <ax-label class=\"load-more-label\">{{\n '@acorex:chat.status.loading-older-messages' | translate | async\n }}</ax-label>\n </div>\n }\n @for (group of messageGroups(); track trackMessageGroup($index, group)) {\n <!-- Date Separator -->\n <div class=\"date-separator\" role=\"separator\" [attr.aria-label]=\"getDateSeparatorAriaLabel(group.dateLabel)\">\n <span class=\"date-separator__label\">{{ group.dateLabel }}</span>\n </div>\n\n <!-- Messages in this date group -->\n @for (message of group.messages; track trackMessage($index, message)) {\n <div\n [class]=\"getMessageClasses(message)\"\n role=\"article\"\n [attr.aria-label]=\"getMessageAriaLabel(message)\"\n [id]=\"'message-' + message.id\"\n >\n <!-- Avatar (only for group conversations and received messages) -->\n @if (shouldShowAvatar(message)) {\n <div class=\"message-avatar\">\n <ax-conversation-avatar\n kind=\"user\"\n [userId]=\"message.senderId\"\n [conversation]=\"activeConversation()\"\n [message]=\"message\"\n [size]=\"32\"\n />\n </div>\n }\n\n <div class=\"message-content-row\" [class.message-content-row-own]=\"isOwnMessage(message)\">\n @if (messageSupportsReactions(message)) {\n <button\n type=\"button\"\n class=\"add-reaction-button add-reaction-outside\"\n [class.add-reaction-visible]=\"reactionPickerTarget() === message.id\"\n (click)=\"toggleReactionPicker(message, $event)\"\n [attr.aria-label]=\"'@acorex:chat.actions.add-reaction' | translate | async\"\n #reactionButton\n >\n <i class=\"fa-light fa-face-smile\"></i>\n </button>\n }\n\n <div\n class=\"message-bubble-container\"\n [id]=\"'message-bubble-' + message.id\"\n [attr.data-message-id]=\"message.id\"\n >\n <div\n [class]=\"getBubbleClasses(message)\"\n [class.message-bubble-sent]=\"message.senderId === currentUser()?.id\"\n [class.message-bubble-received]=\"message.senderId !== currentUser()?.id\"\n >\n <!-- Sender name (only for group conversations and received messages) -->\n @if (shouldShowSenderName(message)) {\n <div class=\"message-sender\">{{ getSenderName(message) }}:</div>\n }\n\n <!-- Reply Preview -->\n @if (message.replyTo) {\n <div\n class=\"reply-preview\"\n (click)=\"scrollToMessage(message.replyTo.id)\"\n role=\"button\"\n [attr.aria-label]=\"'Reply to ' + getSenderName(message.replyTo)\"\n (keydown.enter)=\"scrollToMessage(message.replyTo.id)\"\n (keydown.space)=\"scrollToMessage(message.replyTo.id)\"\n >\n <div class=\"reply-preview-content\">\n <div class=\"reply-preview-sender\">{{ getSenderName(message.replyTo) }}</div>\n <div class=\"reply-preview-text\">\n @if (getMessagePreviewText(message.replyTo); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i\n >{{ '@acorex:chat.' + preview.type | translate | async }}\n } @else {\n {{ preview.value }}\n }\n </span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Forwarded Indicator -->\n @if (message.forwarded) {\n <div class=\"forwarded-preview\">\n <i class=\"fa-solid fa-share\"></i>\n <span class=\"forwarded-text\">{{ getForwardedText(message) }}</span>\n </div>\n }\n\n <ax-conversation-registry-component-outlet\n [component]=\"getRendererComponent(message)\"\n [componentLoader]=\"getRendererComponentLoader(message)\"\n [inputs]=\"getRendererInputs(message)\"\n />\n\n @if (messageSupportsReactions(message) && message.reactions.length > 0) {\n <div class=\"message-reactions-container\">\n <div class=\"message-reactions-bubbles\">\n @for (reaction of getGroupedReactions(message); track reaction.emoji) {\n <button\n type=\"button\"\n class=\"reaction-bubble\"\n [class.reaction-bubble-active]=\"reaction.hasReacted\"\n (click)=\"onReactionClick(message, reaction.emoji)\"\n [attr.aria-label]=\"reaction.emoji + ' ' + reaction.count\"\n >\n <span class=\"reaction-emoji\">{{ reaction.emoji }}</span>\n @if (reaction.count > 1) {\n <span class=\"reaction-count\">{{ reaction.count }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Message Footer -->\n <div class=\"message-footer\">\n @let replyCount = getReplyCount(message);\n @let forwardCount = getForwardCount(message);\n @if (replyCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"replyCount + ' replies'\">\n <i class=\"fa-solid fa-message\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ replyCount }}</span>\n </span>\n }\n @if (forwardCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"forwardCount + ' forwards'\">\n <i class=\"fa-solid fa-share\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ forwardCount }}</span>\n </span>\n }\n @if (replyCount > 0 || forwardCount > 0) {\n <span class=\"message-footer-split\" aria-hidden=\"true\"></span>\n }\n <span class=\"message-time\">{{ message.timestamp | format: 'timeleft' | async }}</span>\n @if (message.editedAt) {\n <span class=\"edited-indicator\">\n <span>{{ '@acorex:chat.status.edited' | translate | async }}</span>\n </span>\n }\n @if (isOwnMessage(message)) {\n <span [class]=\"getStatusIconClasses(message)\">\n <ax-icon><i [class]=\"getStatusIcon(message)\"></i></ax-icon>\n </span>\n }\n </div>\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Message Actions -->\n <ax-context-menu\n [target]=\"'#message-bubble-' + message.id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleMessageContextMenuOpening($event, message)\"\n (onClose)=\"contextMenuMessageId.set(null)\"\n (onItemClick)=\"handleMessageContextMenuItemClick($event, message)\"\n >\n </ax-context-menu>\n </div>\n }\n }\n </div>\n\n <!-- Scroll to Bottom Button -->\n @if (showScrollButton()) {\n <div\n class=\"scroll-to-bottom-wrapper\"\n animate.enter=\"scroll-to-bottom-enter\"\n animate.leave=\"scroll-to-bottom-leave\"\n >\n <ax-fab\n class=\"scroll-to-bottom\"\n (onClick)=\"scrollToBottom()\"\n [attr.aria-label]=\"'@acorex:chat.actions.scroll-to-bottom' | translate | async\"\n >\n <ax-icon><i class=\"fa-light fa-arrow-down\" aria-hidden=\"true\"></i></ax-icon>\n </ax-fab>\n </div>\n }\n }\n </div>\n }\n\n <!-- Reaction Picker Popover -->\n @if (reactionsEnabled() && reactionPickerTarget()) {\n <ax-popover\n #reactionPopover\n [target]=\"reactionPickerElement()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"reactionPickerPlacement()\"\n (onClose)=\"closeReactionPicker()\"\n >\n <div class=\"reaction-picker-popup\">\n <div class=\"reaction-picker-header\">\n <span class=\"picker-title\">{{ '@acorex:chat.actions.react' | translate | async }}</span>\n <button\n type=\"button\"\n class=\"picker-close\"\n (click)=\"closeReactionPicker()\"\n [attr.aria-label]=\"'@acorex:chat.actions.close' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n <div\n class=\"reaction-picker-emojis\"\n role=\"listbox\"\n [attr.aria-label]=\"'@acorex:chat.actions.choose-reaction' | translate | async\"\n >\n @for (emoji of availableReactions(); track emoji) {\n <button\n type=\"button\"\n class=\"reaction-picker-emoji\"\n [class.reaction-picker-emoji-active]=\"hasUserReactedById(reactionPickerTarget()!, emoji)\"\n (click)=\"onReactionClickById(reactionPickerTarget()!, emoji); closeReactionPicker()\"\n [attr.aria-label]=\"emoji\"\n >\n {{ emoji }}\n </button>\n }\n </div>\n </div>\n </ax-popover>\n }\n} @else {\n <div\n class=\"message-list message-list--no-active\"\n role=\"region\"\n [attr.aria-label]=\"'@acorex:chat.status.no-conversation-selected' | translate | async\"\n >\n <div class=\"list-no-active\">\n <ng-content select=\"ax-conversation-message-list-no-active, [ax-conversation-message-list-no-active]\">\n <ng-container *ngComponentOutlet=\"noActiveFallbackComponent\"></ng-container>\n </ng-content>\n </div>\n </div>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-message-list{position:relative;display:block;height:100%;container-type:inline-size;--ax-comp-message-bubble-tail-height: 1.5625rem;--ax-comp-message-bubble-tail-fill-width: 1.25rem;--ax-comp-message-bubble-tail-fill-offset: -.4375rem;--ax-comp-message-bubble-tail-cutout-width: 1.625rem;--ax-comp-message-bubble-tail-cutout-offset: -1.625rem;--ax-comp-message-bubble-tail-curve: 1rem 0rem;--ax-comp-message-bubble-tail-cutout-curve: .625rem;@keyframes axConversationSurfaceIn{0%{opacity:0}to{opacity:1}}@keyframes axConversationSurfaceInReduced{0%{opacity:.92}to{opacity:1}}@keyframes messagesSkeletonIn{0%{opacity:0;transform:translateY(.75rem)}to{opacity:1;transform:translateY(0)}}@keyframes messagesSkeletonInReduced{0%{opacity:.85}to{opacity:1}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes axChatLoadMoreDot{0%,70%,to{transform:translateY(0) scale(1);opacity:.4}35%{transform:translateY(-.28rem) scale(1.08);opacity:1}}@keyframes axChatLoadMoreEnterPrepend{0%{opacity:0;transform:translateY(-.5rem)}to{opacity:1;transform:translateY(0)}}@keyframes axChatLoadMoreLeavePrepend{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-.35rem)}}@keyframes axScrollToBottomEnter{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes axScrollToBottomLeave{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}}ax-conversation-message-list .message-list{position:relative;display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 0);flex-direction:column;overflow:hidden}ax-conversation-message-list .message-list.ax-drop-zone>.ax-uploader-overlay-state{display:none!important}ax-conversation-message-list .message-list--drag{outline-style:var(--tw-outline-style);outline-width:2px;outline-color:rgba(var(--ax-sys-color-primary-surface));--tw-outline-style: dashed;outline-style:dashed;outline-offset:-2px}ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceIn .36s cubic-bezier(.22,1,.36,1) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceInReduced .18s ease both}}ax-conversation-message-list .list-loading{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;justify-content:flex-end;overflow:hidden}ax-conversation-message-list .messages-skeleton{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 6);animation:messagesSkeletonIn .42s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .message-skeleton{display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-message-list .message-skeleton--own{flex-direction:row-reverse}ax-conversation-message-list .message-skeleton-avatar{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);flex-shrink:0;border-radius:calc(infinity * 1px)}ax-conversation-message-list .message-skeleton-bubble{height:calc(var(--spacing, .25rem) * 10);border-radius:var(--radius-2xl, 1rem);width:min(62%,17.5rem)}ax-conversation-message-list .message-skeleton-bubble--short{height:calc(var(--spacing, .25rem) * 8);width:min(36%,9.5rem)}ax-conversation-message-list .message-skeleton-bubble--medium{height:calc(var(--spacing, .25rem) * 9);width:min(48%,13rem)}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .messages-skeleton{animation:messagesSkeletonInReduced .2s ease both}}ax-conversation-message-list .list-empty{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 5);padding-inline:calc(var(--spacing, .25rem) * 8);padding-block:calc(var(--spacing, .25rem) * 12);text-align:center;animation:fadeInUp .5s ease-out}ax-conversation-message-list .message-list--no-active{height:100%}ax-conversation-message-list .list-no-active{display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 48);flex-direction:column;align-items:center;justify-content:center}ax-conversation-message-list .empty-icon{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:5.5rem;--tw-leading: 1;line-height:1;opacity:35%;filter:grayscale(.2)}ax-conversation-message-list .empty-title{margin:calc(var(--spacing, .25rem) * 0);font-size:1.625rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-tight, -.025em);letter-spacing:var(--tracking-tight, -.025em);color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-message-list .empty-description{margin:calc(var(--spacing, .25rem) * 0);max-width:420px;font-size:1.0625rem;--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgba(var(--ax-sys-color-on-surface));opacity:.65}ax-conversation-message-list .spinner{margin-bottom:calc(var(--spacing, .25rem) * 4);height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:3px;border-color:rgba(var(--ax-sys-color-border-light-surface));border-top-color:rgb(var(--ax-sys-color-primary-500));animation:spin .8s linear infinite}ax-conversation-message-list .list-loading-more{display:flex;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);padding-bottom:calc(var(--spacing, .25rem) * 2);text-align:center;color:rgba(var(--ax-sys-color-on-surface));opacity:85%}ax-conversation-message-list .load-more-indicator{display:flex;min-height:calc(var(--spacing, .25rem) * 5);align-items:center;justify-content:center;gap:.3rem}ax-conversation-message-list .load-more-dot{height:.4rem;width:.4rem;border-radius:calc(infinity * 1px);background-color:rgba(var(--ax-sys-color-primary-500));animation:axChatLoadMoreDot 1s ease-in-out infinite}ax-conversation-message-list .load-more-dot:nth-child(2){animation-delay:.14s}ax-conversation-message-list .load-more-dot:nth-child(3){animation-delay:.28s}ax-conversation-message-list .load-more-label{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%}ax-conversation-message-list .load-more-enter{animation:axChatLoadMoreEnterPrepend .32s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .load-more-leave{animation:axChatLoadMoreLeavePrepend .22s ease both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .load-more-dot{animation:none;opacity:.65}ax-conversation-message-list .load-more-enter,ax-conversation-message-list .load-more-leave{animation:none}}ax-conversation-message-list .messages-container{position:relative;min-height:calc(var(--spacing, .25rem) * 0);width:100%;flex:1;overflow-y:auto;overflow-x:visible}ax-conversation-message-list .date-separator{pointer-events:none;position:sticky;z-index:150;display:flex;align-items:center;justify-content:center;top:.5rem;padding:.375rem 1rem .625rem;margin-block:.125rem .375rem}ax-conversation-message-list .date-separator__label{pointer-events:auto;display:inline-flex;width:calc(var(--spacing, .25rem) * 32);max-width:min(100%,18rem);align-items:center;justify-content:center;border-radius:calc(infinity * 1px);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1);text-align:center;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-tight, 1.25);line-height:var(--leading-tight, 1.25);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);white-space:nowrap;-webkit-user-select:none;user-select:none;color:rgba(var(--ax-sys-color-on-lightest-surface));background:rgba(var(--ax-sys-color-lightest-surface));border:1px solid rgba(var(--ax-sys-color-on-lightest-surface),.25)}ax-conversation-message-list .unread-separator{margin-block:calc(var(--spacing, .25rem) * 6);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4)}ax-conversation-message-list .unread-separator-line{height:1px;flex:1;background-color:rgba(var(--ax-sys-color-primary-surface));opacity:30%}ax-conversation-message-list .unread-separator-text{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}ax-conversation-message-list .message-item{position:relative;display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);padding-inline:1.75rem;transition:background-color .3s ease}ax-conversation-message-list .message-item-context-active{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.09);box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.22)}ax-conversation-message-list .message-own.message-item-context-active{background-color:rgba(var(--ax-sys-color-primary-500),.12)}ax-conversation-message-list .message-highlight{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-message-list .message-item.message-own{flex-direction:row-reverse}ax-conversation-message-list .message-avatar{z-index:5;flex-shrink:0}ax-conversation-message-list .message-avatar-icon{display:flex;height:100%;width:100%;align-items:center;justify-content:center;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: 1;line-height:1}ax-conversation-message-list .message-content-row{position:relative;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:0 1 auto;flex-direction:row;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 1);max-width:min(95%,50rem)}@container (min-width: 768px){ax-conversation-message-list .message-content-row{max-width:min(70%,50rem)}}ax-conversation-message-list .message-content-row-own{justify-content:flex-end}ax-conversation-message-list .message-item:not(.message-own) .message-content-row{justify-content:flex-start}ax-conversation-message-list .message-bubble-container{position:relative;display:flex;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0);flex:1 1 auto;flex-direction:column}ax-conversation-message-list .message-own .message-bubble-container{align-items:flex-end}ax-conversation-message-list .message-sender{margin-bottom:.1rem;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-bubble{position:relative;display:flex;max-width:100%;flex-direction:column;border-radius:var(--radius-2xl, 1rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);padding-bottom:.1rem;overflow-wrap:break-word;transition:background-color .3s ease}ax-conversation-message-list .message-bubble>*{position:relative;z-index:1}ax-conversation-message-list .reply-preview{margin-bottom:calc(var(--spacing, .25rem) * 2);cursor:pointer;border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .reply-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .reply-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .reply-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .reply-preview-line{width:3px;flex-shrink:0;border-radius:1.5px;background:currentColor;opacity:.5}ax-conversation-message-list .reply-preview-content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-message-list .reply-preview-sender{margin-bottom:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .reply-preview-text{overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .reply-preview-sender{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .reply-preview-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .last-message{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .forwarded-preview{margin-bottom:.1rem;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .forwarded-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .forwarded-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .forwarded-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .forwarded-preview i{flex-shrink:0;font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .forwarded-text{min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .forwarded-preview i{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .forwarded-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .message-bubble-received:not(.message-system){--ax-comp-message-bubble-bg: rgb(var(--ax-sys-color-lightest-surface));background-color:var(--ax-comp-message-bubble-bg);border-bottom-left-radius:.25rem}ax-conversation-message-list .message-bubble-sent:not(.message-system){--ax-comp-message-bubble-bg: rgb(var(--ax-sys-color-primary-surface));background-color:var(--ax-comp-message-bubble-bg);color:rgb(var(--ax-sys-color-on-primary-surface));border-bottom-right-radius:.25rem}ax-conversation-message-list .message-bubble-received:not(.message-system):before,ax-conversation-message-list .message-bubble-received:not(.message-system):after,ax-conversation-message-list .message-bubble-sent:not(.message-system):before,ax-conversation-message-list .message-bubble-sent:not(.message-system):after{content:\"\";position:absolute;bottom:0;height:var(--ax-comp-message-bubble-tail-height);pointer-events:none;z-index:0}ax-conversation-message-list .message-bubble-received:not(.message-system):before,ax-conversation-message-list .message-bubble-sent:not(.message-system):before{width:var(--ax-comp-message-bubble-tail-fill-width);background-color:var(--ax-comp-message-bubble-bg)}ax-conversation-message-list .message-bubble-received:not(.message-system):after,ax-conversation-message-list .message-bubble-sent:not(.message-system):after{width:var(--ax-comp-message-bubble-tail-cutout-width);background:var(--ax-comp-message-list-surface-bg, rgb(var(--ax-sys-color-primary-lightest-surface)))}ax-conversation-message-list .message-bubble-received:not(.message-system):before{left:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-right-radius:var(--ax-comp-message-bubble-tail-curve)}ax-conversation-message-list .message-bubble-received:not(.message-system):after{left:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-right-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}ax-conversation-message-list .message-bubble-sent:not(.message-system):before{right:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-left-radius:var(--ax-comp-message-bubble-tail-curve)}ax-conversation-message-list .message-bubble-sent:not(.message-system):after{right:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-left-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system){border-bottom-left-radius:1rem;border-bottom-right-radius:.25rem}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system){border-bottom-right-radius:1rem;border-bottom-left-radius:.25rem}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system):before{left:auto;right:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-right-radius:0;border-bottom-left-radius:var(--ax-comp-message-bubble-tail-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system):after{left:auto;right:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-right-radius:0;border-bottom-left-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system):before{right:auto;left:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-left-radius:0;border-bottom-right-radius:var(--ax-comp-message-bubble-tail-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system):after{right:auto;left:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-left-radius:0;border-bottom-right-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}ax-conversation-message-list .message-bubble.message-system:before,ax-conversation-message-list .message-bubble.message-system:after{display:none}ax-conversation-message-list .message-own .message-bubble{color:rgb(var(--ax-sys-color-on-primary-surface))}ax-conversation-message-list .message-bubble.message-system{background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);max-width:100%}ax-conversation-message-list .message-item:has(.message-system){justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .message-item:has(.message-system) .message-content-row{max-width:100%;justify-content:center}ax-conversation-message-list .message-item:has(.message-system) .message-bubble-container{align-items:center}ax-conversation-message-list .message-content{font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);white-space:pre-wrap}ax-conversation-message-list ax-conversation-registry-component-outlet{display:block;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0)}ax-conversation-message-list .message-footer{margin-top:.1rem;display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 1);padding-inline-start:calc(var(--spacing, .25rem) * 1);font-size:.6875rem;--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%;-webkit-user-select:none;user-select:none}ax-conversation-message-list .message-footer-count{display:inline-flex;align-items:center;gap:.2rem;font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .message-footer-count i{font-size:.625rem;opacity:90%}ax-conversation-message-list .message-footer-count-value{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-footer-split{margin-inline:.2rem;height:.65rem;width:1px;flex-shrink:0;align-self:center;background-color:rgba(var(--ax-sys-color-border-light-surface));opacity:90%}ax-conversation-message-list .message-time{font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .edited-indicator{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1);border-inline-start-style:var(--tw-border-style);border-inline-start-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline-start:.35rem;font-size:.675rem;opacity:75%}ax-conversation-message-list .status-icon{display:inline-flex;align-items:center}ax-conversation-message-list .status-icon i{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}ax-conversation-message-list .status-read{color:rgba(var(--ax-sys-color-primary-200))}ax-conversation-message-list .status-failed{color:rgba(var(--ax-sys-color-danger-200))}ax-conversation-message-list .message-reactions-bubbles{display:flex;flex-wrap:wrap;align-items:center;gap:.2rem}ax-conversation-message-list .reaction-bubble{margin:calc(var(--spacing, .25rem) * 0);display:inline-flex;min-height:1.375rem;cursor:pointer;align-items:center;justify-content:center;gap:.15rem;border-radius:var(--radius-xl, .75rem);padding-inline:.35rem;padding-block:.1rem;color:rgba(var(--ax-sys-color-on-surface));--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);background:rgba(var(--ax-sys-color-on-surface),.06);border:1px solid rgba(var(--ax-sys-color-on-surface),.1);transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}ax-conversation-message-list .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-surface),.1);border-color:rgba(var(--ax-sys-color-on-surface),.18)}ax-conversation-message-list .reaction-bubble-active{background:rgba(var(--ax-sys-color-primary-500),.12);border-color:rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-message-list .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-primary-500),.18);border-color:rgba(var(--ax-sys-color-primary-500),.55)}ax-conversation-message-list .reaction-emoji{display:inline-block;font-size:.8125rem;--tw-leading: 1;line-height:1}ax-conversation-message-list .reaction-count{font-size:.6875rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgba(var(--ax-sys-color-on-surface));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:.65}ax-conversation-message-list .reaction-bubble-active .reaction-count{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600));opacity:95%}ax-conversation-message-list .message-own .reaction-bubble{color:rgba(var(--ax-sys-color-on-primary-surface));background:rgba(var(--ax-sys-color-on-primary-surface),.12);border-color:rgba(var(--ax-sys-color-on-primary-surface),.2)}ax-conversation-message-list .message-own .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.2);border-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .reaction-bubble-active{background:rgba(var(--ax-sys-color-on-primary-surface),.28);border-color:rgba(var(--ax-sys-color-on-primary-surface),.5)}ax-conversation-message-list .message-own .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.34);border-color:rgba(var(--ax-sys-color-on-primary-surface),.6)}ax-conversation-message-list .message-own .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:80%}ax-conversation-message-list .message-own .reaction-bubble-active .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:100%}ax-conversation-message-list .message-reactions-container{margin-top:calc(var(--spacing, .25rem) * 1);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:.2rem}ax-conversation-message-list .message-own .message-reactions-container{justify-content:flex-end}ax-conversation-message-list .message-own .message-footer .edited-indicator{border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .message-footer .message-footer-split{background:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .add-reaction-button.add-reaction-outside{position:absolute;top:50%;margin:calc(var(--spacing, .25rem) * 0);box-sizing:border-box;display:none;height:1.8rem;width:1.8rem;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));padding:calc(var(--spacing, .25rem) * 0);inset-inline-end:-2.25rem;box-shadow:0 1px 2px #0000000f}ax-conversation-message-list .add-reaction-button{padding-inline-start:.05rem}ax-conversation-message-list .message-content-row-own .add-reaction-button.add-reaction-outside{inset-inline-start:-2.25rem;inset-inline-end:auto}ax-conversation-message-list .message-item:hover .add-reaction-button.add-reaction-outside,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{display:inline-flex}ax-conversation-message-list .add-reaction-button.add-reaction-outside:hover,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .add-reaction-button.add-reaction-outside i{font-size:.9rem;color:rgba(var(--ax-sys-color-on-surface));opacity:80%}ax-conversation-message-list .reaction-bubble:focus-visible,ax-conversation-message-list .add-reaction-button:focus-visible,ax-conversation-message-list .action-trigger:focus-visible,ax-conversation-message-list ax-fab.scroll-to-bottom ax-button:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .message-actions{z-index:10;padding-bottom:calc(var(--spacing, .25rem) * 6);opacity:0%;transition:opacity var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .message-item:hover .message-actions{opacity:100%}ax-conversation-message-list .action-trigger{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .action-trigger:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-message-list .shortcut{font-size:.6875rem;opacity:70%}ax-conversation-message-list .scroll-to-bottom-wrapper{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * 4);bottom:calc(var(--spacing, .25rem) * 4);z-index:999}ax-conversation-message-list ax-fab.scroll-to-bottom ax-button{display:flex;height:calc(var(--spacing, .25rem) * 12);width:calc(var(--spacing, .25rem) * 12);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none}ax-conversation-message-list .scroll-to-bottom-enter{animation:axScrollToBottomEnter var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}ax-conversation-message-list .scroll-to-bottom-leave{animation:axScrollToBottomLeave var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .scroll-to-bottom-enter,ax-conversation-message-list .scroll-to-bottom-leave{animation:none}}.reaction-picker-popup{width:max-content;min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;border-radius:.65rem;background-color:rgba(var(--ax-sys-color-lightest-surface));max-width:min(260px,92vw)}.reaction-picker-header{display:flex;min-height:calc(var(--spacing, .25rem) * 0);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:.45rem;padding-inline-start:.7rem;padding-inline-end:calc(var(--spacing, .25rem) * 2)}.picker-title{font-size:.8125rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-on-surface));opacity:85%}.picker-close{display:flex;height:1.6rem;width:1.6rem;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:.95rem;color:rgba(var(--ax-sys-color-on-surface),.55);transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}.picker-close:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}.picker-close:focus-visible,.reaction-picker-emoji:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}.reaction-picker-emojis{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.2rem;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:.45rem;padding-bottom:calc(var(--spacing, .25rem) * 2)}.reaction-picker-emoji{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);cursor:pointer;border-radius:.45rem;border-style:var(--tw-border-style);border-width:1px;border-color:transparent;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:1.15rem;--tw-leading: 1;line-height:1;transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.reaction-picker-emoji:hover{background-color:rgba(var(--ax-sys-color-lighter-surface))}.reaction-picker-emoji-active{background-color:rgba(var(--ax-sys-color-surface))}.reaction-picker-emoji-active:hover{background:rgba(var(--ax-sys-color-primary-500),.25)}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@keyframes spin{to{transform:rotate(360deg)}}@keyframes fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-outline-style: solid;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AXFabComponent, selector: "ax-fab", inputs: ["label", "popupStyle", "popupPlacement", "size"], outputs: ["popupPlacementChange", "onClick", "onOpened", "onClosed"] }, { kind: "component", type: AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "closeOnRouteChange", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "component", type: AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "component", type: AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: AXConversationInfiniteScrollDirective, selector: "[axInfiniteScroll]", inputs: ["threshold", "edge", "scrollDisabled", "cooldownMs"], outputs: ["scrollThreshold"] }, { kind: "directive", type: AXUploaderZoneDirective, selector: "[axUploaderZone]", inputs: ["multiple", "accept", "fileType", "overlayTemplate", "disableBrowse", "disableDragDrop"], outputs: ["fileChange", "onChanged", "dragEnter", "dragLeave", "dragOver", "onFileUploadComplete", "onFilesUploadComplete"] }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "component", type: AXConversationRegistryComponentOutletComponent, selector: "ax-conversation-registry-component-outlet", inputs: ["component", "componentLoader", "inputs"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
8776
8999
  }
8777
9000
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationMessageListComponent, decorators: [{
8778
9001
  type: Component,
@@ -8791,7 +9014,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
8791
9014
  AXUploaderZoneDirective,
8792
9015
  AXConversationAvatarComponent,
8793
9016
  AXConversationRegistryComponentOutletComponent,
8794
- ], template: "@if (activeConversation(); as conv) {\n @for (cid of [conv.id]; track cid) {\n <div\n class=\"message-list message-list--conversation-surface\"\n [class.message-list--drag]=\"messageListDragging()\"\n #messageList\n role=\"log\"\n [attr.aria-label]=\"'@acorex:chat.aria.message-list' | translate | async\"\n aria-live=\"polite\"\n [style.background]=\"messageListBackgroundStyle()\"\n axUploaderZone\n [disableBrowse]=\"true\"\n (dragEnter)=\"onMessageListDragEnter()\"\n (dragLeave)=\"onMessageListDragLeave()\"\n (fileChange)=\"onMessageListFilesDropped($event)\"\n >\n @if (loading()) {\n <div\n class=\"list-loading\"\n role=\"status\"\n aria-busy=\"true\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-messages' | translate | async\"\n >\n <div class=\"messages-skeleton\" aria-hidden=\"true\">\n @for (item of loadingSkeletonItems; track item) {\n <div class=\"message-skeleton\" [class.message-skeleton--own]=\"$odd\">\n @if ($even && isGroupConversation()) {\n <ax-skeleton class=\"message-skeleton-avatar\" [animated]=\"true\"></ax-skeleton>\n }\n <ax-skeleton\n class=\"message-skeleton-bubble\"\n [class.message-skeleton-bubble--short]=\"$index % 3 === 1\"\n [class.message-skeleton-bubble--medium]=\"$index % 3 === 2\"\n [animated]=\"true\"\n ></ax-skeleton>\n </div>\n }\n </div>\n </div>\n } @else if (messages().length === 0) {\n <div class=\"list-empty\" role=\"status\" [attr.aria-label]=\"'@acorex:chat.status.no-messages' | translate | async\">\n <ng-content select=\"ax-conversation-message-list-empty, [ax-conversation-message-list-empty]\">\n <ng-container\n *ngComponentOutlet=\"resolvedEmptyStateComponent(); inputs: { conversation: activeConversation()! }\"\n ></ng-container>\n </ng-content>\n </div>\n } @else {\n <div\n class=\"messages-container\"\n (scroll)=\"onScroll($event)\"\n axInfiniteScroll\n [threshold]=\"config.infiniteScrollThreshold\"\n [edge]=\"'top'\"\n [scrollDisabled]=\"loading() || loadingMore() || !hasMoreMessages()\"\n (scrollThreshold)=\"onScrollThreshold($event)\"\n #messagesContainer\n role=\"feed\"\n [attr.aria-label]=\"'@acorex:chat.aria.messages' | translate | async\"\n >\n @if (loadingMore()) {\n <div\n class=\"list-loading-more list-loading-more--prepend\"\n role=\"status\"\n animate.enter=\"load-more-enter\"\n animate.leave=\"load-more-leave\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-older-messages' | translate | async\"\n >\n <div class=\"load-more-indicator\" aria-hidden=\"true\">\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n </div>\n <ax-label class=\"load-more-label\">{{\n '@acorex:chat.status.loading-older-messages' | translate | async\n }}</ax-label>\n </div>\n }\n @for (group of messageGroups(); track trackMessageGroup($index, group)) {\n <!-- Date Separator -->\n <div class=\"date-separator\" role=\"separator\" [attr.aria-label]=\"getDateSeparatorAriaLabel(group.dateLabel)\">\n <span class=\"date-separator__label\">{{ group.dateLabel }}</span>\n </div>\n\n <!-- Messages in this date group -->\n @for (message of group.messages; track trackMessage($index, message)) {\n <div\n [class]=\"getMessageClasses(message)\"\n role=\"article\"\n [attr.aria-label]=\"getMessageAriaLabel(message)\"\n [id]=\"'message-' + message.id\"\n >\n <!-- Avatar (only for group conversations and received messages) -->\n @if (shouldShowAvatar(message)) {\n <div class=\"message-avatar\">\n <ax-conversation-avatar\n kind=\"user\"\n [userId]=\"message.senderId\"\n [conversation]=\"activeConversation()\"\n [message]=\"message\"\n [size]=\"32\"\n />\n </div>\n }\n\n <div class=\"message-content-row\" [class.message-content-row-own]=\"isOwnMessage(message)\">\n @if (messageSupportsReactions(message)) {\n <button\n type=\"button\"\n class=\"add-reaction-button add-reaction-outside\"\n [class.add-reaction-visible]=\"reactionPickerTarget() === message.id\"\n (click)=\"toggleReactionPicker(message, $event)\"\n [attr.aria-label]=\"'@acorex:chat.actions.add-reaction' | translate | async\"\n #reactionButton\n >\n <i class=\"fa-light fa-face-smile\"></i>\n </button>\n }\n\n <div\n class=\"message-bubble-container\"\n [id]=\"'message-bubble-' + message.id\"\n [attr.data-message-id]=\"message.id\"\n >\n <div\n [class]=\"getBubbleClasses(message)\"\n [class.message-bubble-sent]=\"message.senderId === currentUser()?.id\"\n [class.message-bubble-received]=\"message.senderId !== currentUser()?.id\"\n >\n <!-- Sender name (only for group conversations and received messages) -->\n @if (shouldShowSenderName(message)) {\n <div class=\"message-sender\">{{ getSenderName(message) }}:</div>\n }\n\n <!-- Reply Preview -->\n @if (message.replyTo) {\n <div\n class=\"reply-preview\"\n (click)=\"scrollToMessage(message.replyTo.id)\"\n role=\"button\"\n [attr.aria-label]=\"'Reply to ' + getSenderName(message.replyTo)\"\n (keydown.enter)=\"scrollToMessage(message.replyTo.id)\"\n (keydown.space)=\"scrollToMessage(message.replyTo.id)\"\n >\n <div class=\"reply-preview-content\">\n <div class=\"reply-preview-sender\">{{ getSenderName(message.replyTo) }}</div>\n <div class=\"reply-preview-text\">\n @if (getMessagePreviewText(message.replyTo); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i\n >{{ '@acorex:chat.' + preview.type | translate | async }}\n } @else {\n {{ preview.value }}\n }\n </span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Forwarded Indicator -->\n @if (message.forwarded) {\n <div class=\"forwarded-preview\">\n <i class=\"fa-solid fa-share\"></i>\n <span class=\"forwarded-text\">{{ getForwardedText(message) }}</span>\n </div>\n }\n\n <ax-conversation-registry-component-outlet\n [component]=\"getRendererComponent(message)\"\n [componentLoader]=\"getRendererComponentLoader(message)\"\n [inputs]=\"getRendererInputs(message)\"\n />\n\n @if (messageSupportsReactions(message) && message.reactions.length > 0) {\n <div class=\"message-reactions-container\">\n <div class=\"message-reactions-bubbles\">\n @for (reaction of getGroupedReactions(message); track reaction.emoji) {\n <button\n type=\"button\"\n class=\"reaction-bubble\"\n [class.reaction-bubble-active]=\"reaction.hasReacted\"\n (click)=\"onReactionClick(message, reaction.emoji)\"\n [attr.aria-label]=\"reaction.emoji + ' ' + reaction.count\"\n >\n <span class=\"reaction-emoji\">{{ reaction.emoji }}</span>\n @if (reaction.count > 1) {\n <span class=\"reaction-count\">{{ reaction.count }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Message Footer -->\n <div class=\"message-footer\">\n @let replyCount = getReplyCount(message);\n @let forwardCount = getForwardCount(message);\n @if (replyCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"replyCount + ' replies'\">\n <i class=\"fa-solid fa-message\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ replyCount }}</span>\n </span>\n }\n @if (forwardCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"forwardCount + ' forwards'\">\n <i class=\"fa-solid fa-share\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ forwardCount }}</span>\n </span>\n }\n @if (replyCount > 0 || forwardCount > 0) {\n <span class=\"message-footer-split\" aria-hidden=\"true\"></span>\n }\n <span class=\"message-time\">{{ message.timestamp | format: 'timeleft' | async }}</span>\n @if (message.editedAt) {\n <span class=\"edited-indicator\">\n <span>{{ '@acorex:chat.status.edited' | translate | async }}</span>\n </span>\n }\n @if (isOwnMessage(message)) {\n <span [class]=\"getStatusIconClasses(message)\">\n <ax-icon><i [class]=\"getStatusIcon(message)\"></i></ax-icon>\n </span>\n }\n </div>\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Message Actions -->\n <ax-context-menu\n [target]=\"'#message-bubble-' + message.id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleMessageContextMenuOpening($event, message)\"\n (onClose)=\"contextMenuMessageId.set(null)\"\n (onItemClick)=\"handleMessageContextMenuItemClick($event, message)\"\n >\n </ax-context-menu>\n </div>\n }\n }\n </div>\n\n <!-- Scroll to Bottom Button -->\n @if (showScrollButton()) {\n <div\n class=\"scroll-to-bottom-wrapper\"\n animate.enter=\"scroll-to-bottom-enter\"\n animate.leave=\"scroll-to-bottom-leave\"\n >\n <ax-fab\n class=\"scroll-to-bottom\"\n (onClick)=\"scrollToBottom()\"\n [attr.aria-label]=\"'@acorex:chat.actions.scroll-to-bottom' | translate | async\"\n >\n <ax-icon><i class=\"fa-light fa-arrow-down\" aria-hidden=\"true\"></i></ax-icon>\n </ax-fab>\n </div>\n }\n }\n </div>\n }\n\n <!-- Reaction Picker Popover -->\n @if (reactionsEnabled() && reactionPickerTarget()) {\n <ax-popover\n #reactionPopover\n [target]=\"reactionPickerElement()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"reactionPickerPlacement()\"\n (onClose)=\"closeReactionPicker()\"\n >\n <div class=\"reaction-picker-popup\">\n <div class=\"reaction-picker-header\">\n <span class=\"picker-title\">{{ '@acorex:chat.actions.react' | translate | async }}</span>\n <button\n type=\"button\"\n class=\"picker-close\"\n (click)=\"closeReactionPicker()\"\n [attr.aria-label]=\"'@acorex:chat.actions.close' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n <div\n class=\"reaction-picker-emojis\"\n role=\"listbox\"\n [attr.aria-label]=\"'@acorex:chat.actions.choose-reaction' | translate | async\"\n >\n @for (emoji of availableReactions(); track emoji) {\n <button\n type=\"button\"\n class=\"reaction-picker-emoji\"\n [class.reaction-picker-emoji-active]=\"hasUserReactedById(reactionPickerTarget()!, emoji)\"\n (click)=\"onReactionClickById(reactionPickerTarget()!, emoji); closeReactionPicker()\"\n [attr.aria-label]=\"emoji\"\n >\n {{ emoji }}\n </button>\n }\n </div>\n </div>\n </ax-popover>\n }\n} @else {\n <div\n class=\"message-list message-list--no-active\"\n role=\"region\"\n [attr.aria-label]=\"'@acorex:chat.status.no-conversation-selected' | translate | async\"\n >\n <div class=\"list-no-active\">\n <ng-content select=\"ax-conversation-message-list-no-active, [ax-conversation-message-list-no-active]\">\n <ng-container *ngComponentOutlet=\"noActiveFallbackComponent\"></ng-container>\n </ng-content>\n </div>\n </div>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-message-list{position:relative;display:block;height:100%;container-type:inline-size;@keyframes axConversationSurfaceIn{0%{opacity:0}to{opacity:1}}@keyframes axConversationSurfaceInReduced{0%{opacity:.92}to{opacity:1}}@keyframes messagesSkeletonIn{0%{opacity:0;transform:translateY(.75rem)}to{opacity:1;transform:translateY(0)}}@keyframes messagesSkeletonInReduced{0%{opacity:.85}to{opacity:1}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes axChatLoadMoreDot{0%,70%,to{transform:translateY(0) scale(1);opacity:.4}35%{transform:translateY(-.28rem) scale(1.08);opacity:1}}@keyframes axChatLoadMoreEnterPrepend{0%{opacity:0;transform:translateY(-.5rem)}to{opacity:1;transform:translateY(0)}}@keyframes axChatLoadMoreLeavePrepend{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-.35rem)}}@keyframes axScrollToBottomEnter{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes axScrollToBottomLeave{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}}ax-conversation-message-list .message-list{position:relative;display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 0);flex-direction:column;overflow:hidden}ax-conversation-message-list .message-list.ax-drop-zone>.ax-uploader-overlay-state{display:none!important}ax-conversation-message-list .message-list--drag{outline-style:var(--tw-outline-style);outline-width:2px;outline-color:rgba(var(--ax-sys-color-primary-surface));--tw-outline-style: dashed;outline-style:dashed;outline-offset:-2px}ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceIn .36s cubic-bezier(.22,1,.36,1) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceInReduced .18s ease both}}ax-conversation-message-list .list-loading{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;justify-content:flex-end;overflow:hidden}ax-conversation-message-list .messages-skeleton{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 6);animation:messagesSkeletonIn .42s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .message-skeleton{display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-message-list .message-skeleton--own{flex-direction:row-reverse}ax-conversation-message-list .message-skeleton-avatar{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);flex-shrink:0;border-radius:calc(infinity * 1px)}ax-conversation-message-list .message-skeleton-bubble{height:calc(var(--spacing, .25rem) * 10);border-radius:var(--radius-2xl, 1rem);width:min(62%,17.5rem)}ax-conversation-message-list .message-skeleton-bubble--short{height:calc(var(--spacing, .25rem) * 8);width:min(36%,9.5rem)}ax-conversation-message-list .message-skeleton-bubble--medium{height:calc(var(--spacing, .25rem) * 9);width:min(48%,13rem)}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .messages-skeleton{animation:messagesSkeletonInReduced .2s ease both}}ax-conversation-message-list .list-empty{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 5);padding-inline:calc(var(--spacing, .25rem) * 8);padding-block:calc(var(--spacing, .25rem) * 12);text-align:center;animation:fadeInUp .5s ease-out}ax-conversation-message-list .message-list--no-active{height:100%}ax-conversation-message-list .list-no-active{display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 48);flex-direction:column;align-items:center;justify-content:center}ax-conversation-message-list .empty-icon{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:5.5rem;--tw-leading: 1;line-height:1;opacity:35%;filter:grayscale(.2)}ax-conversation-message-list .empty-title{margin:calc(var(--spacing, .25rem) * 0);font-size:1.625rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-tight, -.025em);letter-spacing:var(--tracking-tight, -.025em);color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-message-list .empty-description{margin:calc(var(--spacing, .25rem) * 0);max-width:420px;font-size:1.0625rem;--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgba(var(--ax-sys-color-on-surface));opacity:.65}ax-conversation-message-list .spinner{margin-bottom:calc(var(--spacing, .25rem) * 4);height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:3px;border-color:rgba(var(--ax-sys-color-border-light-surface));border-top-color:rgb(var(--ax-sys-color-primary-500));animation:spin .8s linear infinite}ax-conversation-message-list .list-loading-more{display:flex;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);padding-bottom:calc(var(--spacing, .25rem) * 2);text-align:center;color:rgba(var(--ax-sys-color-on-surface));opacity:85%}ax-conversation-message-list .load-more-indicator{display:flex;min-height:calc(var(--spacing, .25rem) * 5);align-items:center;justify-content:center;gap:.3rem}ax-conversation-message-list .load-more-dot{height:.4rem;width:.4rem;border-radius:calc(infinity * 1px);background-color:rgba(var(--ax-sys-color-primary-500));animation:axChatLoadMoreDot 1s ease-in-out infinite}ax-conversation-message-list .load-more-dot:nth-child(2){animation-delay:.14s}ax-conversation-message-list .load-more-dot:nth-child(3){animation-delay:.28s}ax-conversation-message-list .load-more-label{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%}ax-conversation-message-list .load-more-enter{animation:axChatLoadMoreEnterPrepend .32s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .load-more-leave{animation:axChatLoadMoreLeavePrepend .22s ease both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .load-more-dot{animation:none;opacity:.65}ax-conversation-message-list .load-more-enter,ax-conversation-message-list .load-more-leave{animation:none}}ax-conversation-message-list .messages-container{position:relative;min-height:calc(var(--spacing, .25rem) * 0);width:100%;flex:1;overflow-x:hidden;overflow-y:auto}ax-conversation-message-list .date-separator{pointer-events:none;position:sticky;z-index:150;display:flex;align-items:center;justify-content:center;top:.5rem;padding:.375rem 1rem .625rem;margin-block:.125rem .375rem}ax-conversation-message-list .date-separator__label{pointer-events:auto;display:inline-flex;width:calc(var(--spacing, .25rem) * 32);max-width:min(100%,18rem);align-items:center;justify-content:center;border-radius:calc(infinity * 1px);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1);text-align:center;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-tight, 1.25);line-height:var(--leading-tight, 1.25);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);white-space:nowrap;-webkit-user-select:none;user-select:none;color:rgba(var(--ax-sys-color-on-lightest-surface));background:rgba(var(--ax-sys-color-lightest-surface));border:1px solid rgba(var(--ax-sys-color-on-lightest-surface),.25)}ax-conversation-message-list .unread-separator{margin-block:calc(var(--spacing, .25rem) * 6);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4)}ax-conversation-message-list .unread-separator-line{height:1px;flex:1;background-color:rgba(var(--ax-sys-color-primary-surface));opacity:30%}ax-conversation-message-list .unread-separator-text{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}ax-conversation-message-list .message-item{position:relative;display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 2);--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);transition:background-color .3s ease}ax-conversation-message-list .message-item-context-active{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.09);box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.22)}ax-conversation-message-list .message-own.message-item-context-active{background-color:rgba(var(--ax-sys-color-primary-500),.12)}ax-conversation-message-list .message-highlight{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-message-list .message-item.message-own{flex-direction:row-reverse}ax-conversation-message-list .message-avatar{flex-shrink:0}ax-conversation-message-list .message-avatar-icon{display:flex;height:100%;width:100%;align-items:center;justify-content:center;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: 1;line-height:1}ax-conversation-message-list .message-content-row{position:relative;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:0 1 auto;flex-direction:row;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 1);max-width:min(95%,50rem)}@container (min-width: 768px){ax-conversation-message-list .message-content-row{max-width:min(70%,50rem)}}ax-conversation-message-list .message-content-row-own{justify-content:flex-end}ax-conversation-message-list .message-item:not(.message-own) .message-content-row{justify-content:flex-start}ax-conversation-message-list .message-bubble-container{position:relative;display:flex;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0);flex:1 1 auto;flex-direction:column}ax-conversation-message-list .message-own .message-bubble-container{align-items:flex-end}ax-conversation-message-list .message-sender{margin-bottom:.1rem;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-bubble{position:relative;display:flex;max-width:100%;flex-direction:column;border-radius:var(--radius-2xl, 1rem);background-color:rgba(var(--ax-sys-color-lightest-surface));padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);padding-bottom:.1rem;overflow-wrap:break-word;transition:background-color .3s ease}ax-conversation-message-list .reply-preview{margin-bottom:calc(var(--spacing, .25rem) * 2);cursor:pointer;border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .reply-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .reply-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .reply-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .reply-preview-line{width:3px;flex-shrink:0;border-radius:1.5px;background:currentColor;opacity:.5}ax-conversation-message-list .reply-preview-content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-message-list .reply-preview-sender{margin-bottom:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .reply-preview-text{overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .reply-preview-sender{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .reply-preview-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .last-message{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .forwarded-preview{margin-bottom:.1rem;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .forwarded-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .forwarded-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .forwarded-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .forwarded-preview i{flex-shrink:0;font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .forwarded-text{min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .forwarded-preview i{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .forwarded-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .message-bubble-received{border-end-start-radius:.125rem}ax-conversation-message-list .message-bubble-received:before,ax-conversation-message-list .message-bubble-sent:after{content:\"\";display:block;position:absolute;bottom:0;width:.8rem;height:.8rem;pointer-events:none;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;mask-mode:alpha}ax-conversation-message-list .message-bubble-received:before{background-color:rgba(var(--ax-sys-color-lightest-surface));inset-inline-start:-.7rem;-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list .message-bubble-sent{border-end-end-radius:.125rem}ax-conversation-message-list .message-bubble-sent:after{background:rgb(var(--ax-sys-color-primary-surface));inset-inline-end:-.7rem;-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}[dir=rtl] ax-conversation-message-list .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list:dir(rtl) .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list:dir(rtl) .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}[dir=ltr] ax-conversation-message-list .message-bubble-received:before{-webkit-mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 0% 0%,transparent 99.5%,#fff 100%)}[dir=ltr] ax-conversation-message-list .message-bubble-sent:after{-webkit-mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%);mask-image:radial-gradient(circle .69rem at 100% 0%,transparent 99.5%,#fff 100%)}ax-conversation-message-list .message-own .message-bubble{background:rgb(var(--ax-sys-color-primary-surface));color:rgb(var(--ax-sys-color-on-primary-surface))}ax-conversation-message-list .message-bubble.message-system{background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);max-width:100%}ax-conversation-message-list .message-bubble.message-system:before,ax-conversation-message-list .message-bubble.message-system:after{display:none}ax-conversation-message-list .message-item:has(.message-system){justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .message-item:has(.message-system) .message-content-row{max-width:100%;justify-content:center}ax-conversation-message-list .message-item:has(.message-system) .message-bubble-container{align-items:center}ax-conversation-message-list .message-content{font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);white-space:pre-wrap}ax-conversation-message-list ax-conversation-registry-component-outlet{display:block;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0)}ax-conversation-message-list .message-footer{margin-top:.1rem;display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 1);padding-inline-start:calc(var(--spacing, .25rem) * 1);font-size:.6875rem;--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%;-webkit-user-select:none;user-select:none}ax-conversation-message-list .message-footer-count{display:inline-flex;align-items:center;gap:.2rem;font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .message-footer-count i{font-size:.625rem;opacity:90%}ax-conversation-message-list .message-footer-count-value{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-footer-split{margin-inline:.2rem;height:.65rem;width:1px;flex-shrink:0;align-self:center;background-color:rgba(var(--ax-sys-color-border-light-surface));opacity:90%}ax-conversation-message-list .message-time{font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .edited-indicator{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1);border-inline-start-style:var(--tw-border-style);border-inline-start-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline-start:.35rem;font-size:.675rem;opacity:75%}ax-conversation-message-list .status-icon{display:inline-flex;align-items:center}ax-conversation-message-list .status-icon i{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}ax-conversation-message-list .status-read{color:rgba(var(--ax-sys-color-primary-200))}ax-conversation-message-list .status-failed{color:rgba(var(--ax-sys-color-danger-200))}ax-conversation-message-list .message-reactions-bubbles{display:flex;flex-wrap:wrap;align-items:center;gap:.2rem}ax-conversation-message-list .reaction-bubble{margin:calc(var(--spacing, .25rem) * 0);display:inline-flex;min-height:1.375rem;cursor:pointer;align-items:center;justify-content:center;gap:.15rem;border-radius:var(--radius-xl, .75rem);padding-inline:.35rem;padding-block:.1rem;color:rgba(var(--ax-sys-color-on-surface));--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);background:rgba(var(--ax-sys-color-on-surface),.06);border:1px solid rgba(var(--ax-sys-color-on-surface),.1);transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}ax-conversation-message-list .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-surface),.1);border-color:rgba(var(--ax-sys-color-on-surface),.18)}ax-conversation-message-list .reaction-bubble-active{background:rgba(var(--ax-sys-color-primary-500),.12);border-color:rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-message-list .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-primary-500),.18);border-color:rgba(var(--ax-sys-color-primary-500),.55)}ax-conversation-message-list .reaction-emoji{display:inline-block;font-size:.8125rem;--tw-leading: 1;line-height:1}ax-conversation-message-list .reaction-count{font-size:.6875rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgba(var(--ax-sys-color-on-surface));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:.65}ax-conversation-message-list .reaction-bubble-active .reaction-count{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600));opacity:95%}ax-conversation-message-list .message-own .reaction-bubble{color:rgba(var(--ax-sys-color-on-primary-surface));background:rgba(var(--ax-sys-color-on-primary-surface),.12);border-color:rgba(var(--ax-sys-color-on-primary-surface),.2)}ax-conversation-message-list .message-own .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.2);border-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .reaction-bubble-active{background:rgba(var(--ax-sys-color-on-primary-surface),.28);border-color:rgba(var(--ax-sys-color-on-primary-surface),.5)}ax-conversation-message-list .message-own .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.34);border-color:rgba(var(--ax-sys-color-on-primary-surface),.6)}ax-conversation-message-list .message-own .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:80%}ax-conversation-message-list .message-own .reaction-bubble-active .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:100%}ax-conversation-message-list .message-reactions-container{margin-top:calc(var(--spacing, .25rem) * 1);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:.2rem}ax-conversation-message-list .message-own .message-reactions-container{justify-content:flex-end}ax-conversation-message-list .message-own .message-footer .edited-indicator{border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .message-footer .message-footer-split{background:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .add-reaction-button.add-reaction-outside{position:absolute;top:50%;margin:calc(var(--spacing, .25rem) * 0);box-sizing:border-box;display:none;height:1.8rem;width:1.8rem;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));padding:calc(var(--spacing, .25rem) * 0);inset-inline-end:-2.25rem;box-shadow:0 1px 2px #0000000f}ax-conversation-message-list .add-reaction-button{padding-inline-start:.05rem}ax-conversation-message-list .message-content-row-own .add-reaction-button.add-reaction-outside{inset-inline-start:-2.25rem;inset-inline-end:auto}ax-conversation-message-list .message-item:hover .add-reaction-button.add-reaction-outside,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{display:inline-flex}ax-conversation-message-list .add-reaction-button.add-reaction-outside:hover,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .add-reaction-button.add-reaction-outside i{font-size:.9rem;color:rgba(var(--ax-sys-color-on-surface));opacity:80%}ax-conversation-message-list .reaction-bubble:focus-visible,ax-conversation-message-list .add-reaction-button:focus-visible,ax-conversation-message-list .action-trigger:focus-visible,ax-conversation-message-list ax-fab.scroll-to-bottom ax-button:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .message-actions{z-index:10;padding-bottom:calc(var(--spacing, .25rem) * 6);opacity:0%;transition:opacity var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .message-item:hover .message-actions{opacity:100%}ax-conversation-message-list .action-trigger{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .action-trigger:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-message-list .shortcut{font-size:.6875rem;opacity:70%}ax-conversation-message-list .scroll-to-bottom-wrapper{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * 4);bottom:calc(var(--spacing, .25rem) * 4);z-index:999}ax-conversation-message-list ax-fab.scroll-to-bottom ax-button{display:flex;height:calc(var(--spacing, .25rem) * 12);width:calc(var(--spacing, .25rem) * 12);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none}ax-conversation-message-list .scroll-to-bottom-enter{animation:axScrollToBottomEnter var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}ax-conversation-message-list .scroll-to-bottom-leave{animation:axScrollToBottomLeave var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .scroll-to-bottom-enter,ax-conversation-message-list .scroll-to-bottom-leave{animation:none}}.reaction-picker-popup{width:max-content;min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;border-radius:.65rem;background-color:rgba(var(--ax-sys-color-lightest-surface));max-width:min(260px,92vw)}.reaction-picker-header{display:flex;min-height:calc(var(--spacing, .25rem) * 0);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:.45rem;padding-inline-start:.7rem;padding-inline-end:calc(var(--spacing, .25rem) * 2)}.picker-title{font-size:.8125rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-on-surface));opacity:85%}.picker-close{display:flex;height:1.6rem;width:1.6rem;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:.95rem;color:rgba(var(--ax-sys-color-on-surface),.55);transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}.picker-close:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}.picker-close:focus-visible,.reaction-picker-emoji:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}.reaction-picker-emojis{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.2rem;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:.45rem;padding-bottom:calc(var(--spacing, .25rem) * 2)}.reaction-picker-emoji{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);cursor:pointer;border-radius:.45rem;border-style:var(--tw-border-style);border-width:1px;border-color:transparent;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:1.15rem;--tw-leading: 1;line-height:1;transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.reaction-picker-emoji:hover{background-color:rgba(var(--ax-sys-color-lighter-surface))}.reaction-picker-emoji-active{background-color:rgba(var(--ax-sys-color-surface))}.reaction-picker-emoji-active:hover{background:rgba(var(--ax-sys-color-primary-500),.25)}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@keyframes spin{to{transform:rotate(360deg)}}@keyframes fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-outline-style: solid;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
9017
+ ], template: "@if (activeConversation(); as conv) {\n @for (cid of [conv.id]; track cid) {\n <div\n class=\"message-list message-list--conversation-surface\"\n [class.message-list--drag]=\"messageListDragging()\"\n #messageList\n role=\"log\"\n [attr.aria-label]=\"'@acorex:chat.aria.message-list' | translate | async\"\n aria-live=\"polite\"\n [style.background]=\"messageListBackgroundStyle()\"\n [style.--ax-comp-message-list-surface-bg]=\"messageListBackgroundStyle()\"\n axUploaderZone\n [disableBrowse]=\"true\"\n (dragEnter)=\"onMessageListDragEnter()\"\n (dragLeave)=\"onMessageListDragLeave()\"\n (fileChange)=\"onMessageListFilesDropped($event)\"\n >\n @if (loading()) {\n <div\n class=\"list-loading\"\n role=\"status\"\n aria-busy=\"true\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-messages' | translate | async\"\n >\n <div class=\"messages-skeleton\" aria-hidden=\"true\">\n @for (item of loadingSkeletonItems; track item) {\n <div class=\"message-skeleton\" [class.message-skeleton--own]=\"$odd\">\n @if ($even && isGroupConversation()) {\n <ax-skeleton class=\"message-skeleton-avatar\" [animated]=\"true\"></ax-skeleton>\n }\n <ax-skeleton\n class=\"message-skeleton-bubble\"\n [class.message-skeleton-bubble--short]=\"$index % 3 === 1\"\n [class.message-skeleton-bubble--medium]=\"$index % 3 === 2\"\n [animated]=\"true\"\n ></ax-skeleton>\n </div>\n }\n </div>\n </div>\n } @else if (messages().length === 0) {\n <div class=\"list-empty\" role=\"status\" [attr.aria-label]=\"'@acorex:chat.status.no-messages' | translate | async\">\n <ng-content select=\"ax-conversation-message-list-empty, [ax-conversation-message-list-empty]\">\n <ng-container\n *ngComponentOutlet=\"resolvedEmptyStateComponent(); inputs: { conversation: activeConversation()! }\"\n ></ng-container>\n </ng-content>\n </div>\n } @else {\n <div\n class=\"messages-container\"\n (scroll)=\"onScroll($event)\"\n axInfiniteScroll\n [threshold]=\"config.infiniteScrollThreshold\"\n [edge]=\"'top'\"\n [scrollDisabled]=\"loading() || loadingMore() || !hasMoreMessages()\"\n (scrollThreshold)=\"onScrollThreshold($event)\"\n #messagesContainer\n role=\"feed\"\n [attr.aria-label]=\"'@acorex:chat.aria.messages' | translate | async\"\n >\n @if (loadingMore()) {\n <div\n class=\"list-loading-more list-loading-more--prepend\"\n role=\"status\"\n animate.enter=\"load-more-enter\"\n animate.leave=\"load-more-leave\"\n [attr.aria-label]=\"'@acorex:chat.status.loading-older-messages' | translate | async\"\n >\n <div class=\"load-more-indicator\" aria-hidden=\"true\">\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n <span class=\"load-more-dot\"></span>\n </div>\n <ax-label class=\"load-more-label\">{{\n '@acorex:chat.status.loading-older-messages' | translate | async\n }}</ax-label>\n </div>\n }\n @for (group of messageGroups(); track trackMessageGroup($index, group)) {\n <!-- Date Separator -->\n <div class=\"date-separator\" role=\"separator\" [attr.aria-label]=\"getDateSeparatorAriaLabel(group.dateLabel)\">\n <span class=\"date-separator__label\">{{ group.dateLabel }}</span>\n </div>\n\n <!-- Messages in this date group -->\n @for (message of group.messages; track trackMessage($index, message)) {\n <div\n [class]=\"getMessageClasses(message)\"\n role=\"article\"\n [attr.aria-label]=\"getMessageAriaLabel(message)\"\n [id]=\"'message-' + message.id\"\n >\n <!-- Avatar (only for group conversations and received messages) -->\n @if (shouldShowAvatar(message)) {\n <div class=\"message-avatar\">\n <ax-conversation-avatar\n kind=\"user\"\n [userId]=\"message.senderId\"\n [conversation]=\"activeConversation()\"\n [message]=\"message\"\n [size]=\"32\"\n />\n </div>\n }\n\n <div class=\"message-content-row\" [class.message-content-row-own]=\"isOwnMessage(message)\">\n @if (messageSupportsReactions(message)) {\n <button\n type=\"button\"\n class=\"add-reaction-button add-reaction-outside\"\n [class.add-reaction-visible]=\"reactionPickerTarget() === message.id\"\n (click)=\"toggleReactionPicker(message, $event)\"\n [attr.aria-label]=\"'@acorex:chat.actions.add-reaction' | translate | async\"\n #reactionButton\n >\n <i class=\"fa-light fa-face-smile\"></i>\n </button>\n }\n\n <div\n class=\"message-bubble-container\"\n [id]=\"'message-bubble-' + message.id\"\n [attr.data-message-id]=\"message.id\"\n >\n <div\n [class]=\"getBubbleClasses(message)\"\n [class.message-bubble-sent]=\"message.senderId === currentUser()?.id\"\n [class.message-bubble-received]=\"message.senderId !== currentUser()?.id\"\n >\n <!-- Sender name (only for group conversations and received messages) -->\n @if (shouldShowSenderName(message)) {\n <div class=\"message-sender\">{{ getSenderName(message) }}:</div>\n }\n\n <!-- Reply Preview -->\n @if (message.replyTo) {\n <div\n class=\"reply-preview\"\n (click)=\"scrollToMessage(message.replyTo.id)\"\n role=\"button\"\n [attr.aria-label]=\"'Reply to ' + getSenderName(message.replyTo)\"\n (keydown.enter)=\"scrollToMessage(message.replyTo.id)\"\n (keydown.space)=\"scrollToMessage(message.replyTo.id)\"\n >\n <div class=\"reply-preview-content\">\n <div class=\"reply-preview-sender\">{{ getSenderName(message.replyTo) }}</div>\n <div class=\"reply-preview-text\">\n @if (getMessagePreviewText(message.replyTo); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i\n >{{ '@acorex:chat.' + preview.type | translate | async }}\n } @else {\n {{ preview.value }}\n }\n </span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Forwarded Indicator -->\n @if (message.forwarded) {\n <div class=\"forwarded-preview\">\n <i class=\"fa-solid fa-share\"></i>\n <span class=\"forwarded-text\">{{ getForwardedText(message) }}</span>\n </div>\n }\n\n <ax-conversation-registry-component-outlet\n [component]=\"getRendererComponent(message)\"\n [componentLoader]=\"getRendererComponentLoader(message)\"\n [inputs]=\"getRendererInputs(message)\"\n />\n\n @if (messageSupportsReactions(message) && message.reactions.length > 0) {\n <div class=\"message-reactions-container\">\n <div class=\"message-reactions-bubbles\">\n @for (reaction of getGroupedReactions(message); track reaction.emoji) {\n <button\n type=\"button\"\n class=\"reaction-bubble\"\n [class.reaction-bubble-active]=\"reaction.hasReacted\"\n (click)=\"onReactionClick(message, reaction.emoji)\"\n [attr.aria-label]=\"reaction.emoji + ' ' + reaction.count\"\n >\n <span class=\"reaction-emoji\">{{ reaction.emoji }}</span>\n @if (reaction.count > 1) {\n <span class=\"reaction-count\">{{ reaction.count }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Message Footer -->\n <div class=\"message-footer\">\n @let replyCount = getReplyCount(message);\n @let forwardCount = getForwardCount(message);\n @if (replyCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"replyCount + ' replies'\">\n <i class=\"fa-solid fa-message\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ replyCount }}</span>\n </span>\n }\n @if (forwardCount > 0) {\n <span class=\"message-footer-count\" [attr.aria-label]=\"forwardCount + ' forwards'\">\n <i class=\"fa-solid fa-share\" aria-hidden=\"true\"></i>\n <span class=\"message-footer-count-value\">{{ forwardCount }}</span>\n </span>\n }\n @if (replyCount > 0 || forwardCount > 0) {\n <span class=\"message-footer-split\" aria-hidden=\"true\"></span>\n }\n <span class=\"message-time\">{{ message.timestamp | format: 'timeleft' | async }}</span>\n @if (message.editedAt) {\n <span class=\"edited-indicator\">\n <span>{{ '@acorex:chat.status.edited' | translate | async }}</span>\n </span>\n }\n @if (isOwnMessage(message)) {\n <span [class]=\"getStatusIconClasses(message)\">\n <ax-icon><i [class]=\"getStatusIcon(message)\"></i></ax-icon>\n </span>\n }\n </div>\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Message Actions -->\n <ax-context-menu\n [target]=\"'#message-bubble-' + message.id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleMessageContextMenuOpening($event, message)\"\n (onClose)=\"contextMenuMessageId.set(null)\"\n (onItemClick)=\"handleMessageContextMenuItemClick($event, message)\"\n >\n </ax-context-menu>\n </div>\n }\n }\n </div>\n\n <!-- Scroll to Bottom Button -->\n @if (showScrollButton()) {\n <div\n class=\"scroll-to-bottom-wrapper\"\n animate.enter=\"scroll-to-bottom-enter\"\n animate.leave=\"scroll-to-bottom-leave\"\n >\n <ax-fab\n class=\"scroll-to-bottom\"\n (onClick)=\"scrollToBottom()\"\n [attr.aria-label]=\"'@acorex:chat.actions.scroll-to-bottom' | translate | async\"\n >\n <ax-icon><i class=\"fa-light fa-arrow-down\" aria-hidden=\"true\"></i></ax-icon>\n </ax-fab>\n </div>\n }\n }\n </div>\n }\n\n <!-- Reaction Picker Popover -->\n @if (reactionsEnabled() && reactionPickerTarget()) {\n <ax-popover\n #reactionPopover\n [target]=\"reactionPickerElement()\"\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [placement]=\"reactionPickerPlacement()\"\n (onClose)=\"closeReactionPicker()\"\n >\n <div class=\"reaction-picker-popup\">\n <div class=\"reaction-picker-header\">\n <span class=\"picker-title\">{{ '@acorex:chat.actions.react' | translate | async }}</span>\n <button\n type=\"button\"\n class=\"picker-close\"\n (click)=\"closeReactionPicker()\"\n [attr.aria-label]=\"'@acorex:chat.actions.close' | translate | async\"\n >\n <i class=\"fa-light fa-xmark\"></i>\n </button>\n </div>\n <div\n class=\"reaction-picker-emojis\"\n role=\"listbox\"\n [attr.aria-label]=\"'@acorex:chat.actions.choose-reaction' | translate | async\"\n >\n @for (emoji of availableReactions(); track emoji) {\n <button\n type=\"button\"\n class=\"reaction-picker-emoji\"\n [class.reaction-picker-emoji-active]=\"hasUserReactedById(reactionPickerTarget()!, emoji)\"\n (click)=\"onReactionClickById(reactionPickerTarget()!, emoji); closeReactionPicker()\"\n [attr.aria-label]=\"emoji\"\n >\n {{ emoji }}\n </button>\n }\n </div>\n </div>\n </ax-popover>\n }\n} @else {\n <div\n class=\"message-list message-list--no-active\"\n role=\"region\"\n [attr.aria-label]=\"'@acorex:chat.status.no-conversation-selected' | translate | async\"\n >\n <div class=\"list-no-active\">\n <ng-content select=\"ax-conversation-message-list-no-active, [ax-conversation-message-list-no-active]\">\n <ng-container *ngComponentOutlet=\"noActiveFallbackComponent\"></ng-container>\n </ng-content>\n </div>\n </div>\n}\n", styles: ["@layer properties;@layer components{ax-conversation-message-list{position:relative;display:block;height:100%;container-type:inline-size;--ax-comp-message-bubble-tail-height: 1.5625rem;--ax-comp-message-bubble-tail-fill-width: 1.25rem;--ax-comp-message-bubble-tail-fill-offset: -.4375rem;--ax-comp-message-bubble-tail-cutout-width: 1.625rem;--ax-comp-message-bubble-tail-cutout-offset: -1.625rem;--ax-comp-message-bubble-tail-curve: 1rem 0rem;--ax-comp-message-bubble-tail-cutout-curve: .625rem;@keyframes axConversationSurfaceIn{0%{opacity:0}to{opacity:1}}@keyframes axConversationSurfaceInReduced{0%{opacity:.92}to{opacity:1}}@keyframes messagesSkeletonIn{0%{opacity:0;transform:translateY(.75rem)}to{opacity:1;transform:translateY(0)}}@keyframes messagesSkeletonInReduced{0%{opacity:.85}to{opacity:1}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes axChatLoadMoreDot{0%,70%,to{transform:translateY(0) scale(1);opacity:.4}35%{transform:translateY(-.28rem) scale(1.08);opacity:1}}@keyframes axChatLoadMoreEnterPrepend{0%{opacity:0;transform:translateY(-.5rem)}to{opacity:1;transform:translateY(0)}}@keyframes axChatLoadMoreLeavePrepend{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-.35rem)}}@keyframes axScrollToBottomEnter{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes axScrollToBottomLeave{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}}ax-conversation-message-list .message-list{position:relative;display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 0);flex-direction:column;overflow:hidden}ax-conversation-message-list .message-list.ax-drop-zone>.ax-uploader-overlay-state{display:none!important}ax-conversation-message-list .message-list--drag{outline-style:var(--tw-outline-style);outline-width:2px;outline-color:rgba(var(--ax-sys-color-primary-surface));--tw-outline-style: dashed;outline-style:dashed;outline-offset:-2px}ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceIn .36s cubic-bezier(.22,1,.36,1) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .message-list--conversation-surface{animation:axConversationSurfaceInReduced .18s ease both}}ax-conversation-message-list .list-loading{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;justify-content:flex-end;overflow:hidden}ax-conversation-message-list .messages-skeleton{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 6);animation:messagesSkeletonIn .42s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .message-skeleton{display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2)}ax-conversation-message-list .message-skeleton--own{flex-direction:row-reverse}ax-conversation-message-list .message-skeleton-avatar{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);flex-shrink:0;border-radius:calc(infinity * 1px)}ax-conversation-message-list .message-skeleton-bubble{height:calc(var(--spacing, .25rem) * 10);border-radius:var(--radius-2xl, 1rem);width:min(62%,17.5rem)}ax-conversation-message-list .message-skeleton-bubble--short{height:calc(var(--spacing, .25rem) * 8);width:min(36%,9.5rem)}ax-conversation-message-list .message-skeleton-bubble--medium{height:calc(var(--spacing, .25rem) * 9);width:min(48%,13rem)}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .messages-skeleton{animation:messagesSkeletonInReduced .2s ease both}}ax-conversation-message-list .list-empty{display:flex;min-height:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 5);padding-inline:calc(var(--spacing, .25rem) * 8);padding-block:calc(var(--spacing, .25rem) * 12);text-align:center;animation:fadeInUp .5s ease-out}ax-conversation-message-list .message-list--no-active{height:100%}ax-conversation-message-list .list-no-active{display:flex;height:100%;min-height:calc(var(--spacing, .25rem) * 48);flex-direction:column;align-items:center;justify-content:center}ax-conversation-message-list .empty-icon{margin-bottom:calc(var(--spacing, .25rem) * 2);font-size:5.5rem;--tw-leading: 1;line-height:1;opacity:35%;filter:grayscale(.2)}ax-conversation-message-list .empty-title{margin:calc(var(--spacing, .25rem) * 0);font-size:1.625rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-tight, -.025em);letter-spacing:var(--tracking-tight, -.025em);color:rgba(var(--ax-sys-color-on-surface))}ax-conversation-message-list .empty-description{margin:calc(var(--spacing, .25rem) * 0);max-width:420px;font-size:1.0625rem;--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgba(var(--ax-sys-color-on-surface));opacity:.65}ax-conversation-message-list .spinner{margin-bottom:calc(var(--spacing, .25rem) * 4);height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:3px;border-color:rgba(var(--ax-sys-color-border-light-surface));border-top-color:rgb(var(--ax-sys-color-primary-500));animation:spin .8s linear infinite}ax-conversation-message-list .list-loading-more{display:flex;flex-direction:column;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);padding-bottom:calc(var(--spacing, .25rem) * 2);text-align:center;color:rgba(var(--ax-sys-color-on-surface));opacity:85%}ax-conversation-message-list .load-more-indicator{display:flex;min-height:calc(var(--spacing, .25rem) * 5);align-items:center;justify-content:center;gap:.3rem}ax-conversation-message-list .load-more-dot{height:.4rem;width:.4rem;border-radius:calc(infinity * 1px);background-color:rgba(var(--ax-sys-color-primary-500));animation:axChatLoadMoreDot 1s ease-in-out infinite}ax-conversation-message-list .load-more-dot:nth-child(2){animation-delay:.14s}ax-conversation-message-list .load-more-dot:nth-child(3){animation-delay:.28s}ax-conversation-message-list .load-more-label{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%}ax-conversation-message-list .load-more-enter{animation:axChatLoadMoreEnterPrepend .32s cubic-bezier(.22,1,.36,1) both}ax-conversation-message-list .load-more-leave{animation:axChatLoadMoreLeavePrepend .22s ease both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .load-more-dot{animation:none;opacity:.65}ax-conversation-message-list .load-more-enter,ax-conversation-message-list .load-more-leave{animation:none}}ax-conversation-message-list .messages-container{position:relative;min-height:calc(var(--spacing, .25rem) * 0);width:100%;flex:1;overflow-y:auto;overflow-x:visible}ax-conversation-message-list .date-separator{pointer-events:none;position:sticky;z-index:150;display:flex;align-items:center;justify-content:center;top:.5rem;padding:.375rem 1rem .625rem;margin-block:.125rem .375rem}ax-conversation-message-list .date-separator__label{pointer-events:auto;display:inline-flex;width:calc(var(--spacing, .25rem) * 32);max-width:min(100%,18rem);align-items:center;justify-content:center;border-radius:calc(infinity * 1px);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1);text-align:center;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-tight, 1.25);line-height:var(--leading-tight, 1.25);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);white-space:nowrap;-webkit-user-select:none;user-select:none;color:rgba(var(--ax-sys-color-on-lightest-surface));background:rgba(var(--ax-sys-color-lightest-surface));border:1px solid rgba(var(--ax-sys-color-on-lightest-surface),.25)}ax-conversation-message-list .unread-separator{margin-block:calc(var(--spacing, .25rem) * 6);display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3);padding-inline:calc(var(--spacing, .25rem) * 4)}ax-conversation-message-list .unread-separator-line{height:1px;flex:1;background-color:rgba(var(--ax-sys-color-primary-surface));opacity:30%}ax-conversation-message-list .unread-separator-text{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));text-transform:uppercase}ax-conversation-message-list .message-item{position:relative;display:flex;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);--tw-leading: calc(var(--spacing, .25rem) * 4);line-height:calc(var(--spacing, .25rem) * 4);padding-inline:1.75rem;transition:background-color .3s ease}ax-conversation-message-list .message-item-context-active{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.09);box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.22)}ax-conversation-message-list .message-own.message-item-context-active{background-color:rgba(var(--ax-sys-color-primary-500),.12)}ax-conversation-message-list .message-highlight{border-radius:var(--radius-lg, .5rem);background-color:rgba(var(--ax-sys-color-primary-500),.1)}ax-conversation-message-list .message-item.message-own{flex-direction:row-reverse}ax-conversation-message-list .message-avatar{z-index:5;flex-shrink:0}ax-conversation-message-list .message-avatar-icon{display:flex;height:100%;width:100%;align-items:center;justify-content:center;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-leading: 1;line-height:1}ax-conversation-message-list .message-content-row{position:relative;display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:0 1 auto;flex-direction:row;align-items:flex-end;gap:calc(var(--spacing, .25rem) * 1);max-width:min(95%,50rem)}@container (min-width: 768px){ax-conversation-message-list .message-content-row{max-width:min(70%,50rem)}}ax-conversation-message-list .message-content-row-own{justify-content:flex-end}ax-conversation-message-list .message-item:not(.message-own) .message-content-row{justify-content:flex-start}ax-conversation-message-list .message-bubble-container{position:relative;display:flex;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0);flex:1 1 auto;flex-direction:column}ax-conversation-message-list .message-own .message-bubble-container{align-items:flex-end}ax-conversation-message-list .message-sender{margin-bottom:.1rem;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-bubble{position:relative;display:flex;max-width:100%;flex-direction:column;border-radius:var(--radius-2xl, 1rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 2);padding-bottom:.1rem;overflow-wrap:break-word;transition:background-color .3s ease}ax-conversation-message-list .message-bubble>*{position:relative;z-index:1}ax-conversation-message-list .reply-preview{margin-bottom:calc(var(--spacing, .25rem) * 2);cursor:pointer;border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .reply-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .reply-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .reply-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .reply-preview-line{width:3px;flex-shrink:0;border-radius:1.5px;background:currentColor;opacity:.5}ax-conversation-message-list .reply-preview-content{min-width:calc(var(--spacing, .25rem) * 0);flex:1}ax-conversation-message-list .reply-preview-sender{margin-bottom:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .reply-preview-text{overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .reply-preview-sender{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .reply-preview-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .last-message{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .forwarded-preview{margin-bottom:.1rem;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-radius:var(--ax-sys-border-radius);border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1.5);background:rgba(var(--ax-sys-color-primary-500),.08);border-inline-start-color:rgb(var(--ax-sys-color-primary-500));transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .forwarded-preview:hover{background:rgba(var(--ax-sys-color-primary-500),.14);border-inline-start-color:rgb(var(--ax-sys-color-primary-600))}ax-conversation-message-list .message-own .forwarded-preview{border-inline-start-style:var(--tw-border-style);border-inline-start-width:3px;background:rgba(var(--ax-sys-color-on-primary-surface),.14);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.55)}ax-conversation-message-list .message-own .forwarded-preview:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.22);border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.75)}ax-conversation-message-list .forwarded-preview i{flex-shrink:0;font-size:.8125rem;color:rgba(var(--ax-sys-color-primary-600))}ax-conversation-message-list .forwarded-text{min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;font-size:.8125rem;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-on-surface));opacity:70%}ax-conversation-message-list .message-own .forwarded-preview i{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:95%}ax-conversation-message-list .message-own .forwarded-text{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:.78}ax-conversation-message-list .message-bubble-received:not(.message-system){--ax-comp-message-bubble-bg: rgb(var(--ax-sys-color-lightest-surface));background-color:var(--ax-comp-message-bubble-bg);border-bottom-left-radius:.25rem}ax-conversation-message-list .message-bubble-sent:not(.message-system){--ax-comp-message-bubble-bg: rgb(var(--ax-sys-color-primary-surface));background-color:var(--ax-comp-message-bubble-bg);color:rgb(var(--ax-sys-color-on-primary-surface));border-bottom-right-radius:.25rem}ax-conversation-message-list .message-bubble-received:not(.message-system):before,ax-conversation-message-list .message-bubble-received:not(.message-system):after,ax-conversation-message-list .message-bubble-sent:not(.message-system):before,ax-conversation-message-list .message-bubble-sent:not(.message-system):after{content:\"\";position:absolute;bottom:0;height:var(--ax-comp-message-bubble-tail-height);pointer-events:none;z-index:0}ax-conversation-message-list .message-bubble-received:not(.message-system):before,ax-conversation-message-list .message-bubble-sent:not(.message-system):before{width:var(--ax-comp-message-bubble-tail-fill-width);background-color:var(--ax-comp-message-bubble-bg)}ax-conversation-message-list .message-bubble-received:not(.message-system):after,ax-conversation-message-list .message-bubble-sent:not(.message-system):after{width:var(--ax-comp-message-bubble-tail-cutout-width);background:var(--ax-comp-message-list-surface-bg, rgb(var(--ax-sys-color-primary-lightest-surface)))}ax-conversation-message-list .message-bubble-received:not(.message-system):before{left:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-right-radius:var(--ax-comp-message-bubble-tail-curve)}ax-conversation-message-list .message-bubble-received:not(.message-system):after{left:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-right-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}ax-conversation-message-list .message-bubble-sent:not(.message-system):before{right:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-left-radius:var(--ax-comp-message-bubble-tail-curve)}ax-conversation-message-list .message-bubble-sent:not(.message-system):after{right:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-left-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system){border-bottom-left-radius:1rem;border-bottom-right-radius:.25rem}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system){border-bottom-right-radius:1rem;border-bottom-left-radius:.25rem}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system):before{left:auto;right:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-right-radius:0;border-bottom-left-radius:var(--ax-comp-message-bubble-tail-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-received:not(.message-system):after{left:auto;right:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-right-radius:0;border-bottom-left-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system):before{right:auto;left:var(--ax-comp-message-bubble-tail-fill-offset);border-bottom-left-radius:0;border-bottom-right-radius:var(--ax-comp-message-bubble-tail-curve)}[dir=rtl] ax-conversation-message-list .message-bubble-sent:not(.message-system):after{right:auto;left:var(--ax-comp-message-bubble-tail-cutout-offset);border-bottom-left-radius:0;border-bottom-right-radius:var(--ax-comp-message-bubble-tail-cutout-curve)}ax-conversation-message-list .message-bubble.message-system:before,ax-conversation-message-list .message-bubble.message-system:after{display:none}ax-conversation-message-list .message-own .message-bubble{color:rgb(var(--ax-sys-color-on-primary-surface))}ax-conversation-message-list .message-bubble.message-system{background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);max-width:100%}ax-conversation-message-list .message-item:has(.message-system){justify-content:center;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 1)}ax-conversation-message-list .message-item:has(.message-system) .message-content-row{max-width:100%;justify-content:center}ax-conversation-message-list .message-item:has(.message-system) .message-bubble-container{align-items:center}ax-conversation-message-list .message-content{font-size:.9375rem;--tw-leading: var(--leading-normal, 1.5);line-height:var(--leading-normal, 1.5);white-space:pre-wrap}ax-conversation-message-list ax-conversation-registry-component-outlet{display:block;max-width:100%;min-width:calc(var(--spacing, .25rem) * 0)}ax-conversation-message-list .message-footer{margin-top:.1rem;display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 1);padding-inline-start:calc(var(--spacing, .25rem) * 1);font-size:.6875rem;--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);opacity:70%;-webkit-user-select:none;user-select:none}ax-conversation-message-list .message-footer-count{display:inline-flex;align-items:center;gap:.2rem;font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .message-footer-count i{font-size:.625rem;opacity:90%}ax-conversation-message-list .message-footer-count-value{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-message-list .message-footer-split{margin-inline:.2rem;height:.65rem;width:1px;flex-shrink:0;align-self:center;background-color:rgba(var(--ax-sys-color-border-light-surface));opacity:90%}ax-conversation-message-list .message-time{font-size:.675rem;--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}ax-conversation-message-list .edited-indicator{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * 1);border-inline-start-style:var(--tw-border-style);border-inline-start-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-inline-start:.35rem;font-size:.675rem;opacity:75%}ax-conversation-message-list .status-icon{display:inline-flex;align-items:center}ax-conversation-message-list .status-icon i{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}ax-conversation-message-list .status-read{color:rgba(var(--ax-sys-color-primary-200))}ax-conversation-message-list .status-failed{color:rgba(var(--ax-sys-color-danger-200))}ax-conversation-message-list .message-reactions-bubbles{display:flex;flex-wrap:wrap;align-items:center;gap:.2rem}ax-conversation-message-list .reaction-bubble{margin:calc(var(--spacing, .25rem) * 0);display:inline-flex;min-height:1.375rem;cursor:pointer;align-items:center;justify-content:center;gap:.15rem;border-radius:var(--radius-xl, .75rem);padding-inline:.35rem;padding-block:.1rem;color:rgba(var(--ax-sys-color-on-surface));--tw-shadow: 0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);background:rgba(var(--ax-sys-color-on-surface),.06);border:1px solid rgba(var(--ax-sys-color-on-surface),.1);transition:background-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function),border-color var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}ax-conversation-message-list .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-surface),.1);border-color:rgba(var(--ax-sys-color-on-surface),.18)}ax-conversation-message-list .reaction-bubble-active{background:rgba(var(--ax-sys-color-primary-500),.12);border-color:rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-message-list .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-primary-500),.18);border-color:rgba(var(--ax-sys-color-primary-500),.55)}ax-conversation-message-list .reaction-emoji{display:inline-block;font-size:.8125rem;--tw-leading: 1;line-height:1}ax-conversation-message-list .reaction-count{font-size:.6875rem;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgba(var(--ax-sys-color-on-surface));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:.65}ax-conversation-message-list .reaction-bubble-active .reaction-count{--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-primary-600));opacity:95%}ax-conversation-message-list .message-own .reaction-bubble{color:rgba(var(--ax-sys-color-on-primary-surface));background:rgba(var(--ax-sys-color-on-primary-surface),.12);border-color:rgba(var(--ax-sys-color-on-primary-surface),.2)}ax-conversation-message-list .message-own .reaction-bubble:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.2);border-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .reaction-bubble-active{background:rgba(var(--ax-sys-color-on-primary-surface),.28);border-color:rgba(var(--ax-sys-color-on-primary-surface),.5)}ax-conversation-message-list .message-own .reaction-bubble-active:hover{background:rgba(var(--ax-sys-color-on-primary-surface),.34);border-color:rgba(var(--ax-sys-color-on-primary-surface),.6)}ax-conversation-message-list .message-own .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:80%}ax-conversation-message-list .message-own .reaction-bubble-active .reaction-count{color:rgba(var(--ax-sys-color-on-primary-surface));opacity:100%}ax-conversation-message-list .message-reactions-container{margin-top:calc(var(--spacing, .25rem) * 1);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:.2rem}ax-conversation-message-list .message-own .message-reactions-container{justify-content:flex-end}ax-conversation-message-list .message-own .message-footer .edited-indicator{border-inline-start-color:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .message-own .message-footer .message-footer-split{background:rgba(var(--ax-sys-color-on-primary-surface),.35)}ax-conversation-message-list .add-reaction-button.add-reaction-outside{position:absolute;top:50%;margin:calc(var(--spacing, .25rem) * 0);box-sizing:border-box;display:none;height:1.8rem;width:1.8rem;--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));padding:calc(var(--spacing, .25rem) * 0);inset-inline-end:-2.25rem;box-shadow:0 1px 2px #0000000f}ax-conversation-message-list .add-reaction-button{padding-inline-start:.05rem}ax-conversation-message-list .message-content-row-own .add-reaction-button.add-reaction-outside{inset-inline-start:-2.25rem;inset-inline-end:auto}ax-conversation-message-list .message-item:hover .add-reaction-button.add-reaction-outside,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{display:inline-flex}ax-conversation-message-list .add-reaction-button.add-reaction-outside:hover,ax-conversation-message-list .add-reaction-button.add-reaction-outside.add-reaction-visible{border-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .add-reaction-button.add-reaction-outside i{font-size:.9rem;color:rgba(var(--ax-sys-color-on-surface));opacity:80%}ax-conversation-message-list .reaction-bubble:focus-visible,ax-conversation-message-list .add-reaction-button:focus-visible,ax-conversation-message-list .action-trigger:focus-visible,ax-conversation-message-list ax-fab.scroll-to-bottom ax-button:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}ax-conversation-message-list .message-actions{z-index:10;padding-bottom:calc(var(--spacing, .25rem) * 6);opacity:0%;transition:opacity var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .message-item:hover .message-actions{opacity:100%}ax-conversation-message-list .action-trigger{display:flex;height:calc(var(--spacing, .25rem) * 7);width:calc(var(--spacing, .25rem) * 7);cursor:pointer;align-items:center;justify-content:center;border-radius:var(--ax-sys-border-radius);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));background-color:rgba(var(--ax-sys-color-surface));font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}ax-conversation-message-list .action-trigger:hover{background-color:rgba(var(--ax-sys-color-light-surface))}ax-conversation-message-list .shortcut{font-size:.6875rem;opacity:70%}ax-conversation-message-list .scroll-to-bottom-wrapper{position:absolute;inset-inline-end:calc(var(--spacing, .25rem) * 4);bottom:calc(var(--spacing, .25rem) * 4);z-index:999}ax-conversation-message-list ax-fab.scroll-to-bottom ax-button{display:flex;height:calc(var(--spacing, .25rem) * 12);width:calc(var(--spacing, .25rem) * 12);cursor:pointer;align-items:center;justify-content:center;border-radius:calc(infinity * 1px);--tw-border-style: none;border-style:none}ax-conversation-message-list .scroll-to-bottom-enter{animation:axScrollToBottomEnter var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}ax-conversation-message-list .scroll-to-bottom-leave{animation:axScrollToBottomLeave var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function) both}@media(prefers-reduced-motion:reduce){ax-conversation-message-list .scroll-to-bottom-enter,ax-conversation-message-list .scroll-to-bottom-leave{animation:none}}.reaction-picker-popup{width:max-content;min-width:calc(var(--spacing, .25rem) * 0);overflow:hidden;border-radius:.65rem;background-color:rgba(var(--ax-sys-color-lightest-surface));max-width:min(260px,92vw)}.reaction-picker-header{display:flex;min-height:calc(var(--spacing, .25rem) * 0);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2);border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:rgba(var(--ax-sys-color-border-light-surface));padding-block:.45rem;padding-inline-start:.7rem;padding-inline-end:calc(var(--spacing, .25rem) * 2)}.picker-title{font-size:.8125rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em);color:rgba(var(--ax-sys-color-on-surface));opacity:85%}.picker-close{display:flex;height:1.6rem;width:1.6rem;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;--tw-border-style: none;border-style:none;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:.95rem;color:rgba(var(--ax-sys-color-on-surface),.55);transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function)}.picker-close:hover{background-color:rgba(var(--ax-sys-color-danger-lightest-surface));color:rgba(var(--ax-sys-color-danger-500))}.picker-close:focus-visible,.reaction-picker-emoji:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px;outline-offset:2px;outline-color:rgba(var(--ax-sys-color-primary-surface))}.reaction-picker-emojis{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.2rem;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:.45rem;padding-bottom:calc(var(--spacing, .25rem) * 2)}.reaction-picker-emoji{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 8);cursor:pointer;border-radius:.45rem;border-style:var(--tw-border-style);border-width:1px;border-color:transparent;background-color:transparent;padding:calc(var(--spacing, .25rem) * 0);font-size:1.15rem;--tw-leading: 1;line-height:1;transition:all var(--ax-sys-transition-duration) var(--ax-sys-transition-timing-function);font-family:\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\",\"Apple Color Emoji\",Twemoji Mozilla,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.reaction-picker-emoji:hover{background-color:rgba(var(--ax-sys-color-lighter-surface))}.reaction-picker-emoji-active{background-color:rgba(var(--ax-sys-color-surface))}.reaction-picker-emoji-active:hover{background:rgba(var(--ax-sys-color-primary-500),.25)}}@property --tw-outline-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@property --tw-translate-x{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-y{syntax: \"*\"; inherits: false; initial-value: 0;}@property --tw-translate-z{syntax: \"*\"; inherits: false; initial-value: 0;}@keyframes spin{to{transform:rotate(360deg)}}@keyframes fadeInUp{0%{transform:translate3d(0,100%,0);opacity:0}}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-outline-style: solid;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial;--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
8795
9018
  }], ctorParameters: () => [], propDecorators: { reactionPopover: [{ type: i0.ViewChild, args: ['reactionPopover', { isSignal: true }] }], messageListRef: [{ type: i0.ViewChild, args: ['messageList', { isSignal: true }] }], messagesContainerRef: [{ type: i0.ViewChild, args: ['messagesContainer', { isSignal: true }] }], messageAction: [{ type: i0.Output, args: ["messageAction"] }] } });
8796
9019
 
8797
9020
  /**
@@ -8888,9 +9111,21 @@ class AXConversationItemComponent {
8888
9111
  ...(ngDevMode ? [{ debugName: "itemClasses" }] : /* istanbul ignore next */ []));
8889
9112
  /** Typing indicator text - delegate to utils */
8890
9113
  this.typingText = computed(() => {
8891
- return AXConversationMessageUtilsService.getTypingText(this.liveConversation());
9114
+ this.conversationService.typingRevision();
9115
+ const conv = this.liveConversation();
9116
+ return AXConversationMessageUtilsService.getTypingText(conv, this.conversationService.getActiveTypingUserIds(conv.id));
8892
9117
  }, /* @ts-ignore */
8893
9118
  ...(ngDevMode ? [{ debugName: "typingText" }] : /* istanbul ignore next */ []));
9119
+ this.isTyping = computed(() => {
9120
+ this.conversationService.typingRevision();
9121
+ return this.conversationService.isAnyoneTyping(this.liveConversation().id);
9122
+ }, /* @ts-ignore */
9123
+ ...(ngDevMode ? [{ debugName: "isTyping" }] : /* istanbul ignore next */ []));
9124
+ this.roomPreferences = computed(() => {
9125
+ const conv = this.liveConversation();
9126
+ return this.conversationService.getRoomPreferences(conv.id);
9127
+ }, /* @ts-ignore */
9128
+ ...(ngDevMode ? [{ debugName: "roomPreferences" }] : /* istanbul ignore next */ []));
8894
9129
  /** Last message preview - delegate to utils */
8895
9130
  this.lastMessagePreview = computed(() => {
8896
9131
  const lastMessage = this.liveConversation().lastMessage;
@@ -8966,7 +9201,7 @@ class AXConversationItemComponent {
8966
9201
  }
8967
9202
  }
8968
9203
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8969
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationItemComponent, isStandalone: true, selector: "ax-conversation-item", inputs: { conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: " <div\n [class]=\"itemClasses()\"\n [id]=\"'conversation-item-' + conversation().id\"\n (click)=\"handleClick()\"\n (keydown.enter)=\"handleClick()\"\n (keydown.space)=\"handleClick()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Conversation with ' + conversation().title\"\n >\n <!-- Avatar -->\n <div class=\"item-avatar\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"liveConversation()\"\n [size]=\"48\"\n [showStatus]=\"conversation().type === 'private'\"\n />\n </div>\n\n <!-- Content -->\n <div class=\"item-content\">\n <div class=\"item-header\">\n <span class=\"item-title\">\n <p class=\"item-title-text\">{{ liveConversation().title }}</p>\n @if (liveConversation().settings?.notifications === false) {\n <i class=\"fa-light fa-bell-slash mute-icon\"></i>\n }\n @if (liveConversation()?.blocked) {\n <i class=\"fa-ban fa-light block-icon\"></i>\n }\n </span>\n @if (liveConversation().lastMessageAt) {\n <span class=\"item-time\">{{ liveConversation().lastMessageAt | format: 'timeleft' | async }}</span>\n }\n </div>\n\n <div class=\"item-description\">\n @if (liveConversation().status.isTyping) {\n <span class=\"typing-indicator\">{{ typingText() }}</span>\n } @else if (liveConversation().lastMessage) {\n @if (lastMessagePreview(); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n @if (preview.type === 'text') {\n {{ preview.value }}\n } @else {\n {{ getPreviewTypeKey(preview.type) | translate | async }}\n }\n </span>\n }\n } @else {\n <span class=\"last-message no-message\">{{ '@acorex:chat.status.no-messages' | translate | async }}</span>\n }\n <!-- Badge -->\n @if (liveConversation().unreadCount > 0) {\n <div class=\"item-badge\">\n <ax-badge [text]=\"liveConversation().unreadCount.toString()\" [color]=\"'primary'\" />\n </div>\n }\n <!-- Pin Icon -->\n @if (liveConversation().pinned) {\n <i class=\"fa-light fa-thumbtack pin-icon\"></i>\n }\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Conversation Actions -->\n <ax-context-menu\n [target]=\"'#conversation-item-' + conversation().id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleContextMenuOpening($event)\"\n (onClose)=\"contextMenuOpen.set(false)\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n", styles: ["@layer properties;@layer components{ax-conversation-item{display:block}ax-conversation-item .conversation-item{margin:calc(var(--spacing, .25rem) * 1.5);display:flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1.5);transition:background .2s}ax-conversation-item .conversation-item:focus-visible,ax-conversation-item .conversation-item:hover{background-color:rgba(var(--ax-sys-color-light-surface));--tw-outline-style: none;outline-style:none}ax-conversation-item .conversation-item-active{background-color:rgba(var(--ax-sys-color-primary-lightest-surface));color:rgba(var(--ax-sys-color-on-primary-lightest-surface))}ax-conversation-item .conversation-item-active:hover{background-color:rgba(var(--ax-sys-color-primary-lighter-surface))}ax-conversation-item .conversation-item-context-active{background-color:rgba(var(--ax-sys-color-light-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.35)}ax-conversation-item .conversation-item-active.conversation-item-context-active{background-color:rgba(var(--ax-sys-color-primary-lighter-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-item .item-avatar{flex-shrink:0}ax-conversation-item .item-content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 1);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-item .item-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-item .item-title{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-item .item-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-time{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:70%}ax-conversation-item .item-description{display:flex;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 2);font-size:.8125rem;opacity:70%}ax-conversation-item .typing-indicator{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));font-style:italic}ax-conversation-item .last-message{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-badge{flex-shrink:0}ax-conversation-item .mute-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-warning-500));opacity:60%}ax-conversation-item .block-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-danger-500));opacity:60%}ax-conversation-item .pin-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-primary-surface));opacity:60%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "component", type: AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "closeOnRouteChange", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
9204
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXConversationItemComponent, isStandalone: true, selector: "ax-conversation-item", inputs: { conversation: { classPropertyName: "conversation", publicName: "conversation", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: " <div\n [class]=\"itemClasses()\"\n [id]=\"'conversation-item-' + conversation().id\"\n (click)=\"handleClick()\"\n (keydown.enter)=\"handleClick()\"\n (keydown.space)=\"handleClick()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Conversation with ' + conversation().title\"\n >\n <!-- Avatar -->\n <div class=\"item-avatar\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"liveConversation()\"\n [size]=\"48\"\n [showStatus]=\"conversation().type === 'private'\"\n />\n </div>\n\n <!-- Content -->\n <div class=\"item-content\">\n <div class=\"item-header\">\n <span class=\"item-title\">\n <p class=\"item-title-text\">{{ liveConversation().title }}</p>\n @if (roomPreferences().notifications === false) {\n <i class=\"fa-light fa-bell-slash mute-icon\"></i>\n }\n @if (liveConversation()?.blocked) {\n <i class=\"fa-ban fa-light block-icon\"></i>\n }\n </span>\n @if (liveConversation().lastMessageAt) {\n <span class=\"item-time\">{{ liveConversation().lastMessageAt | format: 'timeleft' | async }}</span>\n }\n </div>\n\n <div class=\"item-description\">\n @if (isTyping()) {\n <span class=\"typing-indicator\">{{ typingText() }}</span>\n } @else if (liveConversation().lastMessage) {\n @if (lastMessagePreview(); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n @if (preview.type === 'text') {\n {{ preview.value }}\n } @else {\n {{ getPreviewTypeKey(preview.type) | translate | async }}\n }\n </span>\n }\n } @else {\n <span class=\"last-message no-message\">{{ '@acorex:chat.status.no-messages' | translate | async }}</span>\n }\n <!-- Badge -->\n @if (liveConversation().unreadCount > 0) {\n <div class=\"item-badge\">\n <ax-badge [text]=\"liveConversation().unreadCount.toString()\" [color]=\"'primary'\" />\n </div>\n }\n <!-- Pin Icon -->\n @if (liveConversation().pinned) {\n <i class=\"fa-light fa-thumbtack pin-icon\"></i>\n }\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Conversation Actions -->\n <ax-context-menu\n [target]=\"'#conversation-item-' + conversation().id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleContextMenuOpening($event)\"\n (onClose)=\"contextMenuOpen.set(false)\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n", styles: ["@layer properties;@layer components{ax-conversation-item{display:block}ax-conversation-item .conversation-item{margin:calc(var(--spacing, .25rem) * 1.5);display:flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1.5);transition:background .2s}ax-conversation-item .conversation-item:focus-visible,ax-conversation-item .conversation-item:hover{background-color:rgba(var(--ax-sys-color-light-surface));--tw-outline-style: none;outline-style:none}ax-conversation-item .conversation-item-active{background-color:rgba(var(--ax-sys-color-primary-lightest-surface));color:rgba(var(--ax-sys-color-on-primary-lightest-surface))}ax-conversation-item .conversation-item-active:hover{background-color:rgba(var(--ax-sys-color-primary-lighter-surface))}ax-conversation-item .conversation-item-context-active{background-color:rgba(var(--ax-sys-color-light-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.35)}ax-conversation-item .conversation-item-active.conversation-item-context-active{background-color:rgba(var(--ax-sys-color-primary-lighter-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-item .item-avatar{flex-shrink:0}ax-conversation-item .item-content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 1);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-item .item-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-item .item-title{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-item .item-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-time{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:70%}ax-conversation-item .item-description{display:flex;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 2);font-size:.8125rem;opacity:70%}ax-conversation-item .typing-indicator{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));font-style:italic}ax-conversation-item .last-message{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-badge{flex-shrink:0}ax-conversation-item .mute-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-warning-500));opacity:60%}ax-conversation-item .block-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-danger-500));opacity:60%}ax-conversation-item .pin-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-primary-surface));opacity:60%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "component", type: AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "closeOnRouteChange", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXConversationAvatarComponent, selector: "ax-conversation-avatar", inputs: ["kind", "userId", "conversation", "message", "size", "showStatus", "name", "avatar", "icon"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
8970
9205
  }
8971
9206
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXConversationItemComponent, decorators: [{
8972
9207
  type: Component,
@@ -8979,7 +9214,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
8979
9214
  AXDateTimeModule,
8980
9215
  AXTranslationModule,
8981
9216
  AXConversationAvatarComponent,
8982
- ], template: " <div\n [class]=\"itemClasses()\"\n [id]=\"'conversation-item-' + conversation().id\"\n (click)=\"handleClick()\"\n (keydown.enter)=\"handleClick()\"\n (keydown.space)=\"handleClick()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Conversation with ' + conversation().title\"\n >\n <!-- Avatar -->\n <div class=\"item-avatar\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"liveConversation()\"\n [size]=\"48\"\n [showStatus]=\"conversation().type === 'private'\"\n />\n </div>\n\n <!-- Content -->\n <div class=\"item-content\">\n <div class=\"item-header\">\n <span class=\"item-title\">\n <p class=\"item-title-text\">{{ liveConversation().title }}</p>\n @if (liveConversation().settings?.notifications === false) {\n <i class=\"fa-light fa-bell-slash mute-icon\"></i>\n }\n @if (liveConversation()?.blocked) {\n <i class=\"fa-ban fa-light block-icon\"></i>\n }\n </span>\n @if (liveConversation().lastMessageAt) {\n <span class=\"item-time\">{{ liveConversation().lastMessageAt | format: 'timeleft' | async }}</span>\n }\n </div>\n\n <div class=\"item-description\">\n @if (liveConversation().status.isTyping) {\n <span class=\"typing-indicator\">{{ typingText() }}</span>\n } @else if (liveConversation().lastMessage) {\n @if (lastMessagePreview(); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n @if (preview.type === 'text') {\n {{ preview.value }}\n } @else {\n {{ getPreviewTypeKey(preview.type) | translate | async }}\n }\n </span>\n }\n } @else {\n <span class=\"last-message no-message\">{{ '@acorex:chat.status.no-messages' | translate | async }}</span>\n }\n <!-- Badge -->\n @if (liveConversation().unreadCount > 0) {\n <div class=\"item-badge\">\n <ax-badge [text]=\"liveConversation().unreadCount.toString()\" [color]=\"'primary'\" />\n </div>\n }\n <!-- Pin Icon -->\n @if (liveConversation().pinned) {\n <i class=\"fa-light fa-thumbtack pin-icon\"></i>\n }\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Conversation Actions -->\n <ax-context-menu\n [target]=\"'#conversation-item-' + conversation().id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleContextMenuOpening($event)\"\n (onClose)=\"contextMenuOpen.set(false)\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n", styles: ["@layer properties;@layer components{ax-conversation-item{display:block}ax-conversation-item .conversation-item{margin:calc(var(--spacing, .25rem) * 1.5);display:flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1.5);transition:background .2s}ax-conversation-item .conversation-item:focus-visible,ax-conversation-item .conversation-item:hover{background-color:rgba(var(--ax-sys-color-light-surface));--tw-outline-style: none;outline-style:none}ax-conversation-item .conversation-item-active{background-color:rgba(var(--ax-sys-color-primary-lightest-surface));color:rgba(var(--ax-sys-color-on-primary-lightest-surface))}ax-conversation-item .conversation-item-active:hover{background-color:rgba(var(--ax-sys-color-primary-lighter-surface))}ax-conversation-item .conversation-item-context-active{background-color:rgba(var(--ax-sys-color-light-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.35)}ax-conversation-item .conversation-item-active.conversation-item-context-active{background-color:rgba(var(--ax-sys-color-primary-lighter-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-item .item-avatar{flex-shrink:0}ax-conversation-item .item-content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 1);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-item .item-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-item .item-title{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-item .item-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-time{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:70%}ax-conversation-item .item-description{display:flex;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 2);font-size:.8125rem;opacity:70%}ax-conversation-item .typing-indicator{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));font-style:italic}ax-conversation-item .last-message{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-badge{flex-shrink:0}ax-conversation-item .mute-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-warning-500));opacity:60%}ax-conversation-item .block-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-danger-500));opacity:60%}ax-conversation-item .pin-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-primary-surface));opacity:60%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
9217
+ ], template: " <div\n [class]=\"itemClasses()\"\n [id]=\"'conversation-item-' + conversation().id\"\n (click)=\"handleClick()\"\n (keydown.enter)=\"handleClick()\"\n (keydown.space)=\"handleClick()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Conversation with ' + conversation().title\"\n >\n <!-- Avatar -->\n <div class=\"item-avatar\">\n <ax-conversation-avatar\n kind=\"auto\"\n [conversation]=\"liveConversation()\"\n [size]=\"48\"\n [showStatus]=\"conversation().type === 'private'\"\n />\n </div>\n\n <!-- Content -->\n <div class=\"item-content\">\n <div class=\"item-header\">\n <span class=\"item-title\">\n <p class=\"item-title-text\">{{ liveConversation().title }}</p>\n @if (roomPreferences().notifications === false) {\n <i class=\"fa-light fa-bell-slash mute-icon\"></i>\n }\n @if (liveConversation()?.blocked) {\n <i class=\"fa-ban fa-light block-icon\"></i>\n }\n </span>\n @if (liveConversation().lastMessageAt) {\n <span class=\"item-time\">{{ liveConversation().lastMessageAt | format: 'timeleft' | async }}</span>\n }\n </div>\n\n <div class=\"item-description\">\n @if (isTyping()) {\n <span class=\"typing-indicator\">{{ typingText() }}</span>\n } @else if (liveConversation().lastMessage) {\n @if (lastMessagePreview(); as preview) {\n <span class=\"last-message\">\n @if (preview.type !== 'text') {\n <i [class]=\"preview.icon\"></i>\n }\n @if (preview.type === 'text') {\n {{ preview.value }}\n } @else {\n {{ getPreviewTypeKey(preview.type) | translate | async }}\n }\n </span>\n }\n } @else {\n <span class=\"last-message no-message\">{{ '@acorex:chat.status.no-messages' | translate | async }}</span>\n }\n <!-- Badge -->\n @if (liveConversation().unreadCount > 0) {\n <div class=\"item-badge\">\n <ax-badge [text]=\"liveConversation().unreadCount.toString()\" [color]=\"'primary'\" />\n </div>\n }\n <!-- Pin Icon -->\n @if (liveConversation().pinned) {\n <i class=\"fa-light fa-thumbtack pin-icon\"></i>\n }\n </div>\n </div>\n </div>\n\n <!-- Context Menu for Conversation Actions -->\n <ax-context-menu\n [target]=\"'#conversation-item-' + conversation().id\"\n [openOn]=\"'click'\"\n [closeOn]=\"'click'\"\n (onOpening)=\"handleContextMenuOpening($event)\"\n (onClose)=\"contextMenuOpen.set(false)\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n", styles: ["@layer properties;@layer components{ax-conversation-item{display:block}ax-conversation-item .conversation-item{margin:calc(var(--spacing, .25rem) * 1.5);display:flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);padding-inline:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1.5);transition:background .2s}ax-conversation-item .conversation-item:focus-visible,ax-conversation-item .conversation-item:hover{background-color:rgba(var(--ax-sys-color-light-surface));--tw-outline-style: none;outline-style:none}ax-conversation-item .conversation-item-active{background-color:rgba(var(--ax-sys-color-primary-lightest-surface));color:rgba(var(--ax-sys-color-on-primary-lightest-surface))}ax-conversation-item .conversation-item-active:hover{background-color:rgba(var(--ax-sys-color-primary-lighter-surface))}ax-conversation-item .conversation-item-context-active{background-color:rgba(var(--ax-sys-color-light-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.35)}ax-conversation-item .conversation-item-active.conversation-item-context-active{background-color:rgba(var(--ax-sys-color-primary-lighter-surface));box-shadow:inset 0 0 0 1px rgba(var(--ax-sys-color-primary-500),.45)}ax-conversation-item .item-avatar{flex-shrink:0}ax-conversation-item .item-content{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 1);--tw-leading: 1.1rem;line-height:1.1rem}ax-conversation-item .item-header{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 1)}ax-conversation-item .item-title{display:flex;min-width:calc(var(--spacing, .25rem) * 0);flex:1;align-items:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600)}ax-conversation-item .item-title-text{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-time{flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);opacity:70%}ax-conversation-item .item-description{display:flex;min-width:calc(var(--spacing, .25rem) * 0);align-items:center;gap:calc(var(--spacing, .25rem) * 2);font-size:.8125rem;opacity:70%}ax-conversation-item .typing-indicator{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:rgba(var(--ax-sys-color-primary-surface));font-style:italic}ax-conversation-item .last-message{min-width:calc(var(--spacing, .25rem) * 0);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ax-conversation-item .item-badge{flex-shrink:0}ax-conversation-item .mute-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-warning-500));opacity:60%}ax-conversation-item .block-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-danger-500));opacity:60%}ax-conversation-item .pin-icon{margin-inline-start:calc(var(--spacing, .25rem) * 1.5);flex-shrink:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-primary-surface));opacity:60%}}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading: initial;--tw-font-weight: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n"] }]
8983
9218
  }], propDecorators: { conversation: [{ type: i0.Input, args: [{ isSignal: true, alias: "conversation", required: true }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
8984
9219
 
8985
9220
  /**
@@ -9464,7 +9699,11 @@ var newConversationDialog_component = /*#__PURE__*/Object.freeze({
9464
9699
 
9465
9700
  /**
9466
9701
  * Participant Model
9467
- * Represents a user/member in a conversation
9702
+ * Membership in a conversation (identity fields are snapshots; live presence is on the user store).
9703
+ */
9704
+
9705
+ /**
9706
+ * User presence — global per-user live state (not room-scoped).
9468
9707
  */
9469
9708
 
9470
9709
  function formatFileSize(bytes) {
@@ -12629,13 +12868,21 @@ const AX_CONVERSATION_INFO_BAR_SEARCH_ACTION = {
12629
12868
  */
12630
12869
  const AX_CONVERSATION_INFO_BAR_MUTE_ACTION = {
12631
12870
  id: 'mute',
12632
- label: (context) => context.conversation.settings.notifications ? '@acorex:chat.actions.mute' : '@acorex:chat.actions.unmute',
12633
- icon: (context) => (context.conversation.settings.notifications ? 'fa-light fa-bell-slash' : 'fa-light fa-bell'),
12871
+ label: (context) => {
12872
+ const notifications = inject(AXConversationService).getRoomPreferences(context.conversation.id).notifications;
12873
+ return notifications ? '@acorex:chat.actions.mute' : '@acorex:chat.actions.unmute';
12874
+ },
12875
+ icon: (context) => {
12876
+ const notifications = inject(AXConversationService).getRoomPreferences(context.conversation.id).notifications;
12877
+ return notifications ? 'fa-light fa-bell-slash' : 'fa-light fa-bell';
12878
+ },
12634
12879
  location: 'menu',
12635
12880
  priority: 90,
12636
12881
  handler: async (context) => {
12637
- await inject(AXConversationService).updateConversationSettings(context.conversation.id, {
12638
- notifications: !context.conversation.settings.notifications,
12882
+ const service = inject(AXConversationService);
12883
+ const currentNotifications = service.getRoomPreferences(context.conversation.id).notifications;
12884
+ await service.updateConversationSettings(context.conversation.id, {
12885
+ notifications: !currentNotifications,
12639
12886
  });
12640
12887
  },
12641
12888
  };
@@ -12916,9 +13163,13 @@ class AXConversationImageAttachmentComponent {
12916
13163
  this.displayUrl = computed(() => pickDisplayMediaUrl(this.resolvedUrl(), this.item().thumbnailUrl, this.item().url), /* @ts-ignore */
12917
13164
  ...(ngDevMode ? [{ debugName: "displayUrl" }] : /* istanbul ignore next */ []));
12918
13165
  effect(() => {
12919
- this.displayUrl();
12920
- this.item().mediaId;
12921
- untracked(() => this.ready.set(false));
13166
+ const url = this.displayUrl();
13167
+ const mediaId = this.item().mediaId;
13168
+ untracked(() => {
13169
+ if (!url) {
13170
+ this.ready.set(false);
13171
+ }
13172
+ });
12922
13173
  });
12923
13174
  }
12924
13175
  onImageLoad() {
@@ -14132,9 +14383,12 @@ const AX_CONVERSATION_MESSAGE_FORWARD_ACTION = {
14132
14383
  icon: 'fa-light fa-share',
14133
14384
  priority: 75,
14134
14385
  visible: () => true,
14135
- enabled: () => true,
14386
+ enabled: () => !inject(AXConversationService).isForwardingMessage(),
14136
14387
  handler: async (context) => {
14137
14388
  const conversationService = inject(AXConversationService);
14389
+ if (conversationService.isForwardingMessage()) {
14390
+ return;
14391
+ }
14138
14392
  const { AXConversationForwardMessageDialogComponent } = await Promise.resolve().then(function () { return forwardMessageDialog_component; });
14139
14393
  await conversationService.popupService.open(AXConversationForwardMessageDialogComponent, {
14140
14394
  title: translateSync('@acorex:chat.dialog.forward-message.title'),
@@ -14337,15 +14591,20 @@ var fallbackRenderer_plugin = /*#__PURE__*/Object.freeze({
14337
14591
  */
14338
14592
  const AX_CONVERSATION_ITEM_MUTE_ACTION = {
14339
14593
  id: 'mute',
14340
- label: (context) => context.conversation.settings?.notifications === false
14341
- ? '@acorex:chat.actions.unmute'
14342
- : '@acorex:chat.actions.mute',
14343
- icon: (context) => context.conversation.settings?.notifications === false ? 'fa-light fa-bell-slash' : 'fa-light fa-bell',
14594
+ label: (context) => {
14595
+ const notifications = inject(AXConversationService).getRoomPreferences(context.conversation.id).notifications;
14596
+ return notifications === false ? '@acorex:chat.actions.unmute' : '@acorex:chat.actions.mute';
14597
+ },
14598
+ icon: (context) => {
14599
+ const notifications = inject(AXConversationService).getRoomPreferences(context.conversation.id).notifications;
14600
+ return notifications === false ? 'fa-light fa-bell-slash' : 'fa-light fa-bell';
14601
+ },
14344
14602
  tooltip: '@acorex:chat.tooltips.toggle-notifications',
14345
14603
  priority: 100,
14346
14604
  handler: async (context) => {
14347
- const currentNotifications = context.conversation.settings?.notifications ?? true;
14348
- await inject(AXConversationService).updateConversationSettings(context.conversation.id, {
14605
+ const service = inject(AXConversationService);
14606
+ const currentNotifications = service.getRoomPreferences(context.conversation.id).notifications;
14607
+ await service.updateConversationSettings(context.conversation.id, {
14349
14608
  notifications: !currentNotifications,
14350
14609
  });
14351
14610
  },
@@ -14546,16 +14805,17 @@ class AXConversationDefaultConversationAvatarComponent {
14546
14805
  return resolveConversationPeerUserId(conversation, this.currentUserId());
14547
14806
  }, /* @ts-ignore */
14548
14807
  ...(ngDevMode ? [{ debugName: "peerUserId" }] : /* istanbul ignore next */ []));
14549
- this.useUserAvatar = computed(() => {
14550
- const component = this.userAvatarComponent;
14551
- const peerId = this.peerUserId();
14552
- return component && peerId ? component : null;
14553
- }, /* @ts-ignore */
14808
+ this.useUserAvatar = computed(() => this.userAvatarComponent ?? null, /* @ts-ignore */
14554
14809
  ...(ngDevMode ? [{ debugName: "useUserAvatar" }] : /* istanbul ignore next */ []));
14555
14810
  this.userAvatarInputs = computed(() => {
14556
- const userId = this.peerUserId() ?? '';
14557
14811
  const conversation = this.conversation();
14558
- const resolved = resolveUserAvatarDisplay(userId, conversation);
14812
+ const peerId = this.peerUserId();
14813
+ const userId = peerId ?? conversation?.id ?? '';
14814
+ const resolved = peerId && conversation
14815
+ ? resolveUserAvatarDisplay(peerId, conversation)
14816
+ : conversation
14817
+ ? resolveConversationAvatarDisplay(conversation, this.currentUserId())
14818
+ : { name: '?', avatar: undefined, icon: undefined };
14559
14819
  return {
14560
14820
  userId,
14561
14821
  size: this.size(),
@@ -15013,5 +15273,5 @@ function getErrorMessage(code, params) {
15013
15273
  * Generated bundle index. Do not edit.
15014
15274
  */
15015
15275
 
15016
- export { AXConversationApi, AXConversationApiLoggerService, AXConversationAudioAttachmentComponent, AXConversationAudioFileTypeProvider, AXConversationAudioPickerComponent, AXConversationAudioRendererComponent, AXConversationAvatarComponent, AXConversationAvatarPickerComponent, AXConversationBaseRegistry, AXConversationComposerActionRegistry, AXConversationComposerComponent, AXConversationComposerFileTypesProvider, AXConversationComposerGenerationStateService, AXConversationComposerPopupComponent, AXConversationComposerService, AXConversationComposerTabRegistry, AXConversationContainerComponent, AXConversationContainerDirective, AXConversationDateUtilsService, AXConversationEmojiTabComponent, AXConversationErrorHandlerService, AXConversationFallbackRendererComponent, AXConversationFileAttachmentComponent, AXConversationFileFileTypeProvider, AXConversationFilePickerComponent, AXConversationFileRendererComponent, AXConversationForwardMessageDialogComponent, AXConversationImageAttachmentComponent, AXConversationImageFileTypeProvider, AXConversationImagePickerComponent, AXConversationImageRendererComponent, AXConversationInfiniteScrollDirective, AXConversationInfoBarActionRegistry, AXConversationInfoBarComponent, AXConversationInfoBarSearchComponent, AXConversationInfoBarService, AXConversationItemActionRegistry, AXConversationLocationPickerComponent, AXConversationLocationRendererComponent, AXConversationMediaPlaybackInfoBarBannerComponent, AXConversationMessageActionRegistry, AXConversationMessageApi, AXConversationMessageListComponent, AXConversationMessageListNoActiveDefaultComponent, AXConversationMessageListService, AXConversationMessageRendererCopyHostComponent, AXConversationMessageRendererRegistry, AXConversationMessageRendererStateComponent, AXConversationMessageUtilsService, AXConversationModule, AXConversationNewDialogComponent, AXConversationPickerCaptionComponent, AXConversationPickerEmptyComponent, AXConversationPickerFooterComponent, AXConversationPickerHeaderComponent, AXConversationPickerShellComponent, AXConversationPickerToolbarComponent, AXConversationRealtimeApi, AXConversationRegistryComponentOutletComponent, AXConversationRegistryService, AXConversationService, AXConversationSidebarComponent, AXConversationSidebarService, AXConversationStickerRendererComponent, AXConversationStickerTabComponent, AXConversationSystemRendererComponent, AXConversationTabRegistry, AXConversationTextRendererComponent, AXConversationUserApi, AXConversationVideoAttachmentComponent, AXConversationVideoFileTypeProvider, AXConversationVideoPickerComponent, AXConversationVideoRendererComponent, AXConversationVoiceFileTypeProvider, AXConversationVoiceRecorderComponent, AXConversationVoiceRendererComponent, AX_CONVERSATION_AUDIO_CATALOG, AX_CONVERSATION_AUDIO_PRESENTATION, AX_CONVERSATION_AUDIO_RENDERER, AX_CONVERSATION_BUILTIN_COMPOSER_TABS, AX_CONVERSATION_COMPOSER_AUDIO_ACTION, AX_CONVERSATION_COMPOSER_EMOJI_ACTION, AX_CONVERSATION_COMPOSER_EMOJI_TAB, AX_CONVERSATION_COMPOSER_FILE_ACTION, AX_CONVERSATION_COMPOSER_IMAGE_ACTION, AX_CONVERSATION_COMPOSER_LOCATION_ACTION, AX_CONVERSATION_COMPOSER_STICKER_TAB, AX_CONVERSATION_COMPOSER_VIDEO_ACTION, AX_CONVERSATION_COMPOSER_VOICE_RECORDING_ACTION, AX_CONVERSATION_CONFIG, AX_CONVERSATION_CONNECTION_ERRORS, AX_CONVERSATION_CONVERSATION_AVATAR_COMPONENT, AX_CONVERSATION_DEFAULT_COMPOSER_ACTIONS, AX_CONVERSATION_DEFAULT_COMPOSER_TABS, AX_CONVERSATION_DEFAULT_CONVERSATION_ITEM_ACTIONS, AX_CONVERSATION_DEFAULT_CONVERSATION_TABS, AX_CONVERSATION_DEFAULT_GROUP_ICON, AX_CONVERSATION_DEFAULT_INFO_BAR_ACTIONS, AX_CONVERSATION_DEFAULT_MESSAGE_ACTIONS, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_BACKGROUND, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_BACKGROUND_PRESET_ID, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_THEME_BACKGROUND, AX_CONVERSATION_DEFAULT_MESSAGE_RENDERERS, AX_CONVERSATION_DEFAULT_USER_ICON, AX_CONVERSATION_ERRORS, AX_CONVERSATION_ERROR_HANDLER_CONFIG, AX_CONVERSATION_ERROR_MESSAGES, AX_CONVERSATION_FALLBACK_RENDERER, AX_CONVERSATION_FILE_CATALOG, AX_CONVERSATION_FILE_ERRORS, AX_CONVERSATION_FILE_PRESENTATION, AX_CONVERSATION_FILE_RENDERER, AX_CONVERSATION_FILE_TYPES_READY, AX_CONVERSATION_IMAGE_CATALOG, AX_CONVERSATION_IMAGE_PRESENTATION, AX_CONVERSATION_IMAGE_RENDERER, AX_CONVERSATION_INFO_BAR_ARCHIVE_ACTION, AX_CONVERSATION_INFO_BAR_BLOCK_ACTION, AX_CONVERSATION_INFO_BAR_DELETE_ACTION, AX_CONVERSATION_INFO_BAR_DIVIDER, AX_CONVERSATION_INFO_BAR_MUTE_ACTION, AX_CONVERSATION_INFO_BAR_SEARCH_ACTION, AX_CONVERSATION_ITEM_BLOCK_ACTION, AX_CONVERSATION_ITEM_DELETE_ACTION, AX_CONVERSATION_ITEM_DIVIDER, AX_CONVERSATION_ITEM_MARK_READ_ACTION, AX_CONVERSATION_ITEM_MUTE_ACTION, AX_CONVERSATION_ITEM_PIN_ACTION, AX_CONVERSATION_LOCATION_ERRORS, AX_CONVERSATION_LOCATION_RENDERER, AX_CONVERSATION_MESSAGE_DELETE_ACTION, AX_CONVERSATION_MESSAGE_EDIT_ACTION, AX_CONVERSATION_MESSAGE_ERRORS, AX_CONVERSATION_MESSAGE_FORWARD_ACTION, AX_CONVERSATION_MESSAGE_LIST_BACKGROUND_PRESETS, AX_CONVERSATION_MESSAGE_REPLY_ACTION, AX_CONVERSATION_MESSAGE_TYPE_FILE_TYPE, AX_CONVERSATION_PEER_AVATAR_TYPES, AX_CONVERSATION_REGISTRY_CONFIG, AX_CONVERSATION_STICKER_API_KEY, AX_CONVERSATION_STICKER_RENDERER, AX_CONVERSATION_SYSTEM_RENDERER, AX_CONVERSATION_TAB_ALL, AX_CONVERSATION_TAB_ARCHIVED, AX_CONVERSATION_TAB_BOT, AX_CONVERSATION_TAB_CHANNELS, AX_CONVERSATION_TAB_GROUPS, AX_CONVERSATION_TAB_PRIVATE, AX_CONVERSATION_TAB_UNREAD, AX_CONVERSATION_TEXT_RENDERER, AX_CONVERSATION_URL_ERRORS, AX_CONVERSATION_USER_AVATAR_COMPONENT, AX_CONVERSATION_USER_ERRORS, AX_CONVERSATION_VIDEO_CATALOG, AX_CONVERSATION_VIDEO_PRESENTATION, AX_CONVERSATION_VIDEO_RENDERER, AX_CONVERSATION_VOICE_CATALOG, AX_CONVERSATION_VOICE_PRESENTATION, AX_CONVERSATION_VOICE_RENDERER, AX_DEFAULT_CONVERSATION_CONFIG, abortPickerUploads, applyAudioLocalPreview, applyFileLocalPreview, applyLocalPreview, applyVideoLocalPreview, applyVoiceLocalPreview, audioItemFromUpload, bindMediaRendererContentState, buildMediaGalleryTiles, canShowRendererContentError, cleanupPickerUploads, conversationAudioUtilities, conversationFileUtilities, conversationImageUtilities, conversationVideoUtilities, conversationVoiceUtilities, copyWithFileTypeFallback, createConversationAudioFileType, createConversationFileFileType, createConversationImageFileType, createConversationVideoFileType, createConversationVoiceFileType, createLocalPreviewUrl, createObjectUrl, createPickerDragHandlers, createResolvedMediaUrlSignal, deleteUploadedPickerMedia, dismissComposerPickerHost, ensureConversationFileCatalogRegistered, fetchConversationMediaPage, fileItemFromUpload, filterMessagesByMediaCategory, filterSupplementalInfoPanelMessages, findExistingPrivateConversation, formatDuration, formatErrorMessage, formatFileByteSize, formatFileSize, formatMediaDuration, formatPickerValidationMessage, getConversationMediaCategories, getConversationProfileFields, getErrorMessage, getMessageAudioItems, getMessageVideoItems, getPickerCancelUploadLabel, getPrivatePeerParticipant, hasRegistryComponent, inferFileExtensionHintFromMessage, isAttachmentListCategory, isComposerTabEnabled, isConversationReactionsEnabled, isGenericPrivateConversationTitle, isGridMediaCategory, isMessageDeliveryPending, isMessageListThemeBackground, isNonPersistableMediaUrl, isPickerItemReadyToSend, isSameMessageListBackground, isUploadAborted, limitFilesToCapacity, mediaCopyText, mergeAudioUploadResult, mergeFileUploadResult, mergeInfoPanelMessages, mergeUploadResult, mergeVideoUploadResult, mergeVoiceUploadResult, mergeWithDefaults, messageContainsLink, normalizeAudioPayload, normalizeFilePayload, normalizeImagePayload, normalizeMessageListBackgroundValue, normalizeVideoPayload, notifyMaxFilesCapacityExceeded, notifyPickerValidationErrors, openWithFileType, pickDisplayMediaUrl, pickerItemToMediaReference, pickerItemToUploadResult, provideConversation, provideConversationComposerFileTypes, provideConversationFileCatalog, reportMediaLoadError, resolveComposerMaxFiles, resolveConversationAvatarDisplay, resolveConversationComposerTabs, resolveConversationForViewer, resolveConversationMessageFileType, resolveConversationPeerParticipant, resolveConversationPeerUserId, resolveConversationTitleForViewer, resolveGalleryImageUrl, resolveImageDisplayUrl, resolveMessageListBackgroundRaw, resolveMessageListBackgroundStyle, resolveParticipantProfile, resolvePersistableMediaUrl, resolvePersistedThumbnailUrl, resolvePrivatePeerParticipant, resolvePrivatePeerUserId, resolveUserAvatarDisplay, resolveVideoThumbnailUrl, revokeObjectUrl, revokePickerBlobPreviews, sanitizeInput, shouldUseUserAvatarForConversation, syncPlaybackInfoBarBanner, toUploaderReference as toMediaItemUploaderReference, toUploaderReference$1 as toUploaderReference, uploadPickerFile, validateConversationId, validateEmail, validateLatitude, validateLongitude, validateMessagePayload, validateMessageText, validateMessageType, validateUrl, validateUserId, validateUserIds, videoItemFromUpload };
15276
+ export { AXConversationApi, AXConversationApiLoggerService, AXConversationAudioAttachmentComponent, AXConversationAudioFileTypeProvider, AXConversationAudioPickerComponent, AXConversationAudioRendererComponent, AXConversationAvatarComponent, AXConversationAvatarPickerComponent, AXConversationBaseRegistry, AXConversationComposerActionRegistry, AXConversationComposerComponent, AXConversationComposerFileTypesProvider, AXConversationComposerGenerationStateService, AXConversationComposerPopupComponent, AXConversationComposerService, AXConversationComposerTabRegistry, AXConversationContainerComponent, AXConversationContainerDirective, AXConversationDateUtilsService, AXConversationEmojiTabComponent, AXConversationErrorHandlerService, AXConversationFallbackRendererComponent, AXConversationFileAttachmentComponent, AXConversationFileFileTypeProvider, AXConversationFilePickerComponent, AXConversationFileRendererComponent, AXConversationForwardMessageDialogComponent, AXConversationImageAttachmentComponent, AXConversationImageFileTypeProvider, AXConversationImagePickerComponent, AXConversationImageRendererComponent, AXConversationInfiniteScrollDirective, AXConversationInfoBarActionRegistry, AXConversationInfoBarComponent, AXConversationInfoBarSearchComponent, AXConversationInfoBarService, AXConversationItemActionRegistry, AXConversationLocationPickerComponent, AXConversationLocationRendererComponent, AXConversationMediaPlaybackInfoBarBannerComponent, AXConversationMessageActionRegistry, AXConversationMessageApi, AXConversationMessageListComponent, AXConversationMessageListNoActiveDefaultComponent, AXConversationMessageListService, AXConversationMessageRendererCopyHostComponent, AXConversationMessageRendererRegistry, AXConversationMessageRendererStateComponent, AXConversationMessageUtilsService, AXConversationModule, AXConversationNewDialogComponent, AXConversationPickerCaptionComponent, AXConversationPickerEmptyComponent, AXConversationPickerFooterComponent, AXConversationPickerHeaderComponent, AXConversationPickerShellComponent, AXConversationPickerToolbarComponent, AXConversationRealtimeApi, AXConversationRegistryComponentOutletComponent, AXConversationRegistryService, AXConversationService, AXConversationSidebarComponent, AXConversationSidebarService, AXConversationStickerRendererComponent, AXConversationStickerTabComponent, AXConversationSystemRendererComponent, AXConversationTabRegistry, AXConversationTextRendererComponent, AXConversationUserApi, AXConversationVideoAttachmentComponent, AXConversationVideoFileTypeProvider, AXConversationVideoPickerComponent, AXConversationVideoRendererComponent, AXConversationVoiceFileTypeProvider, AXConversationVoiceRecorderComponent, AXConversationVoiceRendererComponent, AX_CONVERSATION_AUDIO_CATALOG, AX_CONVERSATION_AUDIO_PRESENTATION, AX_CONVERSATION_AUDIO_RENDERER, AX_CONVERSATION_BUILTIN_COMPOSER_TABS, AX_CONVERSATION_COMPOSER_AUDIO_ACTION, AX_CONVERSATION_COMPOSER_EMOJI_ACTION, AX_CONVERSATION_COMPOSER_EMOJI_TAB, AX_CONVERSATION_COMPOSER_FILE_ACTION, AX_CONVERSATION_COMPOSER_IMAGE_ACTION, AX_CONVERSATION_COMPOSER_LOCATION_ACTION, AX_CONVERSATION_COMPOSER_STICKER_TAB, AX_CONVERSATION_COMPOSER_VIDEO_ACTION, AX_CONVERSATION_COMPOSER_VOICE_RECORDING_ACTION, AX_CONVERSATION_CONFIG, AX_CONVERSATION_CONNECTION_ERRORS, AX_CONVERSATION_CONVERSATION_AVATAR_COMPONENT, AX_CONVERSATION_DEFAULT_COMPOSER_ACTIONS, AX_CONVERSATION_DEFAULT_COMPOSER_TABS, AX_CONVERSATION_DEFAULT_CONVERSATION_ITEM_ACTIONS, AX_CONVERSATION_DEFAULT_CONVERSATION_TABS, AX_CONVERSATION_DEFAULT_GROUP_ICON, AX_CONVERSATION_DEFAULT_INFO_BAR_ACTIONS, AX_CONVERSATION_DEFAULT_MESSAGE_ACTIONS, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_BACKGROUND, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_BACKGROUND_PRESET_ID, AX_CONVERSATION_DEFAULT_MESSAGE_LIST_THEME_BACKGROUND, AX_CONVERSATION_DEFAULT_MESSAGE_RENDERERS, AX_CONVERSATION_DEFAULT_ROOM_PREFERENCES, AX_CONVERSATION_DEFAULT_USER_ICON, AX_CONVERSATION_ERRORS, AX_CONVERSATION_ERROR_HANDLER_CONFIG, AX_CONVERSATION_ERROR_MESSAGES, AX_CONVERSATION_FALLBACK_RENDERER, AX_CONVERSATION_FILE_CATALOG, AX_CONVERSATION_FILE_ERRORS, AX_CONVERSATION_FILE_PRESENTATION, AX_CONVERSATION_FILE_RENDERER, AX_CONVERSATION_FILE_TYPES_READY, AX_CONVERSATION_IMAGE_CATALOG, AX_CONVERSATION_IMAGE_PRESENTATION, AX_CONVERSATION_IMAGE_RENDERER, AX_CONVERSATION_INFO_BAR_ARCHIVE_ACTION, AX_CONVERSATION_INFO_BAR_BLOCK_ACTION, AX_CONVERSATION_INFO_BAR_DELETE_ACTION, AX_CONVERSATION_INFO_BAR_DIVIDER, AX_CONVERSATION_INFO_BAR_MUTE_ACTION, AX_CONVERSATION_INFO_BAR_SEARCH_ACTION, AX_CONVERSATION_ITEM_BLOCK_ACTION, AX_CONVERSATION_ITEM_DELETE_ACTION, AX_CONVERSATION_ITEM_DIVIDER, AX_CONVERSATION_ITEM_MARK_READ_ACTION, AX_CONVERSATION_ITEM_MUTE_ACTION, AX_CONVERSATION_ITEM_PIN_ACTION, AX_CONVERSATION_LOCATION_ERRORS, AX_CONVERSATION_LOCATION_RENDERER, AX_CONVERSATION_MESSAGE_DELETE_ACTION, AX_CONVERSATION_MESSAGE_EDIT_ACTION, AX_CONVERSATION_MESSAGE_ERRORS, AX_CONVERSATION_MESSAGE_FORWARD_ACTION, AX_CONVERSATION_MESSAGE_LIST_BACKGROUND_PRESETS, AX_CONVERSATION_MESSAGE_REPLY_ACTION, AX_CONVERSATION_MESSAGE_TYPE_FILE_TYPE, AX_CONVERSATION_PEER_AVATAR_TYPES, AX_CONVERSATION_REGISTRY_CONFIG, AX_CONVERSATION_STICKER_API_KEY, AX_CONVERSATION_STICKER_RENDERER, AX_CONVERSATION_SYSTEM_RENDERER, AX_CONVERSATION_TAB_ALL, AX_CONVERSATION_TAB_ARCHIVED, AX_CONVERSATION_TAB_BOT, AX_CONVERSATION_TAB_CHANNELS, AX_CONVERSATION_TAB_GROUPS, AX_CONVERSATION_TAB_PRIVATE, AX_CONVERSATION_TAB_UNREAD, AX_CONVERSATION_TEXT_RENDERER, AX_CONVERSATION_URL_ERRORS, AX_CONVERSATION_USER_AVATAR_COMPONENT, AX_CONVERSATION_USER_ERRORS, AX_CONVERSATION_VIDEO_CATALOG, AX_CONVERSATION_VIDEO_PRESENTATION, AX_CONVERSATION_VIDEO_RENDERER, AX_CONVERSATION_VOICE_CATALOG, AX_CONVERSATION_VOICE_PRESENTATION, AX_CONVERSATION_VOICE_RENDERER, AX_DEFAULT_CONVERSATION_CONFIG, abortPickerUploads, applyAudioLocalPreview, applyFileLocalPreview, applyLocalPreview, applyVideoLocalPreview, applyVoiceLocalPreview, audioItemFromUpload, bindMediaRendererContentState, buildMediaGalleryTiles, canShowRendererContentError, cleanupPickerUploads, conversationAudioUtilities, conversationFileUtilities, conversationImageUtilities, conversationVideoUtilities, conversationVoiceUtilities, copyWithFileTypeFallback, createConversationAudioFileType, createConversationFileFileType, createConversationImageFileType, createConversationVideoFileType, createConversationVoiceFileType, createLocalPreviewUrl, createObjectUrl, createPickerDragHandlers, createResolvedMediaUrlSignal, deleteUploadedPickerMedia, dismissComposerPickerHost, ensureConversationFileCatalogRegistered, fetchConversationMediaPage, fileItemFromUpload, filterMessagesByMediaCategory, filterSupplementalInfoPanelMessages, findExistingPrivateConversation, formatDuration, formatErrorMessage, formatFileByteSize, formatFileSize, formatMediaDuration, formatPickerValidationMessage, getConversationMediaCategories, getConversationProfileFields, getErrorMessage, getMessageAudioItems, getMessageVideoItems, getPickerCancelUploadLabel, getPrivatePeerParticipant, hasRegistryComponent, inferFileExtensionHintFromMessage, isAttachmentListCategory, isComposerTabEnabled, isConversationReactionsEnabled, isGenericPrivateConversationTitle, isGridMediaCategory, isMessageDeliveryPending, isMessageListThemeBackground, isNonPersistableMediaUrl, isPickerItemReadyToSend, isSameMessageListBackground, isUploadAborted, limitFilesToCapacity, mediaCopyText, mergeAudioUploadResult, mergeFileUploadResult, mergeInfoPanelMessages, mergeUploadResult, mergeVideoUploadResult, mergeVoiceUploadResult, mergeWithDefaults, messageContainsLink, normalizeAudioPayload, normalizeFilePayload, normalizeImagePayload, normalizeMessageListBackgroundValue, normalizeVideoPayload, notifyMaxFilesCapacityExceeded, notifyPickerValidationErrors, openWithFileType, pickDisplayMediaUrl, pickerItemToMediaReference, pickerItemToUploadResult, provideConversation, provideConversationComposerFileTypes, provideConversationFileCatalog, reportMediaLoadError, resolveComposerMaxFiles, resolveConversationAvatarDisplay, resolveConversationComposerTabs, resolveConversationForViewer, resolveConversationMessageFileType, resolveConversationPeerParticipant, resolveConversationPeerUserId, resolveConversationTitleForViewer, resolveGalleryImageUrl, resolveImageDisplayUrl, resolveMessageListBackgroundRaw, resolveMessageListBackgroundStyle, resolveParticipantProfile, resolvePersistableMediaUrl, resolvePersistedThumbnailUrl, resolvePrivatePeerParticipant, resolvePrivatePeerUserId, resolveUserAvatarDisplay, resolveVideoThumbnailUrl, revokeObjectUrl, revokePickerBlobPreviews, sanitizeInput, shouldUseUserAvatarForConversation, syncPlaybackInfoBarBanner, toUploaderReference as toMediaItemUploaderReference, toUploaderReference$1 as toUploaderReference, uploadPickerFile, validateConversationId, validateEmail, validateLatitude, validateLongitude, validateMessagePayload, validateMessageText, validateMessageType, validateUrl, validateUserId, validateUserIds, videoItemFromUpload };
15017
15277
  //# sourceMappingURL=acorex-components-conversation.mjs.map