igniteui-webcomponents 6.3.0-alpha.0 → 6.3.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/components/accordion/accordion.js +1 -4
  2. package/components/accordion/accordion.js.map +1 -1
  3. package/components/button/themes/button/button.base.css.js +1 -1
  4. package/components/button/themes/button/button.base.css.js.map +1 -1
  5. package/components/button/themes/button/shared/button.common.css.js +1 -1
  6. package/components/button/themes/button/shared/button.common.css.js.map +1 -1
  7. package/components/button/themes/button/shared/button.fluent.css.js +1 -1
  8. package/components/button/themes/button/shared/button.fluent.css.js.map +1 -1
  9. package/components/button/themes/button/shared/button.indigo.css.js +1 -1
  10. package/components/button/themes/button/shared/button.indigo.css.js.map +1 -1
  11. package/components/button/themes/icon-button/icon-button.base.css.js +1 -1
  12. package/components/button/themes/icon-button/icon-button.base.css.js.map +1 -1
  13. package/components/button/themes/icon-button/shared/icon-button.bootstrap.css.js +1 -1
  14. package/components/button/themes/icon-button/shared/icon-button.bootstrap.css.js.map +1 -1
  15. package/components/button/themes/icon-button/shared/icon-button.fluent.css.js +1 -1
  16. package/components/button/themes/icon-button/shared/icon-button.fluent.css.js.map +1 -1
  17. package/components/button/themes/icon-button/shared/icon-button.indigo.css.js +1 -1
  18. package/components/button/themes/icon-button/shared/icon-button.indigo.css.js.map +1 -1
  19. package/components/button/themes/icon-button/shared/icon-button.material.css.js +1 -1
  20. package/components/button/themes/icon-button/shared/icon-button.material.css.js.map +1 -1
  21. package/components/button-group/themes/shared/button/button.bootstrap.css.js +1 -1
  22. package/components/button-group/themes/shared/button/button.bootstrap.css.js.map +1 -1
  23. package/components/button-group/themes/shared/button/button.common.css.js +1 -1
  24. package/components/button-group/themes/shared/button/button.common.css.js.map +1 -1
  25. package/components/button-group/themes/shared/button/button.indigo.css.js +1 -1
  26. package/components/button-group/themes/shared/button/button.indigo.css.js.map +1 -1
  27. package/components/calendar/days-view/days-view.js +1 -3
  28. package/components/calendar/days-view/days-view.js.map +1 -1
  29. package/components/calendar/months-view/months-view.js +1 -3
  30. package/components/calendar/months-view/months-view.js.map +1 -1
  31. package/components/calendar/themes/year-month-view.base.css.js +1 -1
  32. package/components/calendar/themes/year-month-view.base.css.js.map +1 -1
  33. package/components/calendar/years-view/years-view.js +1 -3
  34. package/components/calendar/years-view/years-view.js.map +1 -1
  35. package/components/carousel/carousel.js +0 -3
  36. package/components/carousel/carousel.js.map +1 -1
  37. package/components/chat/assets/file.png +0 -0
  38. package/components/chat/assets/json.png +0 -0
  39. package/components/chat/assets/link.png +0 -0
  40. package/components/chat/chat-input.d.ts +6 -22
  41. package/components/chat/chat-input.js +34 -163
  42. package/components/chat/chat-input.js.map +1 -1
  43. package/components/chat/chat-message-list.d.ts +5 -46
  44. package/components/chat/chat-message-list.js +16 -105
  45. package/components/chat/chat-message-list.js.map +1 -1
  46. package/components/chat/chat-message.d.ts +8 -18
  47. package/components/chat/chat-message.js +40 -29
  48. package/components/chat/chat-message.js.map +1 -1
  49. package/components/chat/chat-renderer.d.ts +14 -0
  50. package/components/chat/chat-renderer.js +39 -0
  51. package/components/chat/chat-renderer.js.map +1 -0
  52. package/components/chat/chat-state.d.ts +116 -21
  53. package/components/chat/chat-state.js +446 -75
  54. package/components/chat/chat-state.js.map +1 -1
  55. package/components/chat/chat.d.ts +27 -14
  56. package/components/chat/chat.js +145 -63
  57. package/components/chat/chat.js.map +1 -1
  58. package/components/chat/markdown-renderer.d.ts +72 -0
  59. package/components/chat/markdown-renderer.js +71 -0
  60. package/components/chat/markdown-renderer.js.map +1 -0
  61. package/components/chat/message-attachments.d.ts +0 -7
  62. package/components/chat/message-attachments.js +3 -81
  63. package/components/chat/message-attachments.js.map +1 -1
  64. package/components/chat/plain-text-renderer.d.ts +15 -0
  65. package/components/chat/plain-text-renderer.js +7 -0
  66. package/components/chat/plain-text-renderer.js.map +1 -0
  67. package/components/chat/themes/chat.base.css.js +1 -1
  68. package/components/chat/themes/chat.base.css.js.map +1 -1
  69. package/components/chat/themes/dark/chat.bootstrap.css.js +1 -1
  70. package/components/chat/themes/dark/chat.bootstrap.css.js.map +1 -1
  71. package/components/chat/themes/dark/chat.fluent.css.js +1 -1
  72. package/components/chat/themes/dark/chat.fluent.css.js.map +1 -1
  73. package/components/chat/themes/dark/chat.indigo.css.js +1 -1
  74. package/components/chat/themes/dark/chat.indigo.css.js.map +1 -1
  75. package/components/chat/themes/input.base.css.js +1 -1
  76. package/components/chat/themes/input.base.css.js.map +1 -1
  77. package/components/chat/themes/light/chat.bootstrap.css.js +1 -1
  78. package/components/chat/themes/light/chat.bootstrap.css.js.map +1 -1
  79. package/components/chat/themes/light/chat.fluent.css.js +1 -1
  80. package/components/chat/themes/light/chat.fluent.css.js.map +1 -1
  81. package/components/chat/themes/light/chat.indigo.css.js +1 -1
  82. package/components/chat/themes/light/chat.indigo.css.js.map +1 -1
  83. package/components/chat/themes/light/chat.shared.css.js +1 -1
  84. package/components/chat/themes/light/chat.shared.css.js.map +1 -1
  85. package/components/chat/themes/message-attachments.base.css.js +1 -1
  86. package/components/chat/themes/message-attachments.base.css.js.map +1 -1
  87. package/components/chat/themes/message-list.base.css.js +1 -1
  88. package/components/chat/themes/message-list.base.css.js.map +1 -1
  89. package/components/chat/themes/message.base.css.js +1 -1
  90. package/components/chat/themes/message.base.css.js.map +1 -1
  91. package/components/chat/themes/message.d.ts +2 -0
  92. package/components/chat/themes/message.js +28 -0
  93. package/components/chat/themes/message.js.map +1 -0
  94. package/components/chat/themes/shared/chat-message/chat-message.bootstrap.css.js +3 -0
  95. package/components/chat/themes/shared/chat-message/chat-message.bootstrap.css.js.map +1 -0
  96. package/components/chat/themes/shared/chat-message/chat-message.common.css.d.ts +1 -0
  97. package/components/chat/themes/shared/chat-message/chat-message.common.css.js +3 -0
  98. package/components/chat/themes/shared/chat-message/chat-message.common.css.js.map +1 -0
  99. package/components/chat/themes/shared/chat-message/chat-message.fluent.css.d.ts +1 -0
  100. package/components/chat/themes/shared/chat-message/chat-message.fluent.css.js +3 -0
  101. package/components/chat/themes/shared/chat-message/chat-message.fluent.css.js.map +1 -0
  102. package/components/chat/themes/shared/chat-message/chat-message.indigo.css.d.ts +1 -0
  103. package/components/chat/themes/shared/chat-message/chat-message.indigo.css.js +3 -0
  104. package/components/chat/themes/shared/chat-message/chat-message.indigo.css.js.map +1 -0
  105. package/components/chat/themes/shared/chat.bootstrap.css.d.ts +1 -0
  106. package/components/chat/themes/shared/chat.bootstrap.css.js +3 -0
  107. package/components/chat/themes/shared/chat.bootstrap.css.js.map +1 -0
  108. package/components/chat/themes/shared/chat.indigo.css.d.ts +1 -0
  109. package/components/chat/themes/shared/chat.indigo.css.js +3 -0
  110. package/components/chat/themes/shared/chat.indigo.css.js.map +1 -0
  111. package/components/chat/themes/shared/input/input.common.css.js +1 -1
  112. package/components/chat/themes/shared/input/input.common.css.js.map +1 -1
  113. package/components/chat/themes/shared/input/input.indigo.css.js +1 -1
  114. package/components/chat/themes/shared/input/input.indigo.css.js.map +1 -1
  115. package/components/chat/themes/shared/message-attachments.common.css.js +1 -1
  116. package/components/chat/themes/shared/message-attachments.common.css.js.map +1 -1
  117. package/components/chat/themes/shared/message-list.common.css.js +1 -1
  118. package/components/chat/themes/shared/message-list.common.css.js.map +1 -1
  119. package/components/chat/themes/themes.js +6 -4
  120. package/components/chat/themes/themes.js.map +1 -1
  121. package/components/chat/types.d.ts +72 -18
  122. package/components/chat/types.js +7 -0
  123. package/components/chat/types.js.map +1 -1
  124. package/components/checkbox/themes/shared/switch/switch.bootstrap.css.js +1 -1
  125. package/components/checkbox/themes/shared/switch/switch.bootstrap.css.js.map +1 -1
  126. package/components/checkbox/themes/shared/switch/switch.common.css.js +1 -1
  127. package/components/checkbox/themes/shared/switch/switch.common.css.js.map +1 -1
  128. package/components/checkbox/themes/shared/switch/switch.fluent.css.js +1 -1
  129. package/components/checkbox/themes/shared/switch/switch.fluent.css.js.map +1 -1
  130. package/components/checkbox/themes/shared/switch/switch.indigo.css.js +1 -1
  131. package/components/checkbox/themes/shared/switch/switch.indigo.css.js.map +1 -1
  132. package/components/chip/themes/chip.base.css.js +1 -1
  133. package/components/chip/themes/chip.base.css.js.map +1 -1
  134. package/components/chip/themes/shared/chip.indigo.css.js +1 -1
  135. package/components/chip/themes/shared/chip.indigo.css.js.map +1 -1
  136. package/components/combo/controllers/navigation.js +1 -1
  137. package/components/combo/controllers/navigation.js.map +1 -1
  138. package/components/combo/themes/combo-item.base.css.js +1 -1
  139. package/components/combo/themes/combo-item.base.css.js.map +1 -1
  140. package/components/combo/themes/combo.base.css.js +1 -1
  141. package/components/combo/themes/combo.base.css.js.map +1 -1
  142. package/components/combo/themes/shared/combo.bootstrap.css.js +1 -1
  143. package/components/combo/themes/shared/combo.bootstrap.css.js.map +1 -1
  144. package/components/combo/themes/shared/combo.common.css.js +1 -1
  145. package/components/combo/themes/shared/combo.common.css.js.map +1 -1
  146. package/components/combo/themes/shared/combo.fluent.css.js +1 -1
  147. package/components/combo/themes/shared/combo.fluent.css.js.map +1 -1
  148. package/components/combo/themes/shared/combo.indigo.css.js +1 -1
  149. package/components/combo/themes/shared/combo.indigo.css.js.map +1 -1
  150. package/components/combo/themes/shared/combo.material.css.js +1 -1
  151. package/components/combo/themes/shared/combo.material.css.js.map +1 -1
  152. package/components/common/controllers/key-bindings.js +4 -3
  153. package/components/common/controllers/key-bindings.js.map +1 -1
  154. package/components/common/i18n/chat.resources.d.ts +8 -0
  155. package/components/common/i18n/chat.resources.js +8 -0
  156. package/components/common/i18n/chat.resources.js.map +1 -0
  157. package/components/common/util.d.ts +14 -0
  158. package/components/common/util.js +51 -1
  159. package/components/common/util.js.map +1 -1
  160. package/components/date-picker/date-picker.js +2 -2
  161. package/components/date-picker/date-picker.js.map +1 -1
  162. package/components/date-picker/themes/shared/date-picker.common.css.js +1 -1
  163. package/components/date-picker/themes/shared/date-picker.common.css.js.map +1 -1
  164. package/components/date-range-picker/date-range-picker.js +0 -1
  165. package/components/date-range-picker/date-range-picker.js.map +1 -1
  166. package/components/date-range-picker/themes/shared/date-range-picker.bootstrap.css.js +1 -1
  167. package/components/date-range-picker/themes/shared/date-range-picker.bootstrap.css.js.map +1 -1
  168. package/components/date-range-picker/themes/shared/date-range-picker.common.css.js +1 -1
  169. package/components/date-range-picker/themes/shared/date-range-picker.common.css.js.map +1 -1
  170. package/components/date-time-input/date-time-input.js +1 -1
  171. package/components/date-time-input/date-time-input.js.map +1 -1
  172. package/components/dropdown/themes/dropdown-group.base.css.js +1 -1
  173. package/components/dropdown/themes/dropdown-group.base.css.js.map +1 -1
  174. package/components/dropdown/themes/dropdown-item.base.css.js +1 -1
  175. package/components/dropdown/themes/dropdown-item.base.css.js.map +1 -1
  176. package/components/dropdown/themes/shared/group/dropdown-group.fluent.css.js +1 -1
  177. package/components/dropdown/themes/shared/group/dropdown-group.fluent.css.js.map +1 -1
  178. package/components/dropdown/themes/shared/header/dropdown-header.common.css.js +1 -1
  179. package/components/dropdown/themes/shared/header/dropdown-header.common.css.js.map +1 -1
  180. package/components/dropdown/themes/shared/header/dropdown-header.indigo.css.js +1 -1
  181. package/components/dropdown/themes/shared/header/dropdown-header.indigo.css.js.map +1 -1
  182. package/components/dropdown/themes/shared/item/dropdown-item.indigo.css.js +1 -1
  183. package/components/dropdown/themes/shared/item/dropdown-item.indigo.css.js.map +1 -1
  184. package/components/expansion-panel/expansion-panel.js +0 -1
  185. package/components/expansion-panel/expansion-panel.js.map +1 -1
  186. package/components/expansion-panel/themes/expansion-panel.base.css.js +1 -1
  187. package/components/expansion-panel/themes/expansion-panel.base.css.js.map +1 -1
  188. package/components/expansion-panel/themes/shared/expansion-panel.indigo.css.js +1 -1
  189. package/components/expansion-panel/themes/shared/expansion-panel.indigo.css.js.map +1 -1
  190. package/components/file-input/themes/shared/file-input.bootstrap.css.js +1 -1
  191. package/components/file-input/themes/shared/file-input.bootstrap.css.js.map +1 -1
  192. package/components/input/themes/shared/input.bootstrap.css.js +1 -1
  193. package/components/input/themes/shared/input.bootstrap.css.js.map +1 -1
  194. package/components/input/themes/shared/input.common.css.js +1 -1
  195. package/components/input/themes/shared/input.common.css.js.map +1 -1
  196. package/components/input/themes/shared/input.fluent.css.js +1 -1
  197. package/components/input/themes/shared/input.fluent.css.js.map +1 -1
  198. package/components/input/themes/shared/input.indigo.css.js +1 -1
  199. package/components/input/themes/shared/input.indigo.css.js.map +1 -1
  200. package/components/input/themes/shared/input.material.css.js +1 -1
  201. package/components/input/themes/shared/input.material.css.js.map +1 -1
  202. package/components/list/themes/header.base.css.js +1 -1
  203. package/components/list/themes/header.base.css.js.map +1 -1
  204. package/components/list/themes/item.base.css.js +1 -1
  205. package/components/list/themes/item.base.css.js.map +1 -1
  206. package/components/list/themes/shared/header/list-header.indigo.css.js +1 -1
  207. package/components/list/themes/shared/header/list-header.indigo.css.js.map +1 -1
  208. package/components/list/themes/shared/item/list-item.indigo.css.js +1 -1
  209. package/components/list/themes/shared/item/list-item.indigo.css.js.map +1 -1
  210. package/components/rating/rating.js +0 -1
  211. package/components/rating/rating.js.map +1 -1
  212. package/components/select/themes/dark/select.bootstrap.css.js +1 -1
  213. package/components/select/themes/dark/select.bootstrap.css.js.map +1 -1
  214. package/components/select/themes/light/select.bootstrap.css.js +1 -1
  215. package/components/select/themes/light/select.bootstrap.css.js.map +1 -1
  216. package/components/select/themes/shared/select.bootstrap.css.js +1 -1
  217. package/components/select/themes/shared/select.bootstrap.css.js.map +1 -1
  218. package/components/select/themes/shared/select.common.css.js +1 -1
  219. package/components/select/themes/shared/select.common.css.js.map +1 -1
  220. package/components/select/themes/shared/select.material.css.js +1 -1
  221. package/components/select/themes/shared/select.material.css.js.map +1 -1
  222. package/components/slider/slider-base.js +0 -1
  223. package/components/slider/slider-base.js.map +1 -1
  224. package/components/tabs/tabs.js +0 -1
  225. package/components/tabs/tabs.js.map +1 -1
  226. package/components/textarea/themes/shared/textarea.bootstrap.css.js +1 -1
  227. package/components/textarea/themes/shared/textarea.bootstrap.css.js.map +1 -1
  228. package/components/textarea/themes/shared/textarea.common.css.js +1 -1
  229. package/components/textarea/themes/shared/textarea.common.css.js.map +1 -1
  230. package/components/textarea/themes/shared/textarea.fluent.css.js +1 -1
  231. package/components/textarea/themes/shared/textarea.fluent.css.js.map +1 -1
  232. package/components/textarea/themes/shared/textarea.indigo.css.js +1 -1
  233. package/components/textarea/themes/shared/textarea.indigo.css.js.map +1 -1
  234. package/components/textarea/themes/shared/textarea.material.css.js +1 -1
  235. package/components/textarea/themes/shared/textarea.material.css.js.map +1 -1
  236. package/components/textarea/themes/textarea.base.css.js +1 -1
  237. package/components/textarea/themes/textarea.base.css.js.map +1 -1
  238. package/components/tree/themes/item.base.css.js +1 -1
  239. package/components/tree/themes/item.base.css.js.map +1 -1
  240. package/components/tree/themes/shared/item.indigo.css.js +1 -1
  241. package/components/tree/themes/shared/item.indigo.css.js.map +1 -1
  242. package/components/tree/tree.js +3 -1
  243. package/components/tree/tree.js.map +1 -1
  244. package/components/tree/tree.navigation.js +3 -3
  245. package/components/tree/tree.navigation.js.map +1 -1
  246. package/components/tree/tree.selection.js +6 -2
  247. package/components/tree/tree.selection.js.map +1 -1
  248. package/custom-elements.json +5131 -4707
  249. package/igniteui-webcomponents.css-data.json +1 -1
  250. package/igniteui-webcomponents.html-data.json +1 -1
  251. package/index.d.ts +3 -0
  252. package/index.js +3 -0
  253. package/index.js.map +1 -1
  254. package/package.json +1 -1
  255. package/themes/dark/bootstrap.css +1 -1
  256. package/themes/dark/fluent.css +1 -1
  257. package/themes/dark/indigo.css +1 -1
  258. package/themes/dark/material.css +1 -1
  259. package/themes/light/bootstrap.css +1 -1
  260. package/themes/light/fluent.css +1 -1
  261. package/themes/light/indigo.css +1 -1
  262. package/themes/light/material.css +1 -1
  263. package/web-types.json +2 -2
  264. package/components/chat/markdown-util.d.ts +0 -2
  265. package/components/chat/markdown-util.js +0 -22
  266. package/components/chat/markdown-util.js.map +0 -1
  267. package/components/chat/themes/shared/chat-message.common.css.js +0 -3
  268. package/components/chat/themes/shared/chat-message.common.css.js.map +0 -1
  269. /package/components/chat/themes/shared/{chat-message.common.css.d.ts → chat-message/chat-message.bootstrap.css.d.ts} +0 -0
@@ -6,10 +6,9 @@ import { LitElement } from 'lit';
6
6
  *
7
7
  * This component:
8
8
  * - Renders messages using the `<igc-chat-message>` component.
9
- * - Supports keyboard navigation between messages (Home, End, ArrowUp, ArrowDown).
10
9
  * - Manages focus highlighting on active messages.
11
10
  * - Automatically scrolls to the bottom when new messages arrive, unless auto-scroll is disabled.
12
- * - Displays a typing indicator if the chat state option `isComposing` is true.
11
+ * - Displays a typing indicator if the chat state option `isTyping` is true.
13
12
  *
14
13
  * Accessibility:
15
14
  * - Uses ARIA roles and properties for grouping and active descendant management.
@@ -21,37 +20,16 @@ export default class IgcChatMessageListComponent extends LitElement {
21
20
  static readonly tagName = "igc-chat-message-list";
22
21
  /** Styles applied to the component */
23
22
  static styles: import("lit").CSSResult[];
24
- /**
25
- * Consumed chat state context providing messages, options, and user data.
26
- * @private
27
- */
28
- private _chatState?;
29
- /**
30
- * Currently active message id used for focus and keyboard navigation.
31
- * @private
32
- */
33
- private _activeMessageId;
34
23
  /**
35
24
  * Registers this component and its dependencies.
36
25
  * Used internally for component setup.
37
26
  */
38
27
  static register(): void;
39
- constructor();
40
- /**
41
- * Formats a date to a human-readable label.
42
- * Returns 'Today', 'Yesterday', or localized date string.
43
- * @param date - Date object to format
44
- * @returns formatted string
45
- * @private
46
- */
47
- private formatDate;
48
28
  /**
49
- * Groups messages by their date labels.
50
- * @param messages - Array of messages to group
51
- * @returns Array of groups with date label and messages
29
+ * Consumed chat state context providing messages, options, and user data.
52
30
  * @private
53
31
  */
54
- private groupMessagesByDate;
32
+ private _chatState?;
55
33
  /**
56
34
  * Scrolls the container to the bottom, typically called after new messages are rendered.
57
35
  * @private
@@ -62,26 +40,7 @@ export default class IgcChatMessageListComponent extends LitElement {
62
40
  * @param messageId - The id of the message to scroll to
63
41
  * @private
64
42
  */
65
- private scrollToMessage;
66
- /**
67
- * Handles focus entering the message list container.
68
- * Sets the active message to the last message for keyboard navigation.
69
- * @private
70
- */
71
- private handleFocusIn;
72
- /**
73
- * Handles focus leaving the message list container.
74
- * Clears the active message.
75
- * @private
76
- */
77
- private handleFocusOut;
78
- /**
79
- * Handles keyboard navigation within the message list.
80
- * Supports Home, End, ArrowUp, ArrowDown keys to move active message focus.
81
- * @param e KeyboardEvent from user input
82
- * @private
83
- */
84
- private navigateToMessage;
43
+ scrollToMessage(messageId: string): void;
85
44
  /**
86
45
  * Lifecycle: called when the component updates.
87
46
  * Scrolls to bottom unless auto-scroll is disabled.
@@ -93,7 +52,7 @@ export default class IgcChatMessageListComponent extends LitElement {
93
52
  */
94
53
  protected firstUpdated(): void;
95
54
  /**
96
- * Renders the typing indicator template if composing.
55
+ * Renders the typing indicator template.
97
56
  * @protected
98
57
  */
99
58
  protected renderLoadingTemplate(): Generator<import("lit-html").TemplateResult<1>, void, unknown>;
@@ -6,10 +6,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { consume } from '@lit/context';
8
8
  import { html, LitElement, nothing } from 'lit';
9
- import { state } from 'lit/decorators.js';
10
9
  import { repeat } from 'lit/directives/repeat.js';
11
10
  import { chatContext } from '../common/context.js';
12
- import { addKeybindings, arrowDown, arrowUp, endKey, homeKey, } from '../common/controllers/key-bindings.js';
13
11
  import { registerComponent } from '../common/definitions/register.js';
14
12
  import IgcChatMessageComponent from './chat-message.js';
15
13
  import { styles } from './themes/message-list.base.css.js';
@@ -18,45 +16,6 @@ class IgcChatMessageListComponent extends LitElement {
18
16
  static register() {
19
17
  registerComponent(IgcChatMessageListComponent, IgcChatMessageComponent);
20
18
  }
21
- constructor() {
22
- super();
23
- this._activeMessageId = '';
24
- addKeybindings(this)
25
- .set(homeKey, this.navigateToMessage)
26
- .set(endKey, this.navigateToMessage)
27
- .set(arrowUp, this.navigateToMessage)
28
- .set(arrowDown, this.navigateToMessage);
29
- }
30
- formatDate(date) {
31
- const today = new Date();
32
- const yesterday = new Date(today);
33
- yesterday.setDate(yesterday.getDate() - 1);
34
- if (date.toDateString() === today.toDateString()) {
35
- return 'Today';
36
- }
37
- if (date.toDateString() === yesterday.toDateString()) {
38
- return 'Yesterday';
39
- }
40
- return date.toLocaleDateString('en-US', {
41
- weekday: 'long',
42
- month: 'short',
43
- day: 'numeric',
44
- });
45
- }
46
- groupMessagesByDate(messages) {
47
- const grouped = {};
48
- messages.forEach((message) => {
49
- const dateStr = this.formatDate(message.timestamp);
50
- if (!grouped[dateStr]) {
51
- grouped[dateStr] = [];
52
- }
53
- grouped[dateStr].push(message);
54
- });
55
- return Object.keys(grouped).map((date) => ({
56
- date,
57
- messages: grouped[date],
58
- }));
59
- }
60
19
  scrollToBottom() {
61
20
  requestAnimationFrame(() => {
62
21
  const container = this.shadowRoot?.host;
@@ -69,47 +28,6 @@ class IgcChatMessageListComponent extends LitElement {
69
28
  const messageElement = this.shadowRoot?.querySelector(`#message-${messageId}`);
70
29
  messageElement?.scrollIntoView();
71
30
  }
72
- handleFocusIn() {
73
- if (!this._chatState?.messages || this._chatState.messages.length === 0) {
74
- return;
75
- }
76
- const lastMessage = this._chatState.sortedMessagesIds?.pop() ?? '';
77
- this._activeMessageId = lastMessage !== '' ? `message-${lastMessage}` : '';
78
- }
79
- handleFocusOut() {
80
- this._activeMessageId = '';
81
- }
82
- navigateToMessage(e) {
83
- if (!this._chatState?.messages || this._chatState.messages.length === 0) {
84
- return;
85
- }
86
- const currentIndex = this._chatState?.sortedMessagesIds.findIndex((id) => `message-${id}` === this._activeMessageId);
87
- let activeMessageId = '';
88
- const key = e.key.toLowerCase();
89
- switch (key) {
90
- case 'home':
91
- activeMessageId = this._chatState.sortedMessagesIds[0];
92
- break;
93
- case 'end':
94
- activeMessageId =
95
- this._chatState.sortedMessagesIds[this._chatState.sortedMessagesIds.length - 1];
96
- break;
97
- case 'arrowup':
98
- if (currentIndex > 0) {
99
- activeMessageId = this._chatState.sortedMessagesIds[currentIndex - 1];
100
- }
101
- break;
102
- case 'arrowdown':
103
- if (currentIndex < this._chatState?.messages.length - 1) {
104
- activeMessageId = this._chatState.sortedMessagesIds[currentIndex + 1];
105
- }
106
- break;
107
- default:
108
- return;
109
- }
110
- this._activeMessageId = `message-${activeMessageId}`;
111
- this.scrollToMessage(activeMessageId);
112
- }
113
31
  updated() {
114
32
  if (!this._chatState?.options?.disableAutoScroll) {
115
33
  this.scrollToBottom();
@@ -121,44 +39,40 @@ class IgcChatMessageListComponent extends LitElement {
121
39
  }
122
40
  }
123
41
  *renderLoadingTemplate() {
124
- yield html `${this._chatState?.options?.templates?.composingIndicatorTemplate
125
- ? this._chatState.options.templates.composingIndicatorTemplate
42
+ yield html `${this._chatState?.options?.templates?.typingIndicatorTemplate
43
+ ? this._chatState.options.templates.typingIndicatorTemplate
126
44
  : html `<div part="typing-indicator">
127
45
  <div part="typing-dot"></div>
128
46
  <div part="typing-dot"></div>
129
47
  <div part="typing-dot"></div>
48
+ <div part="typing-dot"></div>
130
49
  </div>`}`;
131
50
  }
132
51
  render() {
133
- const groupedMessages = this.groupMessagesByDate(this._chatState?.messages ?? []);
52
+ const messages = this._chatState?.messages ?? [];
134
53
  return html `
135
54
  <div
136
55
  part="message-container"
137
- aria-activedescendant=${this._activeMessageId}
138
56
  role="group"
139
57
  aria-label="Message list"
140
58
  tabindex="0"
141
- @focusin=${this.handleFocusIn}
142
- @focusout=${this.handleFocusOut}
143
59
  ></div>
144
60
  <div part="message-list">
145
- ${repeat(groupedMessages, (group) => group.date, (group) => html `
146
- ${repeat(group.messages, (message) => message.id, (message) => {
61
+ ${repeat(messages, (message) => message.id, (message) => {
147
62
  const messageId = `message-${message.id}`;
148
63
  return html `
149
- <igc-chat-message
150
- id=${messageId}
151
- role="option"
152
- part="message-item ${this._activeMessageId === messageId
153
- ? 'active'
154
- : ''}"
155
- .message=${message}
156
- >
157
- </igc-chat-message>
158
- `;
64
+ <igc-chat-message
65
+ id=${messageId}
66
+ role="option"
67
+ part="message-item"
68
+ .message=${message}
69
+ exportparts="message-container, message-text, message-attachments, message-actions,
70
+ attachments-container, attachment, attachment-header, attachment-content, attachment-icon, file-name, actions: attachment-actions"
71
+ >
72
+ </igc-chat-message>
73
+ `;
159
74
  })}
160
- `)}
161
- ${this._chatState?.options?.isComposing
75
+ ${this._chatState?.options?.isTyping
162
76
  ? this.renderLoadingTemplate()
163
77
  : nothing}
164
78
  </div>
@@ -172,7 +86,4 @@ export default IgcChatMessageListComponent;
172
86
  __decorate([
173
87
  consume({ context: chatContext, subscribe: true })
174
88
  ], IgcChatMessageListComponent.prototype, "_chatState", void 0);
175
- __decorate([
176
- state()
177
- ], IgcChatMessageListComponent.prototype, "_activeMessageId", void 0);
178
89
  //# sourceMappingURL=chat-message-list.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-message-list.js","sourceRoot":"","sources":["../../../src/components/chat/chat-message-list.ts"],"names":[],"mappings":"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","sourcesContent":["import { consume } from '@lit/context';\nimport { html, LitElement, nothing } from 'lit';\nimport { state } from 'lit/decorators.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { chatContext } from '../common/context.js';\nimport {\n addKeybindings,\n arrowDown,\n arrowUp,\n endKey,\n homeKey,\n} from '../common/controllers/key-bindings.js';\nimport { registerComponent } from '../common/definitions/register.js';\nimport IgcChatMessageComponent from './chat-message.js';\nimport type { ChatState } from './chat-state.js';\nimport { styles } from './themes/message-list.base.css.js';\nimport { styles as shared } from './themes/shared/message-list.common.css.js';\nimport type { IgcMessage } from './types.js';\n\n/**\n * A chat message list component that displays a list of chat messages grouped by date.\n *\n * @element igc-chat-message-list\n *\n * This component:\n * - Renders messages using the `<igc-chat-message>` component.\n * - Supports keyboard navigation between messages (Home, End, ArrowUp, ArrowDown).\n * - Manages focus highlighting on active messages.\n * - Automatically scrolls to the bottom when new messages arrive, unless auto-scroll is disabled.\n * - Displays a typing indicator if the chat state option `isComposing` is true.\n *\n * Accessibility:\n * - Uses ARIA roles and properties for grouping and active descendant management.\n * - Message items have role=\"option\" for assistive technologies.\n *\n */\nexport default class IgcChatMessageListComponent extends LitElement {\n /** Tag name of the custom element. */\n public static readonly tagName = 'igc-chat-message-list';\n\n /** Styles applied to the component */\n public static override styles = [styles, shared];\n\n /**\n * Consumed chat state context providing messages, options, and user data.\n * @private\n */\n @consume({ context: chatContext, subscribe: true })\n private _chatState?: ChatState;\n\n /**\n * Currently active message id used for focus and keyboard navigation.\n * @private\n */\n @state()\n private _activeMessageId = '';\n\n /**\n * Registers this component and its dependencies.\n * Used internally for component setup.\n */\n /* blazorSuppress */\n public static register() {\n registerComponent(IgcChatMessageListComponent, IgcChatMessageComponent);\n }\n\n constructor() {\n super();\n addKeybindings(this)\n .set(homeKey, this.navigateToMessage)\n .set(endKey, this.navigateToMessage)\n .set(arrowUp, this.navigateToMessage)\n .set(arrowDown, this.navigateToMessage);\n }\n\n /**\n * Formats a date to a human-readable label.\n * Returns 'Today', 'Yesterday', or localized date string.\n * @param date - Date object to format\n * @returns formatted string\n * @private\n */\n private formatDate(date: Date): string {\n const today = new Date();\n const yesterday = new Date(today);\n yesterday.setDate(yesterday.getDate() - 1);\n\n if (date.toDateString() === today.toDateString()) {\n return 'Today';\n }\n\n if (date.toDateString() === yesterday.toDateString()) {\n return 'Yesterday';\n }\n\n return date.toLocaleDateString('en-US', {\n weekday: 'long',\n month: 'short',\n day: 'numeric',\n });\n }\n\n /**\n * Groups messages by their date labels.\n * @param messages - Array of messages to group\n * @returns Array of groups with date label and messages\n * @private\n */\n private groupMessagesByDate(\n messages: IgcMessage[]\n ): { date: string; messages: IgcMessage[] }[] {\n const grouped: { [key: string]: IgcMessage[] } = {};\n\n messages.forEach((message) => {\n const dateStr = this.formatDate(message.timestamp);\n if (!grouped[dateStr]) {\n grouped[dateStr] = [];\n }\n grouped[dateStr].push(message);\n });\n\n return Object.keys(grouped).map((date) => ({\n date,\n messages: grouped[date],\n }));\n }\n\n /**\n * Scrolls the container to the bottom, typically called after new messages are rendered.\n * @private\n */\n private scrollToBottom() {\n requestAnimationFrame(() => {\n const container = this.shadowRoot?.host as HTMLElement;\n if (container) {\n container.scrollTop = container.scrollHeight;\n }\n });\n }\n\n /**\n * Scrolls the view to a specific message by id.\n * @param messageId - The id of the message to scroll to\n * @private\n */\n private scrollToMessage(messageId: string) {\n const messageElement = this.shadowRoot?.querySelector(\n `#message-${messageId}`\n );\n messageElement?.scrollIntoView();\n }\n\n /**\n * Handles focus entering the message list container.\n * Sets the active message to the last message for keyboard navigation.\n * @private\n */\n private handleFocusIn() {\n if (!this._chatState?.messages || this._chatState.messages.length === 0) {\n return;\n }\n const lastMessage = this._chatState.sortedMessagesIds?.pop() ?? '';\n this._activeMessageId = lastMessage !== '' ? `message-${lastMessage}` : '';\n }\n\n /**\n * Handles focus leaving the message list container.\n * Clears the active message.\n * @private\n */\n private handleFocusOut() {\n this._activeMessageId = '';\n }\n\n /**\n * Handles keyboard navigation within the message list.\n * Supports Home, End, ArrowUp, ArrowDown keys to move active message focus.\n * @param e KeyboardEvent from user input\n * @private\n */\n private navigateToMessage(e: KeyboardEvent) {\n if (!this._chatState?.messages || this._chatState.messages.length === 0) {\n return;\n }\n\n const currentIndex = this._chatState?.sortedMessagesIds.findIndex(\n (id) => `message-${id}` === this._activeMessageId\n );\n let activeMessageId = '';\n const key = e.key.toLowerCase();\n\n switch (key) {\n case 'home':\n activeMessageId = this._chatState.sortedMessagesIds[0];\n break;\n case 'end':\n activeMessageId =\n this._chatState.sortedMessagesIds[\n this._chatState.sortedMessagesIds.length - 1\n ];\n break;\n case 'arrowup':\n if (currentIndex > 0) {\n activeMessageId = this._chatState.sortedMessagesIds[currentIndex - 1];\n }\n break;\n case 'arrowdown':\n if (currentIndex < this._chatState?.messages.length - 1) {\n activeMessageId = this._chatState.sortedMessagesIds[currentIndex + 1];\n }\n break;\n default:\n return; // Ignore other keys\n }\n\n this._activeMessageId = `message-${activeMessageId}`;\n this.scrollToMessage(activeMessageId);\n }\n\n /**\n * Lifecycle: called when the component updates.\n * Scrolls to bottom unless auto-scroll is disabled.\n */\n protected override updated() {\n if (!this._chatState?.options?.disableAutoScroll) {\n this.scrollToBottom();\n }\n }\n\n /**\n * Lifecycle: called after first render.\n * Scrolls to bottom unless auto-scroll is disabled.\n */\n protected override firstUpdated() {\n if (!this._chatState?.options?.disableAutoScroll) {\n this.scrollToBottom();\n }\n }\n\n /**\n * Renders the typing indicator template if composing.\n * @protected\n */\n protected *renderLoadingTemplate() {\n yield html`${this._chatState?.options?.templates?.composingIndicatorTemplate\n ? this._chatState.options.templates.composingIndicatorTemplate\n : html`<div part=\"typing-indicator\">\n <div part=\"typing-dot\"></div>\n <div part=\"typing-dot\"></div>\n <div part=\"typing-dot\"></div>\n </div>`}`;\n }\n\n /**\n * Main render method.\n * Groups messages by date and renders each message.\n * Shows the typing indicator if applicable.\n */\n protected override render() {\n const groupedMessages = this.groupMessagesByDate(\n this._chatState?.messages ?? []\n );\n\n return html`\n <div\n part=\"message-container\"\n aria-activedescendant=${this._activeMessageId}\n role=\"group\"\n aria-label=\"Message list\"\n tabindex=\"0\"\n @focusin=${this.handleFocusIn}\n @focusout=${this.handleFocusOut}\n ></div>\n <div part=\"message-list\">\n ${repeat(\n groupedMessages,\n (group) => group.date,\n (group) => html`\n ${repeat(\n group.messages,\n (message) => message.id,\n (message) => {\n const messageId = `message-${message.id}`;\n return html`\n <igc-chat-message\n id=${messageId}\n role=\"option\"\n part=\"message-item ${this._activeMessageId === messageId\n ? 'active'\n : ''}\"\n .message=${message}\n >\n </igc-chat-message>\n `;\n }\n )}\n `\n )}\n ${\n this._chatState?.options?.isComposing\n ? this.renderLoadingTemplate()\n : nothing\n }\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'igc-chat-message-list': IgcChatMessageListComponent;\n }\n}\n"]}
1
+ {"version":3,"file":"chat-message-list.js","sourceRoot":"","sources":["../../../src/components/chat/chat-message-list.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,uBAAuB,MAAM,mBAAmB,CAAC;AAExD,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAC3D,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,4CAA4C,CAAC;AAkB9E,MAAqB,2BAA4B,SAAQ,UAAU;IAY1D,MAAM,CAAC,QAAQ;QACpB,iBAAiB,CAAC,2BAA2B,EAAE,uBAAuB,CAAC,CAAC;IAC1E,CAAC;IAaO,cAAc;QACpB,qBAAqB,CAAC,GAAG,EAAE;YACzB,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,IAAmB,CAAC;YACvD,IAAI,SAAS,EAAE,CAAC;gBACd,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC,YAAY,CAAC;YAC/C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAOM,eAAe,CAAC,SAAiB;QACtC,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CACnD,YAAY,SAAS,EAAE,CACxB,CAAC;QACF,cAAc,EAAE,cAAc,EAAE,CAAC;IACnC,CAAC;IAMkB,OAAO;QACxB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;YACjD,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAMkB,YAAY;QAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;YACjD,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAMS,CAAC,qBAAqB;QAC9B,MAAM,IAAI,CAAA,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,uBAAuB;YACvE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,uBAAuB;YAC3D,CAAC,CAAC,IAAI,CAAA;;;;;eAKG,EAAE,CAAC;IAChB,CAAC;IAOkB,MAAM;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,IAAI,EAAE,CAAC;QAEjD,OAAO,IAAI,CAAA;;;;;;;;aAQF,MAAM,CACN,QAAQ,EACR,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,EACvB,CAAC,OAAO,EAAE,EAAE;YACV,MAAM,SAAS,GAAG,WAAW,OAAO,CAAC,EAAE,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAA;;wBAEF,SAAS;;;8BAGH,OAAO;;;;;gBAKrB,CAAC;QACJ,CAAC,CACF;YAEA,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ;YAChC,CAAC,CAAC,IAAI,CAAC,qBAAqB,EAAE;YAC9B,CAAC,CAAC,OACN;;;KAGL,CAAC;IACJ,CAAC;;AA3HsB,mCAAO,GAAG,uBAAuB,CAAC;AAGlC,kCAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;eAL9B,2BAA2B;AAqBtC;IADP,OAAO,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;+DACpB","sourcesContent":["import { consume } from '@lit/context';\nimport { html, LitElement, nothing } from 'lit';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { chatContext } from '../common/context.js';\nimport { registerComponent } from '../common/definitions/register.js';\nimport IgcChatMessageComponent from './chat-message.js';\nimport type { ChatState } from './chat-state.js';\nimport { styles } from './themes/message-list.base.css.js';\nimport { styles as shared } from './themes/shared/message-list.common.css.js';\n\n/**\n * A chat message list component that displays a list of chat messages grouped by date.\n *\n * @element igc-chat-message-list\n *\n * This component:\n * - Renders messages using the `<igc-chat-message>` component.\n * - Manages focus highlighting on active messages.\n * - Automatically scrolls to the bottom when new messages arrive, unless auto-scroll is disabled.\n * - Displays a typing indicator if the chat state option `isTyping` is true.\n *\n * Accessibility:\n * - Uses ARIA roles and properties for grouping and active descendant management.\n * - Message items have role=\"option\" for assistive technologies.\n *\n */\nexport default class IgcChatMessageListComponent extends LitElement {\n /** Tag name of the custom element. */\n public static readonly tagName = 'igc-chat-message-list';\n\n /** Styles applied to the component */\n public static override styles = [styles, shared];\n\n /**\n * Registers this component and its dependencies.\n * Used internally for component setup.\n */\n /* blazorSuppress */\n public static register() {\n registerComponent(IgcChatMessageListComponent, IgcChatMessageComponent);\n }\n\n /**\n * Consumed chat state context providing messages, options, and user data.\n * @private\n */\n @consume({ context: chatContext, subscribe: true })\n private _chatState?: ChatState;\n\n /**\n * Scrolls the container to the bottom, typically called after new messages are rendered.\n * @private\n */\n private scrollToBottom() {\n requestAnimationFrame(() => {\n const container = this.shadowRoot?.host as HTMLElement;\n if (container) {\n container.scrollTop = container.scrollHeight;\n }\n });\n }\n\n /**\n * Scrolls the view to a specific message by id.\n * @param messageId - The id of the message to scroll to\n * @private\n */\n public scrollToMessage(messageId: string) {\n const messageElement = this.shadowRoot?.querySelector(\n `#message-${messageId}`\n );\n messageElement?.scrollIntoView();\n }\n\n /**\n * Lifecycle: called when the component updates.\n * Scrolls to bottom unless auto-scroll is disabled.\n */\n protected override updated() {\n if (!this._chatState?.options?.disableAutoScroll) {\n this.scrollToBottom();\n }\n }\n\n /**\n * Lifecycle: called after first render.\n * Scrolls to bottom unless auto-scroll is disabled.\n */\n protected override firstUpdated() {\n if (!this._chatState?.options?.disableAutoScroll) {\n this.scrollToBottom();\n }\n }\n\n /**\n * Renders the typing indicator template.\n * @protected\n */\n protected *renderLoadingTemplate() {\n yield html`${this._chatState?.options?.templates?.typingIndicatorTemplate\n ? this._chatState.options.templates.typingIndicatorTemplate\n : html`<div part=\"typing-indicator\">\n <div part=\"typing-dot\"></div>\n <div part=\"typing-dot\"></div>\n <div part=\"typing-dot\"></div>\n <div part=\"typing-dot\"></div>\n </div>`}`;\n }\n\n /**\n * Main render method.\n * Groups messages by date and renders each message.\n * Shows the typing indicator if applicable.\n */\n protected override render() {\n const messages = this._chatState?.messages ?? [];\n\n return html`\n <div\n part=\"message-container\"\n role=\"group\"\n aria-label=\"Message list\"\n tabindex=\"0\"\n ></div>\n <div part=\"message-list\">\n ${repeat(\n messages,\n (message) => message.id,\n (message) => {\n const messageId = `message-${message.id}`;\n return html`\n <igc-chat-message\n id=${messageId}\n role=\"option\"\n part=\"message-item\"\n .message=${message}\n exportparts=\"message-container, message-text, message-attachments, message-actions,\n attachments-container, attachment, attachment-header, attachment-content, attachment-icon, file-name, actions: attachment-actions\"\n >\n </igc-chat-message>\n `;\n }\n )}\n ${\n this._chatState?.options?.isTyping\n ? this.renderLoadingTemplate()\n : nothing\n }\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'igc-chat-message-list': IgcChatMessageListComponent;\n }\n}\n"]}
@@ -1,10 +1,12 @@
1
- import { LitElement } from 'lit';
1
+ import { LitElement, nothing } from 'lit';
2
2
  import type { IgcMessage } from './types.js';
3
3
  /**
4
4
  * A chat message component for displaying individual messages in `<igc-chat>`.
5
5
  *
6
6
  * @element igc-chat-message
7
7
  *
8
+ * @fires igcMessageReact - Fired when a message is reacted to.
9
+ *
8
10
  * This component renders a single chat message including:
9
11
  * - Message text (sanitized)
10
12
  * - Attachments (if any)
@@ -17,38 +19,26 @@ import type { IgcMessage } from './types.js';
17
19
  * and can be rendered with a markdown renderer if provided.
18
20
  */
19
21
  export default class IgcChatMessageComponent extends LitElement {
20
- /** Tag name of the custom element. */
21
22
  static readonly tagName = "igc-chat-message";
22
- /** Styles applied to the component. */
23
23
  static styles: import("lit").CSSResult[];
24
+ static register(): void;
24
25
  /**
25
26
  * Injected chat state context. Provides message data, user info, and options.
26
- * @private
27
27
  */
28
28
  private _chatState?;
29
- /**
30
- * Registers this component and its dependencies.
31
- * This is used internally to set up the component definitions.
32
- */
33
- static register(): void;
34
29
  /**
35
30
  * The chat message to render.
36
31
  */
37
- message: IgcMessage | undefined;
38
- /**
39
- * Sanitizes message text to prevent XSS or invalid HTML.
40
- * @param text The raw message text
41
- * @returns Sanitized text safe for HTML rendering
42
- * @private
43
- */
44
- private sanitizeMessageText;
32
+ message?: IgcMessage;
33
+ constructor();
34
+ protected firstUpdated(): void;
45
35
  /**
46
36
  * Renders the chat message template.
47
37
  * - Applies 'sent' CSS class if the message sender matches current user.
48
38
  * - Uses markdown rendering if configured.
49
39
  * - Renders attachments and custom templates if provided.
50
40
  */
51
- protected render(): import("lit-html").TemplateResult<1>;
41
+ protected render(): import("lit-html").TemplateResult<1> | typeof nothing;
52
42
  }
53
43
  declare global {
54
44
  interface HTMLElementTagNameMap {
@@ -5,46 +5,42 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { consume } from '@lit/context';
8
- import DOMPurify from 'dompurify';
9
- import { html, LitElement, nothing } from 'lit';
8
+ import { adoptStyles, html, LitElement, nothing } from 'lit';
10
9
  import { property } from 'lit/decorators.js';
10
+ import { until } from 'lit/directives/until.js';
11
+ import { addThemingController } from '../../theming/theming-controller.js';
11
12
  import IgcAvatarComponent from '../avatar/avatar.js';
12
13
  import { chatContext } from '../common/context.js';
13
14
  import { registerComponent } from '../common/definitions/register.js';
14
- import { renderMarkdown } from './markdown-util.js';
15
+ import { partMap } from '../common/part-map.js';
16
+ import IgcTooltipComponent from '../tooltip/tooltip.js';
15
17
  import IgcMessageAttachmentsComponent from './message-attachments.js';
16
18
  import { styles } from './themes/message.base.css.js';
17
- import { styles as shared } from './themes/shared/chat-message.common.css.js';
19
+ import { all } from './themes/message.js';
20
+ import { styles as shared } from './themes/shared/chat-message/chat-message.common.css.js';
18
21
  class IgcChatMessageComponent extends LitElement {
19
22
  static register() {
20
- registerComponent(IgcChatMessageComponent, IgcMessageAttachmentsComponent, IgcAvatarComponent);
23
+ registerComponent(IgcChatMessageComponent, IgcMessageAttachmentsComponent, IgcAvatarComponent, IgcTooltipComponent);
21
24
  }
22
- sanitizeMessageText(text) {
23
- return DOMPurify.sanitize(text);
25
+ constructor() {
26
+ super();
27
+ addThemingController(this, all);
28
+ }
29
+ firstUpdated() {
30
+ adoptPageStyles(this);
24
31
  }
25
32
  render() {
26
- const containerPart = `message-container ${this.message?.sender === this._chatState?.currentUserId ? 'sent' : ''}`;
27
- const sanitizedMessageText = this.sanitizeMessageText(this.message?.text.trim() || '');
28
- const renderer = this._chatState?.options?.markdownRenderer || renderMarkdown;
29
- return html `
30
- <div part=${containerPart}>
31
- <div part="bubble">
32
- ${this._chatState?.options?.templates?.messageTemplate && this.message
33
- ? this._chatState.options.templates.messageTemplate(this.message)
34
- : html `${sanitizedMessageText
35
- ? html `<div>${renderer(sanitizedMessageText)}</div>`
36
- : nothing}`}
37
- ${this.message?.attachments && this.message?.attachments.length > 0
38
- ? html `<igc-message-attachments .message=${this.message}>
39
- </igc-message-attachments>`
40
- : nothing}
41
- ${this._chatState?.options?.templates?.messageActionsTemplate &&
42
- this.message
43
- ? this._chatState.options.templates.messageActionsTemplate(this.message)
44
- : nothing}
45
- </div>
46
- </div>
47
- `;
33
+ const parts = {
34
+ 'message-container': true,
35
+ sent: this._chatState?.currentUserId === this.message?.sender,
36
+ };
37
+ return this.message && this._chatState?.chatRenderer
38
+ ? html `
39
+ <div part=${partMap(parts)}>
40
+ ${until(this._chatState.chatRenderer.render(this.message))}
41
+ </div>
42
+ `
43
+ : nothing;
48
44
  }
49
45
  }
50
46
  IgcChatMessageComponent.tagName = 'igc-chat-message';
@@ -56,4 +52,19 @@ __decorate([
56
52
  __decorate([
57
53
  property({ attribute: false })
58
54
  ], IgcChatMessageComponent.prototype, "message", void 0);
55
+ function adoptPageStyles(message) {
56
+ const sheets = [];
57
+ for (const sheet of document.styleSheets) {
58
+ try {
59
+ const constructed = new CSSStyleSheet();
60
+ for (const rule of sheet.cssRules) {
61
+ constructed.insertRule(rule.cssText);
62
+ }
63
+ sheets.push(constructed);
64
+ }
65
+ catch { }
66
+ }
67
+ const ctor = message.constructor;
68
+ adoptStyles(message.shadowRoot, [...ctor.elementStyles, ...sheets]);
69
+ }
59
70
  //# sourceMappingURL=chat-message.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-message.js","sourceRoot":"","sources":["../../../src/components/chat/chat-message.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,kBAAkB,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAEtE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,8BAA8B,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AACtD,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,4CAA4C,CAAC;AAmB9E,MAAqB,uBAAwB,SAAQ,UAAU;IAmBtD,MAAM,CAAC,QAAQ;QACpB,iBAAiB,CACf,uBAAuB,EACvB,8BAA8B,EAC9B,kBAAkB,CACnB,CAAC;IACJ,CAAC;IAcO,mBAAmB,CAAC,IAAY;QACtC,OAAO,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAQkB,MAAM;QACvB,MAAM,aAAa,GAAG,qBAAqB,IAAI,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACnH,MAAM,oBAAoB,GAAG,IAAI,CAAC,mBAAmB,CACnD,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAChC,CAAC;QACF,MAAM,QAAQ,GACZ,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,gBAAgB,IAAI,cAAc,CAAC;QAE/D,OAAO,IAAI,CAAA;kBACG,aAAa;;YAEnB,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,IAAI,IAAI,CAAC,OAAO;YACpE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;YACjE,CAAC,CAAC,IAAI,CAAA,GAAG,oBAAoB;gBACzB,CAAC,CAAC,IAAI,CAAA,QAAQ,QAAQ,CAAC,oBAAoB,CAAC,QAAQ;gBACpD,CAAC,CAAC,OAAO,EAAE;YACf,IAAI,CAAC,OAAO,EAAE,WAAW,IAAI,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC;YACjE,CAAC,CAAC,IAAI,CAAA,qCAAqC,IAAI,CAAC,OAAO;yCAC1B;YAC7B,CAAC,CAAC,OAAO;YACT,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,sBAAsB;YAC7D,IAAI,CAAC,OAAO;YACV,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,sBAAsB,CACtD,IAAI,CAAC,OAAO,CACb;YACH,CAAC,CAAC,OAAO;;;KAGhB,CAAC;IACJ,CAAC;;AA5EsB,+BAAO,GAAG,kBAAkB,CAAC;AAG7B,8BAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;eAL9B,uBAAuB;AAYlC;IADP,OAAO,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;2DACpB;AAmBxB;IADN,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;wDACQ","sourcesContent":["import { consume } from '@lit/context';\nimport DOMPurify from 'dompurify';\nimport { html, LitElement, nothing } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport IgcAvatarComponent from '../avatar/avatar.js';\nimport { chatContext } from '../common/context.js';\nimport { registerComponent } from '../common/definitions/register.js';\nimport type { ChatState } from './chat-state.js';\nimport { renderMarkdown } from './markdown-util.js';\nimport IgcMessageAttachmentsComponent from './message-attachments.js';\nimport { styles } from './themes/message.base.css.js';\nimport { styles as shared } from './themes/shared/chat-message.common.css.js';\nimport type { IgcMessage } from './types.js';\n\n/**\n * A chat message component for displaying individual messages in `<igc-chat>`.\n *\n * @element igc-chat-message\n *\n * This component renders a single chat message including:\n * - Message text (sanitized)\n * - Attachments (if any)\n * - Custom templates for message content and actions (if provided via chat options)\n *\n * It distinguishes sent messages from received messages by comparing\n * the message sender with the current user ID from chat state.\n *\n * The message text is sanitized with DOMPurify before rendering,\n * and can be rendered with a markdown renderer if provided.\n */\nexport default class IgcChatMessageComponent extends LitElement {\n /** Tag name of the custom element. */\n public static readonly tagName = 'igc-chat-message';\n\n /** Styles applied to the component. */\n public static override styles = [styles, shared];\n\n /**\n * Injected chat state context. Provides message data, user info, and options.\n * @private\n */\n @consume({ context: chatContext, subscribe: true })\n private _chatState?: ChatState;\n\n /**\n * Registers this component and its dependencies.\n * This is used internally to set up the component definitions.\n */\n /* blazorSuppress */\n public static register() {\n registerComponent(\n IgcChatMessageComponent,\n IgcMessageAttachmentsComponent,\n IgcAvatarComponent\n );\n }\n\n /**\n * The chat message to render.\n */\n @property({ attribute: false })\n public message: IgcMessage | undefined;\n\n /**\n * Sanitizes message text to prevent XSS or invalid HTML.\n * @param text The raw message text\n * @returns Sanitized text safe for HTML rendering\n * @private\n */\n private sanitizeMessageText(text: string): string {\n return DOMPurify.sanitize(text);\n }\n\n /**\n * Renders the chat message template.\n * - Applies 'sent' CSS class if the message sender matches current user.\n * - Uses markdown rendering if configured.\n * - Renders attachments and custom templates if provided.\n */\n protected override render() {\n const containerPart = `message-container ${this.message?.sender === this._chatState?.currentUserId ? 'sent' : ''}`;\n const sanitizedMessageText = this.sanitizeMessageText(\n this.message?.text.trim() || ''\n );\n const renderer =\n this._chatState?.options?.markdownRenderer || renderMarkdown;\n\n return html`\n <div part=${containerPart}>\n <div part=\"bubble\">\n ${this._chatState?.options?.templates?.messageTemplate && this.message\n ? this._chatState.options.templates.messageTemplate(this.message)\n : html`${sanitizedMessageText\n ? html`<div>${renderer(sanitizedMessageText)}</div>`\n : nothing}`}\n ${this.message?.attachments && this.message?.attachments.length > 0\n ? html`<igc-message-attachments .message=${this.message}>\n </igc-message-attachments>`\n : nothing}\n ${this._chatState?.options?.templates?.messageActionsTemplate &&\n this.message\n ? this._chatState.options.templates.messageActionsTemplate(\n this.message\n )\n : nothing}\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'igc-chat-message': IgcChatMessageComponent;\n }\n}\n"]}
1
+ {"version":3,"file":"chat-message.js","sourceRoot":"","sources":["../../../src/components/chat/chat-message.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,kBAAkB,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AAExD,OAAO,8BAA8B,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AACtD,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,yDAAyD,CAAC;AAqB3F,MAAqB,uBAAwB,SAAQ,UAAU;IAKtD,MAAM,CAAC,QAAQ;QACpB,iBAAiB,CACf,uBAAuB,EACvB,8BAA8B,EAC9B,kBAAkB,EAClB,mBAAmB,CACpB,CAAC;IACJ,CAAC;IAcD;QACE,KAAK,EAAE,CAAC;QACR,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC;IAEkB,YAAY;QAC7B,eAAe,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAQkB,MAAM;QACvB,MAAM,KAAK,GAAG;YACZ,mBAAmB,EAAE,IAAI;YACzB,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,KAAK,IAAI,CAAC,OAAO,EAAE,MAAM;SAC9D,CAAC;QAEF,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,EAAE,YAAY;YAClD,CAAC,CAAC,IAAI,CAAA;sBACU,OAAO,CAAC,KAAK,CAAC;cACtB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;;SAE7D;YACH,CAAC,CAAC,OAAO,CAAC;IACd,CAAC;;AArDsB,+BAAO,GAAG,kBAAkB,CAAC;AAC7B,8BAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;eAF9B,uBAAuB;AAkBlC;IADP,OAAO,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;2DACpB;AAMxB;IADN,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;wDACH;AAwC9B,SAAS,eAAe,CAAC,OAAgC;IACvD,MAAM,MAAM,GAAoB,EAAE,CAAC;IAEnC,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAI,aAAa,EAAE,CAAC;YACxC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAClC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvC,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,WAAgC,CAAC;IACtD,WAAW,CAAC,OAAO,CAAC,UAAW,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;AACvE,CAAC","sourcesContent":["import { consume } from '@lit/context';\nimport { adoptStyles, html, LitElement, nothing } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { until } from 'lit/directives/until.js';\nimport { addThemingController } from '../../theming/theming-controller.js';\nimport IgcAvatarComponent from '../avatar/avatar.js';\nimport { chatContext } from '../common/context.js';\nimport { registerComponent } from '../common/definitions/register.js';\nimport { partMap } from '../common/part-map.js';\nimport IgcTooltipComponent from '../tooltip/tooltip.js';\nimport type { ChatState } from './chat-state.js';\nimport IgcMessageAttachmentsComponent from './message-attachments.js';\nimport { styles } from './themes/message.base.css.js';\nimport { all } from './themes/message.js';\nimport { styles as shared } from './themes/shared/chat-message/chat-message.common.css.js';\nimport type { IgcMessage } from './types.js';\n\n/**\n * A chat message component for displaying individual messages in `<igc-chat>`.\n *\n * @element igc-chat-message\n *\n * @fires igcMessageReact - Fired when a message is reacted to.\n *\n * This component renders a single chat message including:\n * - Message text (sanitized)\n * - Attachments (if any)\n * - Custom templates for message content and actions (if provided via chat options)\n *\n * It distinguishes sent messages from received messages by comparing\n * the message sender with the current user ID from chat state.\n *\n * The message text is sanitized with DOMPurify before rendering,\n * and can be rendered with a markdown renderer if provided.\n */\nexport default class IgcChatMessageComponent extends LitElement {\n public static readonly tagName = 'igc-chat-message';\n public static override styles = [styles, shared];\n\n /* blazorSuppress */\n public static register(): void {\n registerComponent(\n IgcChatMessageComponent,\n IgcMessageAttachmentsComponent,\n IgcAvatarComponent,\n IgcTooltipComponent\n );\n }\n\n /**\n * Injected chat state context. Provides message data, user info, and options.\n */\n @consume({ context: chatContext, subscribe: true })\n private _chatState?: ChatState;\n\n /**\n * The chat message to render.\n */\n @property({ attribute: false })\n public message?: IgcMessage;\n\n constructor() {\n super();\n addThemingController(this, all);\n }\n\n protected override firstUpdated(): void {\n adoptPageStyles(this);\n }\n\n /**\n * Renders the chat message template.\n * - Applies 'sent' CSS class if the message sender matches current user.\n * - Uses markdown rendering if configured.\n * - Renders attachments and custom templates if provided.\n */\n protected override render() {\n const parts = {\n 'message-container': true,\n sent: this._chatState?.currentUserId === this.message?.sender,\n };\n\n return this.message && this._chatState?.chatRenderer\n ? html`\n <div part=${partMap(parts)}>\n ${until(this._chatState.chatRenderer.render(this.message))}\n </div>\n `\n : nothing;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'igc-chat-message': IgcChatMessageComponent;\n }\n}\n\n// REVIEW: Maybe put that behind a configuration flag as this is nasty.\nfunction adoptPageStyles(message: IgcChatMessageComponent): void {\n const sheets: CSSStyleSheet[] = [];\n\n for (const sheet of document.styleSheets) {\n try {\n const constructed = new CSSStyleSheet();\n for (const rule of sheet.cssRules) {\n constructed.insertRule(rule.cssText);\n }\n sheets.push(constructed);\n } catch {}\n }\n\n const ctor = message.constructor as typeof LitElement;\n adoptStyles(message.shadowRoot!, [...ctor.elementStyles, ...sheets]);\n}\n"]}
@@ -0,0 +1,14 @@
1
+ import type { ChatMessageRenderer, IgcChatTemplates, IgcMessage } from './types.js';
2
+ export declare class DefaultChatRenderer implements ChatMessageRenderer {
3
+ private baseTextRenderer;
4
+ private defaultTemplates;
5
+ private cache;
6
+ templates: Required<IgcChatTemplates>;
7
+ constructor(baseTextRenderer: ChatMessageRenderer, // e.g. PlainTextRenderer, MarkdownMessageRenderer
8
+ defaultTemplates: Required<IgcChatTemplates>, userTemplates?: Partial<IgcChatTemplates>);
9
+ protected renderText(message: IgcMessage): Promise<unknown>;
10
+ render(message: IgcMessage, ctx?: {
11
+ templates?: Partial<IgcChatTemplates>;
12
+ }): Promise<unknown>;
13
+ clearCache(): void;
14
+ }
@@ -0,0 +1,39 @@
1
+ export class DefaultChatRenderer {
2
+ constructor(baseTextRenderer, defaultTemplates, userTemplates) {
3
+ this.baseTextRenderer = baseTextRenderer;
4
+ this.defaultTemplates = defaultTemplates;
5
+ this.cache = new Map();
6
+ this.templates = {
7
+ ...this.defaultTemplates,
8
+ ...(userTemplates ?? {}),
9
+ };
10
+ }
11
+ async renderText(message) {
12
+ const rendered = await this.baseTextRenderer.render(message);
13
+ return rendered;
14
+ }
15
+ async render(message, ctx) {
16
+ const templates = { ...ctx?.templates, ...this.templates };
17
+ if (!message.id) {
18
+ const textContent = await this.baseTextRenderer.render(message);
19
+ return templates.messageTemplate(message, { textContent, templates });
20
+ }
21
+ if (this.cache.has(message.id)) {
22
+ const cached = this.cache.get(message.id);
23
+ if (cached && cached.text === message.text) {
24
+ return cached.rendered;
25
+ }
26
+ }
27
+ const textContent = await this.baseTextRenderer.render(message);
28
+ const rendered = templates.messageTemplate(message, {
29
+ textContent,
30
+ templates,
31
+ });
32
+ this.cache.set(message.id, { text: message.text, rendered });
33
+ return rendered;
34
+ }
35
+ clearCache() {
36
+ this.cache.clear();
37
+ }
38
+ }
39
+ //# sourceMappingURL=chat-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-renderer.js","sourceRoot":"","sources":["../../../src/components/chat/chat-renderer.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,mBAAmB;IAI9B,YACU,gBAAqC,EACrC,gBAA4C,EACpD,aAAyC;QAFjC,qBAAgB,GAAhB,gBAAgB,CAAqB;QACrC,qBAAgB,GAAhB,gBAAgB,CAA4B;QAL9C,UAAK,GAAG,IAAI,GAAG,EAA+C,CAAC;QAQrE,IAAI,CAAC,SAAS,GAAG;YACf,GAAG,IAAI,CAAC,gBAAgB;YACxB,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;SACzB,CAAC;IACJ,CAAC;IAES,KAAK,CAAC,UAAU,CAAC,OAAmB;QAC5C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7D,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEM,KAAK,CAAC,MAAM,CACjB,OAAmB,EACnB,GAA+C;QAE/C,MAAM,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC3D,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAEhB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAChE,OAAO,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC1C,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC3C,OAAO,MAAM,CAAC,QAAQ,CAAC;YACzB,CAAC;QACH,CAAC;QAGD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAChE,MAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE;YAClD,WAAW;YACX,SAAS;SACV,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAE7D,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEM,UAAU;QACf,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF","sourcesContent":["import type {\n ChatMessageRenderer,\n IgcChatTemplates,\n IgcMessage,\n} from './types.js';\n\nexport class DefaultChatRenderer implements ChatMessageRenderer {\n private cache = new Map<string, { text: string; rendered: unknown }>();\n public templates: Required<IgcChatTemplates>;\n\n constructor(\n private baseTextRenderer: ChatMessageRenderer, // e.g. PlainTextRenderer, MarkdownMessageRenderer\n private defaultTemplates: Required<IgcChatTemplates>,\n userTemplates?: Partial<IgcChatTemplates>\n ) {\n this.templates = {\n ...this.defaultTemplates,\n ...(userTemplates ?? {}),\n };\n }\n\n protected async renderText(message: IgcMessage) {\n const rendered = await this.baseTextRenderer.render(message);\n return rendered;\n }\n\n public async render(\n message: IgcMessage,\n ctx?: { templates?: Partial<IgcChatTemplates> }\n ): Promise<unknown> {\n const templates = { ...ctx?.templates, ...this.templates };\n if (!message.id) {\n // No caching for messages without an ID\n const textContent = await this.baseTextRenderer.render(message);\n return templates.messageTemplate(message, { textContent, templates });\n }\n\n if (this.cache.has(message.id)) {\n const cached = this.cache.get(message.id);\n if (cached && cached.text === message.text) {\n return cached.rendered;\n }\n }\n\n // Cache miss or message text changed\n const textContent = await this.baseTextRenderer.render(message);\n const rendered = templates.messageTemplate(message, {\n textContent,\n templates,\n });\n this.cache.set(message.id, { text: message.text, rendered });\n\n return rendered;\n }\n\n public clearCache() {\n this.cache.clear();\n }\n}\n"]}