@cometchat/skills 4.3.0 → 4.4.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 (233) hide show
  1. package/LICENSE +21 -0
  2. package/bin/install.js +27 -0
  3. package/package.json +14 -1
  4. package/skills/cometchat/SKILL.md +233 -69
  5. package/skills/cometchat/references/asking-questions.md +48 -0
  6. package/skills/cometchat-a11y/SKILL.md +3 -2
  7. package/skills/cometchat-android-v5/SKILL.md +2 -1
  8. package/skills/cometchat-android-v5-calls/SKILL.md +36 -22
  9. package/skills/cometchat-android-v5-calls/references/README.md +1 -1
  10. package/skills/cometchat-android-v5-calls/references/add-calls-to-existing-chat.md +7 -5
  11. package/skills/cometchat-android-v5-calls/references/audio-controls.md +4 -4
  12. package/skills/cometchat-android-v5-calls/references/call-layouts.md +33 -25
  13. package/skills/cometchat-android-v5-calls/references/call-session.md +2 -2
  14. package/skills/cometchat-android-v5-calls/references/custom-ui.md +5 -5
  15. package/skills/cometchat-android-v5-calls/references/event-listeners.md +2 -2
  16. package/skills/cometchat-android-v5-calls/references/idle-timeout.md +20 -14
  17. package/skills/cometchat-android-v5-calls/references/in-call-chat.md +1 -1
  18. package/skills/cometchat-android-v5-calls/references/migration-v4-to-v5.md +43 -27
  19. package/skills/cometchat-android-v5-calls/references/participant-management.md +3 -3
  20. package/skills/cometchat-android-v5-calls/references/raise-hand.md +25 -19
  21. package/skills/cometchat-android-v5-calls/references/recording.md +2 -2
  22. package/skills/cometchat-android-v5-calls/references/ringing-integration.md +1 -1
  23. package/skills/cometchat-android-v5-calls/references/screen-sharing.md +5 -9
  24. package/skills/cometchat-android-v5-calls/references/session-settings.md +3 -3
  25. package/skills/cometchat-android-v5-calls/references/setup.md +1 -1
  26. package/skills/cometchat-android-v5-calls/references/share-invite.md +9 -4
  27. package/skills/cometchat-android-v5-calls/references/video-controls.md +4 -4
  28. package/skills/cometchat-android-v5-calls/references/voip-calling.md +2 -2
  29. package/skills/cometchat-android-v5-components/SKILL.md +4 -3
  30. package/skills/cometchat-android-v5-core/SKILL.md +5 -3
  31. package/skills/cometchat-android-v5-customization/SKILL.md +171 -7
  32. package/skills/cometchat-android-v5-extensions/SKILL.md +7 -4
  33. package/skills/cometchat-android-v5-features/SKILL.md +5 -4
  34. package/skills/cometchat-android-v5-placement/SKILL.md +2 -1
  35. package/skills/cometchat-android-v5-production/SKILL.md +2 -1
  36. package/skills/cometchat-android-v5-push/SKILL.md +2 -3
  37. package/skills/cometchat-android-v5-testing/SKILL.md +2 -1
  38. package/skills/cometchat-android-v5-theming/SKILL.md +2 -1
  39. package/skills/cometchat-android-v5-troubleshooting/SKILL.md +3 -2
  40. package/skills/cometchat-android-v6/SKILL.md +2 -1
  41. package/skills/cometchat-android-v6-builder-settings/SKILL.md +11 -7
  42. package/skills/cometchat-android-v6-calls/SKILL.md +79 -18
  43. package/skills/cometchat-android-v6-calls/references/advanced-features.md +87 -0
  44. package/skills/cometchat-android-v6-calls/references/call-layouts.md +24 -15
  45. package/skills/cometchat-android-v6-calls/references/call-session.md +2 -2
  46. package/skills/cometchat-android-v6-calls/references/device-management.md +17 -16
  47. package/skills/cometchat-android-v6-calls/references/idle-timeout.md +7 -4
  48. package/skills/cometchat-android-v6-calls/references/in-call-chat.md +13 -8
  49. package/skills/cometchat-android-v6-calls/references/raise-hand.md +6 -4
  50. package/skills/cometchat-android-v6-compose-components/SKILL.md +52 -29
  51. package/skills/cometchat-android-v6-compose-customization/SKILL.md +156 -1
  52. package/skills/cometchat-android-v6-compose-placement/SKILL.md +129 -40
  53. package/skills/cometchat-android-v6-compose-theming/SKILL.md +27 -1
  54. package/skills/cometchat-android-v6-core/SKILL.md +208 -28
  55. package/skills/cometchat-android-v6-events/SKILL.md +4 -1
  56. package/skills/cometchat-android-v6-extensions/SKILL.md +2 -1
  57. package/skills/cometchat-android-v6-features/SKILL.md +26 -2
  58. package/skills/cometchat-android-v6-kotlin-components/SKILL.md +31 -1
  59. package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +172 -1
  60. package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +20 -5
  61. package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +36 -5
  62. package/skills/cometchat-android-v6-migration/SKILL.md +44 -42
  63. package/skills/cometchat-android-v6-production/SKILL.md +6 -3
  64. package/skills/cometchat-android-v6-push/SKILL.md +43 -2
  65. package/skills/cometchat-android-v6-testing/SKILL.md +11 -8
  66. package/skills/cometchat-android-v6-troubleshooting/SKILL.md +26 -5
  67. package/skills/cometchat-angular-calls/SKILL.md +256 -389
  68. package/skills/cometchat-angular-calls/references/add-calls-to-existing-chat.md +3 -2
  69. package/skills/cometchat-angular-calls/references/call-layouts.md +29 -12
  70. package/skills/cometchat-angular-calls/references/call-session.md +2 -2
  71. package/skills/cometchat-angular-calls/references/custom-ui.md +18 -10
  72. package/skills/cometchat-angular-calls/references/device-management.md +53 -34
  73. package/skills/cometchat-angular-calls/references/group-calls.md +45 -24
  74. package/skills/cometchat-angular-calls/references/idle-timeout.md +31 -15
  75. package/skills/cometchat-angular-calls/references/ngzone-and-async-callbacks.md +7 -6
  76. package/skills/cometchat-angular-calls/references/raise-hand.md +9 -4
  77. package/skills/cometchat-angular-calls/references/recording-screen-share.md +32 -39
  78. package/skills/cometchat-angular-calls/references/ringing-integration.md +3 -1
  79. package/skills/cometchat-angular-calls/references/share-invite.md +11 -5
  80. package/skills/cometchat-angular-calls/references/virtual-background.md +29 -0
  81. package/skills/cometchat-angular-components/SKILL.md +149 -620
  82. package/skills/cometchat-angular-core/SKILL.md +232 -312
  83. package/skills/cometchat-angular-customization/SKILL.md +415 -223
  84. package/skills/cometchat-angular-features/SKILL.md +216 -334
  85. package/skills/cometchat-angular-patterns/SKILL.md +168 -359
  86. package/skills/cometchat-angular-placement/SKILL.md +189 -560
  87. package/skills/cometchat-angular-production/SKILL.md +241 -92
  88. package/skills/cometchat-angular-push/SKILL.md +280 -294
  89. package/skills/cometchat-angular-testing/SKILL.md +430 -158
  90. package/skills/cometchat-angular-theming/SKILL.md +190 -265
  91. package/skills/cometchat-angular-troubleshooting/SKILL.md +192 -157
  92. package/skills/cometchat-astro-patterns/SKILL.md +3 -2
  93. package/skills/cometchat-calls/SKILL.md +25 -19
  94. package/skills/cometchat-calls/references/use-case-broadcast.md +15 -10
  95. package/skills/cometchat-calls/references/use-case-marketplace.md +2 -3
  96. package/skills/cometchat-calls/references/use-case-support.md +3 -4
  97. package/skills/cometchat-calls/references/use-case-team.md +23 -12
  98. package/skills/cometchat-calls/references/use-case-telehealth.md +3 -4
  99. package/skills/cometchat-components/SKILL.md +163 -25
  100. package/skills/cometchat-core/SKILL.md +258 -20
  101. package/skills/cometchat-customization/SKILL.md +50 -25
  102. package/skills/cometchat-features/SKILL.md +314 -35
  103. package/skills/cometchat-flutter-v5/SKILL.md +10 -4
  104. package/skills/cometchat-flutter-v5-calls/SKILL.md +188 -158
  105. package/skills/cometchat-flutter-v5-calls/references/add-calls-to-existing-chat.md +48 -24
  106. package/skills/cometchat-flutter-v5-calls/references/call-layouts.md +20 -15
  107. package/skills/cometchat-flutter-v5-calls/references/call-session.md +100 -145
  108. package/skills/cometchat-flutter-v5-calls/references/device-management.md +12 -8
  109. package/skills/cometchat-flutter-v5-calls/references/group-calls.md +30 -36
  110. package/skills/cometchat-flutter-v5-calls/references/idle-timeout.md +15 -13
  111. package/skills/cometchat-flutter-v5-calls/references/in-call-chat.md +12 -9
  112. package/skills/cometchat-flutter-v5-calls/references/migration-v4-to-v5.md +115 -65
  113. package/skills/cometchat-flutter-v5-calls/references/raise-hand.md +41 -30
  114. package/skills/cometchat-flutter-v5-calls/references/ringing-integration.md +17 -14
  115. package/skills/cometchat-flutter-v5-calls/references/share-invite.md +8 -2
  116. package/skills/cometchat-flutter-v5-conversations/SKILL.md +2 -1
  117. package/skills/cometchat-flutter-v5-core/SKILL.md +5 -4
  118. package/skills/cometchat-flutter-v5-customization/SKILL.md +136 -5
  119. package/skills/cometchat-flutter-v5-events/SKILL.md +2 -1
  120. package/skills/cometchat-flutter-v5-messages/SKILL.md +2 -1
  121. package/skills/cometchat-flutter-v5-production/SKILL.md +15 -6
  122. package/skills/cometchat-flutter-v5-push/SKILL.md +2 -1
  123. package/skills/cometchat-flutter-v5-testing/SKILL.md +17 -6
  124. package/skills/cometchat-flutter-v5-theming/SKILL.md +2 -1
  125. package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +7 -6
  126. package/skills/cometchat-flutter-v5-users-groups/SKILL.md +3 -2
  127. package/skills/cometchat-flutter-v6/SKILL.md +17 -16
  128. package/skills/cometchat-flutter-v6-calls/SKILL.md +72 -57
  129. package/skills/cometchat-flutter-v6-calls/references/add-calls-to-existing-chat.md +5 -3
  130. package/skills/cometchat-flutter-v6-calls/references/advanced-features.md +89 -0
  131. package/skills/cometchat-flutter-v6-calls/references/call-layouts.md +15 -12
  132. package/skills/cometchat-flutter-v6-calls/references/call-session.md +2 -2
  133. package/skills/cometchat-flutter-v6-calls/references/device-management.md +9 -3
  134. package/skills/cometchat-flutter-v6-calls/references/group-calls.md +10 -10
  135. package/skills/cometchat-flutter-v6-calls/references/idle-timeout.md +15 -7
  136. package/skills/cometchat-flutter-v6-calls/references/in-call-chat.md +6 -3
  137. package/skills/cometchat-flutter-v6-calls/references/raise-hand.md +23 -16
  138. package/skills/cometchat-flutter-v6-components/SKILL.md +32 -11
  139. package/skills/cometchat-flutter-v6-conversations/SKILL.md +39 -11
  140. package/skills/cometchat-flutter-v6-core/SKILL.md +182 -21
  141. package/skills/cometchat-flutter-v6-customization/SKILL.md +97 -25
  142. package/skills/cometchat-flutter-v6-events/SKILL.md +3 -2
  143. package/skills/cometchat-flutter-v6-features/SKILL.md +15 -6
  144. package/skills/cometchat-flutter-v6-messages/SKILL.md +111 -60
  145. package/skills/cometchat-flutter-v6-migration/SKILL.md +18 -25
  146. package/skills/cometchat-flutter-v6-placement/SKILL.md +79 -50
  147. package/skills/cometchat-flutter-v6-production/SKILL.md +13 -12
  148. package/skills/cometchat-flutter-v6-push/SKILL.md +41 -19
  149. package/skills/cometchat-flutter-v6-testing/SKILL.md +4 -4
  150. package/skills/cometchat-flutter-v6-theming/SKILL.md +38 -5
  151. package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +182 -17
  152. package/skills/cometchat-flutter-v6-users-groups/SKILL.md +12 -4
  153. package/skills/cometchat-i18n/SKILL.md +140 -79
  154. package/skills/cometchat-ios/SKILL.md +4 -2
  155. package/skills/cometchat-ios-calls/SKILL.md +225 -95
  156. package/skills/cometchat-ios-calls/references/add-calls-to-existing-chat.md +11 -9
  157. package/skills/cometchat-ios-calls/references/audio-modes-and-controls.md +45 -0
  158. package/skills/cometchat-ios-calls/references/avaudiosession-routing.md +6 -7
  159. package/skills/cometchat-ios-calls/references/call-layouts.md +31 -91
  160. package/skills/cometchat-ios-calls/references/call-session.md +51 -54
  161. package/skills/cometchat-ios-calls/references/callkit-and-pushkit.md +33 -29
  162. package/skills/cometchat-ios-calls/references/custom-ui.md +38 -38
  163. package/skills/cometchat-ios-calls/references/group-calls.md +33 -70
  164. package/skills/cometchat-ios-calls/references/idle-timeout.md +24 -25
  165. package/skills/cometchat-ios-calls/references/in-call-chat.md +19 -23
  166. package/skills/cometchat-ios-calls/references/migration-v4-to-v5.md +128 -70
  167. package/skills/cometchat-ios-calls/references/picture-in-picture.md +20 -20
  168. package/skills/cometchat-ios-calls/references/raise-hand.md +14 -227
  169. package/skills/cometchat-ios-calls/references/recording-screen-share.md +35 -122
  170. package/skills/cometchat-ios-calls/references/ringing-integration.md +17 -16
  171. package/skills/cometchat-ios-calls/references/share-invite.md +8 -12
  172. package/skills/cometchat-ios-calls/references/swiftui-uikit-hosting.md +4 -4
  173. package/skills/cometchat-ios-components/SKILL.md +200 -12
  174. package/skills/cometchat-ios-core/SKILL.md +173 -45
  175. package/skills/cometchat-ios-customization/SKILL.md +276 -110
  176. package/skills/cometchat-ios-features/SKILL.md +64 -36
  177. package/skills/cometchat-ios-placement/SKILL.md +15 -12
  178. package/skills/cometchat-ios-production/SKILL.md +12 -4
  179. package/skills/cometchat-ios-push/SKILL.md +53 -19
  180. package/skills/cometchat-ios-testing/SKILL.md +14 -9
  181. package/skills/cometchat-ios-theming/SKILL.md +39 -3
  182. package/skills/cometchat-ios-troubleshooting/SKILL.md +41 -21
  183. package/skills/cometchat-native-bare-patterns/SKILL.md +36 -19
  184. package/skills/cometchat-native-calls/SKILL.md +29 -17
  185. package/skills/cometchat-native-calls/references/add-calls-to-existing-chat.md +2 -2
  186. package/skills/cometchat-native-calls/references/call-layouts.md +15 -14
  187. package/skills/cometchat-native-calls/references/call-session.md +2 -2
  188. package/skills/cometchat-native-calls/references/custom-ui.md +12 -8
  189. package/skills/cometchat-native-calls/references/device-management.md +53 -30
  190. package/skills/cometchat-native-calls/references/group-calls.md +35 -30
  191. package/skills/cometchat-native-calls/references/idle-timeout.md +6 -6
  192. package/skills/cometchat-native-calls/references/in-call-chat.md +10 -8
  193. package/skills/cometchat-native-calls/references/migration-v4-to-v5.md +2 -2
  194. package/skills/cometchat-native-calls/references/raise-hand.md +15 -13
  195. package/skills/cometchat-native-calls/references/recording-screen-share.md +49 -170
  196. package/skills/cometchat-native-calls/references/share-invite.md +7 -5
  197. package/skills/cometchat-native-calls/references/voip-push-end-to-end.md +4 -2
  198. package/skills/cometchat-native-components/SKILL.md +84 -52
  199. package/skills/cometchat-native-core/SKILL.md +102 -33
  200. package/skills/cometchat-native-customization/SKILL.md +150 -28
  201. package/skills/cometchat-native-expo-patterns/SKILL.md +60 -29
  202. package/skills/cometchat-native-features/SKILL.md +24 -17
  203. package/skills/cometchat-native-placement/SKILL.md +19 -10
  204. package/skills/cometchat-native-production/SKILL.md +9 -3
  205. package/skills/cometchat-native-push/SKILL.md +2 -1
  206. package/skills/cometchat-native-testing/SKILL.md +1 -2
  207. package/skills/cometchat-native-theming/SKILL.md +54 -29
  208. package/skills/cometchat-native-troubleshooting/SKILL.md +11 -5
  209. package/skills/cometchat-nextjs-patterns/SKILL.md +22 -8
  210. package/skills/cometchat-placement/SKILL.md +42 -3
  211. package/skills/cometchat-production/SKILL.md +12 -5
  212. package/skills/cometchat-react-calls/SKILL.md +220 -10
  213. package/skills/cometchat-react-calls/references/add-calls-to-existing-chat.md +4 -3
  214. package/skills/cometchat-react-calls/references/call-layouts.md +5 -6
  215. package/skills/cometchat-react-calls/references/call-session.md +1 -1
  216. package/skills/cometchat-react-calls/references/custom-ui.md +61 -15
  217. package/skills/cometchat-react-calls/references/device-management.md +55 -51
  218. package/skills/cometchat-react-calls/references/group-calls.md +18 -23
  219. package/skills/cometchat-react-calls/references/idle-timeout.md +25 -12
  220. package/skills/cometchat-react-calls/references/in-call-chat.md +7 -7
  221. package/skills/cometchat-react-calls/references/migration-v4-to-v5.md +9 -11
  222. package/skills/cometchat-react-calls/references/raise-hand.md +14 -14
  223. package/skills/cometchat-react-calls/references/recording-screen-share.md +39 -38
  224. package/skills/cometchat-react-calls/references/ringing-integration.md +2 -2
  225. package/skills/cometchat-react-calls/references/share-invite.md +4 -5
  226. package/skills/cometchat-react-calls/references/testing-calls-on-web.md +20 -2
  227. package/skills/cometchat-react-calls/references/virtual-background.md +32 -0
  228. package/skills/cometchat-react-patterns/SKILL.md +45 -5
  229. package/skills/cometchat-react-push/SKILL.md +258 -72
  230. package/skills/cometchat-react-router-patterns/SKILL.md +12 -6
  231. package/skills/cometchat-react-testing/SKILL.md +14 -5
  232. package/skills/cometchat-theming/SKILL.md +181 -18
  233. package/skills/cometchat-troubleshooting/SKILL.md +40 -20
@@ -1,163 +1,175 @@
1
1
  ---
2
2
  name: cometchat-angular-customization
3
- description: "Customize the CometChat Angular UI Kit without forking — four-tier model: Angular inputs → request builders → text formatters + message templates DataSource decorators + event bus."
3
+ description: "Customize the CometChat Angular UI Kit v5 (@cometchat/chat-uikit-angular@5) without forking — four-tier model: Angular @Input slot views → request builders → text formatters + message-action options + per-type bubble views event bus. Standalone components, ng-template slots, no NgModule, no DataSource."
4
4
  license: "MIT"
5
- compatibility: "Angular >=12 <=15; @cometchat/chat-uikit-angular ^4; @cometchat/chat-sdk-javascript ^4"
6
- allowed-tools: "shell, file-read, file-search, file-list, ask-user"
5
+ compatibility: "Angular >=17 <22; @cometchat/chat-uikit-angular ^5.0"
7
6
  metadata:
8
7
  author: "CometChat"
9
- version: "3.0.0"
10
- tags: "cometchat angular customization formatters events datasource templates ng-template"
8
+ version: "4.0.0"
9
+ tags: "cometchat angular customization v5 formatters events templates ng-template slot-views options standalone"
11
10
  ---
12
11
 
13
12
  ## Purpose
14
13
 
15
- Teaches Claude how to change the behavior or appearance of the Angular UI Kit **without modifying the kit itself**. Four tiers, from cheapest to deepest:
14
+ Teaches Claude how to change the behaviour or appearance of the CometChat **Angular UI Kit v5** (`@cometchat/chat-uikit-angular@5`) **without modifying the kit itself**. Four tiers, from cheapest to deepest:
16
15
 
17
16
  ```
18
- Tier 1 — Angular inputs (95% of asks solved here)
19
- Tier 2 — RequestBuilder (filter what data loads)
20
- Tier 3 — Formatters + Templates (change how text / messages render)
21
- Tier 4 — DataSource decorators + Events (last resort, powerful)
17
+ Tier 1 — Slot views (@Input ng-template) (95% of asks solved here)
18
+ Tier 2 — RequestBuilder (filter what data loads)
19
+ Tier 3 — Formatters + message-action options + per-type bubble views
20
+ Tier 4 — Event bus (react to kit activity)
22
21
  ```
23
22
 
24
23
  **Always try Tier 1 first.** Escalate only when the tier can't do what the user wants.
25
24
 
26
- **Read `cometchat-angular-components` first** the catalog is the source of truth for input names, slot templates, and event names that this skill builds on.
25
+ **Read `cometchat-angular-core` first, then `cometchat-angular-components`.** The component catalog is the source of truth for the exact `@Input` slot-view names, `@Output` events, and request-builder inputs that this skill builds on. Never invent a binding — if it isn't in the catalog or the bundled `.d.ts`, it doesn't exist.
27
26
 
28
- Ground truth: `docs/ui-kit/angular/custom-text-formatter-guide`, `docs/ui-kit/angular/events`, `docs/ui-kit/angular/methods`, and the kit's source.
27
+ Ground truth: `@cometchat/chat-uikit-angular@5.0.2` bundled types (`node_modules/@cometchat/chat-uikit-angular/types/cometchat-chat-uikit-angular.d.ts`) + `docs/ui-kit/angular`. Verify any non-obvious symbol against the installed `.d.ts` before relying on it. **Official docs:** https://www.cometchat.com/docs/ui-kit/angular/overview · **Docs MCP:** `claude mcp add --transport http cometchat-docs https://www.cometchat.com/docs/mcp` (or fetch the URL directly without MCP).
28
+
29
+ ---
30
+
31
+ ## v5 reset — what is NOT here (if you've seen the v4 Angular kit)
32
+
33
+ v5 is a clean break from the v4 (NgModule, Angular 12–15) customization model. These v4 symbols are **gone** — do not import or reference them:
34
+
35
+ | v4 symbol (phantom in v5) | v5 replacement |
36
+ |---|---|
37
+ | `CometChatMessageTemplate` | per-type bubble views via `MessageBubbleConfigService.setBubbleView(type, partMap)`, **or** the `bubbleFooterView` / `appendView` slot inputs (Tier 3c) |
38
+ | `DataSource` / `DataSourceDecorator` / `ChatConfigurator` | request builders (Tier 2) + the `MessageBubbleConfigService` / `CometChatTemplatesService` injected services |
39
+ | `templates` @Input on `<cometchat-message-list>` | **does not exist** — use `optionsOverride` / `additionalOptions` for actions and `MessageBubbleConfigService` for bubbles |
40
+ | `CometChatTextFormatter` v4 API (`setRegexPatterns`, `getFormattedText(input)`, `getOriginalText(input)`) | v5 API: abstract `id`, `getRegex()`, `format(text)`, optional `shouldFormat(text, msg)`, `priority` |
41
+ | `CometChatUrlsFormatter` (plural) | `CometChatUrlFormatter` (singular) |
42
+ | `@cometchat/uikit-shared` imports | everything imports from `@cometchat/chat-uikit-angular` |
43
+
44
+ Everything in this skill imports from **`@cometchat/chat-uikit-angular`** (formatters, event classes, services) or **`@cometchat/chat-sdk-javascript`** (the `CometChat` namespace + request builders). There is no `uikit-shared` in v5.
45
+
46
+ > **Verified absent in the Angular kit (v5.0.2 source):** `CometChatMessageTemplate`, `getDataSource`, `ChatConfigurator`, `DataSourceDecorator`, and `getAllMessageTemplates` do **not** exist anywhere in `projects/cometchat-uikit/src/lib` (grep over the entire library returns no matches outside specs). The web/React kit's `new CometChat.MessageTemplate(...)` / `getDataSource().getAllMessageTemplates()` pattern has **no Angular equivalent** — custom bubbles go exclusively through `MessageBubbleConfigService.setBubbleView` (Tier 3c) and message-action overrides through the `additionalOptions` / `optionsOverride` `@Input`s (Tier 3b). Do not port the React DataSource recipe here.
29
47
 
30
48
  ---
31
49
 
32
50
  ## Four-tier triage — pick the right tier before writing any code
33
51
 
34
- **Start with Tier 1 every time.** The Angular UI Kit follows a "inputs over components" philosophy — most additions are inputs on already-mounted components, not new components or custom code.
52
+ **Start with Tier 1 every time.** The Angular UI Kit follows an "inputs over components" philosophy — most additions are `@Input` bindings on already-mounted standalone components, not new components or custom code.
35
53
 
36
54
  ### Quick task → input lookup
37
55
 
38
- Before escalating to any tier, check if an existing component input already does what you need:
56
+ Before escalating, check whether an existing component `@Input` already does what you need (all verified in `cometchat-angular-components`):
39
57
 
40
- | User asks for | Likely input on which component |
58
+ | User asks for | Likely `@Input` on which component |
41
59
  |---|---|
42
- | Search bar | `[hideSearch]="false"` on `<cometchat-conversations>`, `<cometchat-users>`, `<cometchat-groups>` |
60
+ | Search bar on the conversation list | `[showSearchBar]="true"` on `<cometchat-conversations>` |
43
61
  | Filter conversations | `[conversationsRequestBuilder]` on `<cometchat-conversations>` |
44
62
  | Filter messages | `[messagesRequestBuilder]` on `<cometchat-message-list>` |
45
63
  | Filter users / groups | `[usersRequestBuilder]` / `[groupsRequestBuilder]` |
46
- | Custom empty state | `[emptyStateView]` on list components |
47
- | Custom error UI | `[errorStateView]` |
48
- | Custom loading UI | `[loadingStateView]` |
49
- | Custom list item | `[listItemView]` on `<cometchat-conversations>`, `<cometchat-users>`, `<cometchat-groups>` |
64
+ | Custom empty state | `[emptyView]` on list / message components |
65
+ | Custom error UI | `[errorView]` |
66
+ | Custom loading UI | `[loadingView]` |
67
+ | Custom list row | `[itemView]` (or `[leadingView]`/`[titleView]`/`[subtitleView]`/`[trailingView]`) on list components |
50
68
  | Custom header subtitle | `[subtitleView]` on `<cometchat-message-header>` |
51
- | Custom header menu | `[menu]` on `<cometchat-message-header>` |
52
- | Hide receipts | `[hideReceipt]="true"` on `<cometchat-message-list>` |
53
- | Disable reactions | `[disableReactions]="true"` on `<cometchat-message-list>` |
69
+ | Hide receipts | `[hideReceipts]="true"` on `<cometchat-message-list>` |
70
+ | Disable a message action | the matching `[hide*Option]` flag (e.g. `[hideEditMessageOption]`) on `<cometchat-message-list>` |
54
71
  | Disable mentions | `[disableMentions]="true"` on `<cometchat-message-composer>` |
55
72
  | Custom send button | `[sendButtonView]` on `<cometchat-message-composer>` |
56
- | Custom attachment options | `[attachmentOptions]` on `<cometchat-message-composer>` |
57
- | Click handler on conversation | `[onItemClick]` on `<cometchat-conversations>` |
73
+ | Click handler on conversation | `(itemClick)` `@Output` on `<cometchat-conversations>` |
58
74
  | Active conversation highlight | `[activeConversation]` on `<cometchat-conversations>` |
59
75
 
60
- > **Note:** `[hideReactions]`, `[hideReplyInThreadOption]`, `[hideEditMessageOption]`, `[hideDeleteMessageOption]`, `[hideTranslateMessageOption]` do **not** exist in the Angular v4 UIKit. Use `[disableReactions]` for reactions. Message action options are controlled via the `[options]` callback or `[templates]` prop.
76
+ > **v5 hide flags ARE real on the message list** (unlike the old v4 kit, where most didn't exist). `<cometchat-message-list>` exposes `hideReplyInThreadOption`, `hideTranslateMessageOption`, `hideEditMessageOption`, `hideDeleteMessageOption`, `hideReactionOption`, `hideCopyMessageOption`, `hideMessageInfoOption`, `hideReplyOption`, `hideMessagePrivatelyOption`, `hideFlagMessageOption`, `hideReceipts`, `hideDateSeparator`, `hideAvatar`, and more. Prefer a `[hide*]` flag over `optionsOverride` when you just want to remove a built-in action. Confirm the exact flag in `cometchat-angular-components`.
61
77
 
62
- If a matching input exists, **add the input and stop**. No new components, no custom CSS, no new files.
78
+ If a matching input exists, **add the binding and stop**. No new components, no custom CSS, no new files.
63
79
 
64
80
  | If they want to... | Use Tier | Cost |
65
81
  |---|---|---|
66
- | Hide a feature (thread option, receipts, edit, etc.) | Tier 1 — `[hide*]` inputs | 1 line of HTML |
67
- | Customize a subsection (header subtitle, list item, empty state) | Tier 1 — `[*View]` / `[*Template]` slot | 1 `ng-template` |
68
- | Filter what loads (only show online users, exclude blocked, include tags) | Tier 2 — `[*RequestBuilder]` | 1 builder |
69
- | Change how URLs / mentions / hashtags / emojis render inline | Tier 3 — `[textFormatters]` | Subclass of `CometChatTextFormatter` |
70
- | Render a custom message type (custom bubble, custom interactive msg) | Tier 3 — `[templates]` + `CometChatMessageTemplate` | 1 template + 1 component |
71
- | React to events from another component | Tier 4 — `CometChatConversationEvents` / `CometChatMessageEvents` | RxJS subscription |
72
- | Rewrite how data flows through the kit | Tier 4 — `DataSourceDecorator` | Class extension |
82
+ | Hide a feature / built-in action | Tier 1 — `[hide*]` / `[hide*Option]` input | 1 line of HTML |
83
+ | Replace a subsection (header, list row, empty/error/loading state, bubble footer) | Tier 1 — `[*View]` slot + `<ng-template>` | 1 template |
84
+ | Filter what loads (only online users, joined groups, tagged conversations) | Tier 2 — `[*RequestBuilder]` | 1 builder |
85
+ | Change how URLs / mentions / hashtags render inline | Tier 3a — `[textFormatters]` | Subclass of `CometChatTextFormatter` |
86
+ | Add / remove / reorder message-action menu items | Tier 3b — `[additionalOptions]` / `[optionsOverride]` | `CometChatActionsIcon[]` |
87
+ | Render a custom view for a message type's bubble | Tier 3c — `MessageBubbleConfigService.setBubbleView` **or** `[bubbleFooterView]` / `[appendView]` | 1 template + 1 service call |
88
+ | React to kit activity (message sent, group left, conversation deleted) | Tier 4 — `CometChat*Events` | RxJS subscription |
73
89
 
74
- If a user's ask fits Tier 1 but you jumped to Tier 3, you've written 50 lines that a 1-line input could have replaced. Start low.
90
+ Start low. If an ask fits Tier 1 but you jumped to Tier 3, you've written 50 lines that one `[*View]` binding could have replaced.
75
91
 
76
92
  ---
77
93
 
78
- ## Tier 1 — Angular inputs (hide / slot views / styles)
94
+ ## Tier 1 — Slot views (`@Input` `ng-template`)
79
95
 
80
- ### 1a. `[hide*]` inputs
96
+ Every v5 list / message component exposes named slot-view `@Input`s that take a **`TemplateRef`**. In Angular you bind a `#ref` `<ng-template>` to the slot: `[itemView]="myTemplate"`. The kit passes the relevant item to the template via its `let-` context.
81
97
 
82
- Turn features off with a single input binding:
98
+ > **Get the slot names right.** They are component-specific. The list components (`<cometchat-conversations>`, `<cometchat-users>`, `<cometchat-groups>`, `<cometchat-group-members>`) expose: `headerView`, `menuView`, `loadingView`, `emptyView`, `errorView`, `itemView`, `leadingView`, `titleView`, `subtitleView`, `trailingView` (conversations also has `searchView`). The message list exposes a different set: `headerView`, `footerView`, `emptyView`, `errorView`, `loadingView`, `bubbleFooterView`, `appendView`. Always confirm per component in `cometchat-angular-components`.
83
99
 
84
- ```html
85
- <cometchat-message-list
86
- [user]="selectedUser"
87
- [hideReceipt]="true"
88
- [disableReactions]="false"
89
- [disableSoundForMessages]="false"
90
- ></cometchat-message-list>
91
- ```
92
-
93
- Real hide/disable inputs on `<cometchat-message-list>`: `[hideReceipt]`, `[hideError]`, `[hideDateSeparator]`, `[disableReactions]`, `[disableSoundForMessages]`, `[disableMentions]`.
94
-
95
- Full list of inputs per component: `cometchat-angular-components`. Check there before writing custom code.
96
-
97
- ### 1b. `ng-template` slot views — replace a section
98
-
99
- Every component has slot inputs for replacing named sections of its default UI. Pass an `ng-template` reference:
100
-
101
- ```html
102
- <cometchat-conversations
103
- [listItemView]="customListItem"
104
- ></cometchat-conversations>
105
-
106
- <ng-template #customListItem let-conversation>
107
- <div class="custom-item">
108
- <span class="name">{{ conversation.getConversationWith().getName() }}</span>
109
- <span class="time">{{ conversation.getLastMessage()?.getSentAt() | date:'shortTime' }}</span>
110
- </div>
111
- </ng-template>
112
- ```
100
+ ### 1a. Replace a list row
113
101
 
114
102
  ```typescript
115
- import { ViewChild, TemplateRef } from "@angular/core";
116
-
117
- @Component({ /* ... */ })
118
- export class AppComponent {
119
- @ViewChild("customListItem") customListItem!: TemplateRef<any>;
120
- }
103
+ // app-conversations.component.ts
104
+ import { Component } from "@angular/core";
105
+ import { CometChatConversationsComponent } from "@cometchat/chat-uikit-angular";
106
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
107
+ import { DatePipe } from "@angular/common";
108
+
109
+ @Component({
110
+ selector: "app-conversations",
111
+ standalone: true,
112
+ imports: [CometChatConversationsComponent, DatePipe],
113
+ template: `
114
+ <cometchat-conversations [itemView]="customItem">
115
+ </cometchat-conversations>
116
+
117
+ <ng-template #customItem let-conversation>
118
+ <div class="custom-item">
119
+ <span class="name">{{ conversation?.getConversationWith()?.getName() }}</span>
120
+ <span class="time">{{ conversation?.getLastMessage()?.getSentAt() * 1000 | date: 'shortTime' }}</span>
121
+ </div>
122
+ </ng-template>`,
123
+ })
124
+ export class AppConversationsComponent {}
121
125
  ```
122
126
 
123
- For the message header's subtitle:
127
+ The `<ng-template>` lives **inside** the same component's template, right after the kit component — Angular resolves the `#customItem` reference and hands the `TemplateRef` to the `[itemView]` `@Input`. No `@ViewChild` is required when the template is declared inline like this.
128
+
129
+ ### 1b. Replace the message-header subtitle
124
130
 
125
131
  ```html
126
- <cometchat-message-header
127
- [user]="selectedUser"
128
- [subtitleView]="customSubtitle"
129
- ></cometchat-message-header>
132
+ <cometchat-message-header [user]="selectedUser" [subtitleView]="customSubtitle">
133
+ </cometchat-message-header>
130
134
 
131
135
  <ng-template #customSubtitle let-user>
132
- <span style="color: #09C26F; font-size: 12px;">
133
- {{ user?.getStatus() === 'online' ? 'Online' : 'Offline' }}
136
+ <span style="color: var(--cometchat-success-color); font-size: 12px;">
137
+ {{ user?.getStatus() === 'online' ? 'Online now' : 'Offline' }}
134
138
  </span>
135
139
  </ng-template>
136
140
  ```
137
141
 
138
- ### 1c. `[*Style]` inputs per-component styling
142
+ ### 1c. Custom empty / error / loading state
139
143
 
140
- See `cometchat-angular-theming` § 4 for the full style object reference. Use `[*Style]` for one-off overrides on a single component instance.
144
+ ```html
145
+ <cometchat-users [emptyView]="noUsers" [loadingView]="spinner">
146
+ </cometchat-users>
147
+
148
+ <ng-template #noUsers><div class="empty">No teammates yet.</div></ng-template>
149
+ <ng-template #spinner><div class="loading">Loading…</div></ng-template>
150
+ ```
151
+
152
+ Keep any custom CSS to layout glue and consume `--cometchat-*` variables for colour / spacing / radius — see `cometchat-angular-theming`.
141
153
 
142
154
  ---
143
155
 
144
156
  ## Tier 2 — RequestBuilder filtering
145
157
 
146
- For "I want to show a subset of X", use the matching `[*RequestBuilder]`. Never post-filter in-render.
158
+ For "show a subset of X", use the matching `[*RequestBuilder]` `@Input`. The builders live on the **chat SDK** `CometChat` namespace. Never post-filter in-render with `*ngIf`.
147
159
 
148
160
  ```typescript
149
161
  import { CometChat } from "@cometchat/chat-sdk-javascript";
150
162
 
151
- // Only conversations in a specific tag group
163
+ // Only conversations tagged "premium", users only
152
164
  conversationsRequestBuilder = new CometChat.ConversationsRequestBuilder()
153
165
  .setLimit(20)
154
- .setUserTags(["premium"])
155
- .setConversationType(CometChat.RECEIVER_TYPE.USER);
166
+ .setTags(["premium"])
167
+ .setConversationType("user");
156
168
 
157
169
  // Only online users, exclude blocked
158
170
  usersRequestBuilder = new CometChat.UsersRequestBuilder()
159
171
  .setLimit(30)
160
- .setStatus("online")
172
+ .setStatus(CometChat.USER_STATUS.ONLINE)
161
173
  .hideBlockedUsers(true);
162
174
 
163
175
  // Only groups you've joined
@@ -165,117 +177,250 @@ groupsRequestBuilder = new CometChat.GroupsRequestBuilder()
165
177
  .setLimit(30)
166
178
  .joinedOnly(true);
167
179
 
168
- // Message list — exclude system messages
180
+ // Message list — exclude action/system messages
169
181
  messagesRequestBuilder = new CometChat.MessagesRequestBuilder()
170
- .setUID(this.selectedUser.getUid())
171
182
  .setLimit(30)
172
183
  .setCategories(["message"]);
173
184
  ```
174
185
 
186
+ ```html
187
+ <cometchat-conversations [conversationsRequestBuilder]="conversationsRequestBuilder">
188
+ </cometchat-conversations>
189
+ ```
190
+
191
+ > Construct request builders **once** (as class properties), not inside a getter or `ngOnInit` that re-runs — a new builder instance on every change-detection pass forces the list to refetch. Confirm exact builder method names against the chat SDK; they are SDK-side, not kit-side.
192
+
175
193
  ---
176
194
 
177
- ## Tier 3 — Text formatters + message templates
195
+ ## Tier 3 — Formatters + message-action options + per-type bubble views
178
196
 
179
- ### 3a. Custom text formatter — inline text patterns
197
+ ### 3a. Text formatters — inline text patterns
180
198
 
181
- `CometChatTextFormatter` is an abstract base class for matching inline text patterns and replacing them with custom HTML.
199
+ `[textFormatters]` is an `@Input` on `<cometchat-message-list>`, `<cometchat-message-composer>`, and `<cometchat-message-information>`, taking an array of `CometChatTextFormatter` instances.
200
+
201
+ **Built-in formatters** (all exported from `@cometchat/chat-uikit-angular`, all zero-arg constructors): `CometChatMentionsFormatter`, `CometChatUrlFormatter`, `CometChatEmojiFormatter`, `CometChatMarkdownFormatter`. (`CometChatTextFormatter` is the abstract base — you can't instantiate it directly.)
202
+
203
+ ```typescript
204
+ import {
205
+ CometChatMentionsFormatter,
206
+ CometChatUrlFormatter,
207
+ CometChatEmojiFormatter,
208
+ } from "@cometchat/chat-uikit-angular";
209
+
210
+ textFormatters = [
211
+ new CometChatMentionsFormatter(),
212
+ new CometChatUrlFormatter(),
213
+ new CometChatEmojiFormatter(),
214
+ ];
215
+ ```
216
+
217
+ ```html
218
+ <cometchat-message-list [user]="selectedUser" [textFormatters]="textFormatters">
219
+ </cometchat-message-list>
220
+ <cometchat-message-composer [user]="selectedUser" [textFormatters]="textFormatters">
221
+ </cometchat-message-composer>
222
+ ```
223
+
224
+ **⚠️ Pass the same `textFormatters` array to both list and composer.** If they differ, text renders differently while typing vs. after send.
225
+
226
+ **Custom formatter — the v5 API.** Extend `CometChatTextFormatter` and implement the abstract members. This is **different from v4** — there is no `setTrackingCharacter` / `setRegexPatterns` / `getFormattedText(input)` here. v5 requires: a readonly `id`, `getRegex()`, and `format(text)`; optionally override `shouldFormat()` and set `priority` (lower runs earlier; default 100).
182
227
 
183
228
  ```typescript
184
229
  // hashtag-formatter.ts
185
- import { CometChatTextFormatter } from "@cometchat/uikit-shared";
230
+ import { CometChatTextFormatter } from "@cometchat/chat-uikit-angular";
231
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
186
232
 
187
233
  export class HashtagFormatter extends CometChatTextFormatter {
188
- constructor() {
189
- super();
190
- this.setTrackingCharacter("#");
191
- this.setRegexPatterns([/\B#(\w+)\b/g]);
192
- this.setRegexToReplaceFormatting([/#(\w+)/g]);
234
+ readonly id = "hashtag-formatter";
235
+ override priority = 90;
236
+
237
+ getRegex(): RegExp {
238
+ return /\B#(\w+)\b/g;
193
239
  }
194
240
 
195
- override getFormattedText(inputText: string): string {
196
- if (!inputText) return "";
197
- return inputText.replace(
198
- /\B#(\w+)\b/g,
199
- '<span style="color: #6851D6; font-weight: 600;">#$1</span>'
241
+ format(text: string): string {
242
+ this.originalText = text ?? "";
243
+ this.formattedText = this.originalText.replace(
244
+ this.getRegex(),
245
+ '<span style="color: var(--cometchat-primary-color); font-weight: 600;">#$1</span>'
200
246
  );
247
+ return this.formattedText;
201
248
  }
202
249
 
203
- override getOriginalText(inputText: string): string {
204
- if (!inputText) return "";
205
- return inputText.replace(/<span[^>]*>(#\w+)<\/span>/g, "$1");
250
+ // Optional skip very short messages
251
+ override shouldFormat(text: string, _message?: CometChat.BaseMessage): boolean {
252
+ return !!text && text.length > 1;
206
253
  }
207
254
  }
208
255
  ```
209
256
 
210
- Register by passing to both `<cometchat-message-list>` and `<cometchat-message-composer>`:
211
-
212
257
  ```typescript
213
- // In your component:
214
258
  import { HashtagFormatter } from "./hashtag-formatter";
215
- import { CometChatMentionsFormatter, CometChatUrlsFormatter } from "@cometchat/uikit-shared";
259
+ import { CometChatMentionsFormatter, CometChatUrlFormatter } from "@cometchat/chat-uikit-angular";
216
260
 
217
261
  textFormatters = [
218
262
  new CometChatMentionsFormatter(),
219
- new CometChatUrlsFormatter([
220
- /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)/gi,
221
- ]),
263
+ new CometChatUrlFormatter(),
222
264
  new HashtagFormatter(),
223
265
  ];
224
266
  ```
225
267
 
268
+ > Construct formatter instances **once** at class level (as a property), not in `ngOnInit` or a getter. Recreating them every change-detection cycle drops their internal `originalText` / `formattedText` / metadata state.
269
+
270
+ ### 3b. Message-action menu — `additionalOptions` / `optionsOverride`
271
+
272
+ To **add** items to the per-message action menu, pass `CometChatActionsIcon[]` to `[additionalOptions]`. To **add / remove / reorder** items with full control, pass an `[optionsOverride]` callback `(message, defaultOptions) => CometChatActionsIcon[]`.
273
+
274
+ > **There is no `getMessageOptions` override point in the Angular kit** (unlike the web/React DataSource path). `getMessageOptions` exists only as an *internal* component method (`components/cometchat-message-list/cometchat-message-list.component.ts:398` → `cometchat-message-list.option-builders.ts`); the public override surface is the two `@Input`s below. Verified `@Input() additionalOptions: CometChatActionsIcon[]` (`cometchat-message-list.component.ts:174`) and `@Input() optionsOverride?: (message: CometChat.BaseMessage, defaultOptions: CometChatActionsIcon[]) => CometChatActionsIcon[]` (`cometchat-message-list.component.ts:175-178`). `CometChatActionsIcon` is exported from `@cometchat/chat-uikit-angular` (`modals/index.ts:9`) with constructor `{ id: string; title: string; iconURL: string; onClick: (id: number) => void }` (`modals/CometChatActionsIcon.ts`). A "Forward"-style action is built exactly this way — push a `CometChatActionsIcon` into `additionalOptions` (or reorder inside `optionsOverride`).
275
+
276
+ ```typescript
277
+ import { CometChatActionsIcon } from "@cometchat/chat-uikit-angular";
278
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
279
+
280
+ // Add a "Pin" action to every message's menu
281
+ additionalOptions: CometChatActionsIcon[] = [
282
+ new CometChatActionsIcon({
283
+ id: "pin",
284
+ title: "Pin",
285
+ iconURL: "assets/pin.svg",
286
+ onClick: (id: number) => {
287
+ // your pin handler — `id` is the message id
288
+ },
289
+ }),
290
+ ];
291
+
292
+ // Or rewrite the whole option set per message
293
+ optionsOverride = (
294
+ message: CometChat.BaseMessage,
295
+ defaultOptions: CometChatActionsIcon[]
296
+ ): CometChatActionsIcon[] => {
297
+ // e.g. drop the default options for system messages
298
+ if (message.getCategory() === "action") return [];
299
+ return [...defaultOptions, ...this.additionalOptions];
300
+ };
301
+ ```
302
+
226
303
  ```html
227
304
  <cometchat-message-list
228
305
  [user]="selectedUser"
229
- [textFormatters]="textFormatters"
230
- ></cometchat-message-list>
231
- <cometchat-message-composer
232
- [user]="selectedUser"
233
- [textFormatters]="textFormatters"
234
- ></cometchat-message-composer>
306
+ [additionalOptions]="additionalOptions"
307
+ [optionsOverride]="optionsOverride">
308
+ </cometchat-message-list>
309
+ ```
310
+
311
+ > To merely **hide** a built-in action, prefer the Tier 1 `[hide*Option]` flag — it's a single boolean and survives kit upgrades better than reconstructing the option array.
312
+
313
+ ### 3c. Custom bubble views per message type
314
+
315
+ v5 has **no `CometChatMessageTemplate` and no `templates` @Input**. Two supported paths:
316
+
317
+ **(i) Slot inputs on the message list** — for an extra row under existing bubbles, use `[bubbleFooterView]` (per-bubble footer) or `[appendView]` (after the bubble). Cheapest; no service.
318
+
319
+ ```html
320
+ <cometchat-message-list [user]="selectedUser" [bubbleFooterView]="myFooter">
321
+ </cometchat-message-list>
322
+
323
+ <ng-template #myFooter let-message>
324
+ <small class="bubble-meta">{{ message?.getId() }}</small>
325
+ </ng-template>
235
326
  ```
236
327
 
237
- **⚠️ Pass the same `textFormatters` array to both list and composer.** If they differ, messages look different when sent vs. received.
328
+ **(ii) `MessageBubbleConfigService`** — to replace a *part* of a specific message type's bubble globally (content, header, footer, etc.), inject the service and call `setBubbleView(messageTypeKey, partMap)`. `partMap` is a `BubblePartMap` whose keys are `bubbleView` / `contentView` / `bottomView` / `footerView` / `leadingView` / `headerView` / `statusInfoView` / `replyView` / `threadView`, each a `TemplateRef` (verified `BubblePartMap` in `@cometchat/chat-uikit-angular` — `services/message-bubble-config.types.ts:30-40`).
238
329
 
239
- ### 3b. Custom message template entire custom bubble
330
+ > **⚠️ The `messageTypeKey` is `"{type}_{category}"`, NOT just the type.** The kit builds its lookup key as `` `${message.getType()}_${message.getCategory()}` `` (`components/cometchat-message-bubble/cometchat-message-bubble.component.ts:322` consumed in `getEffectiveView` at line 332). A custom message sent with `type: "poll"` has category `"custom"` (`CometChat.CATEGORY_CUSTOM`), so its key is **`"poll_custom"`** — passing just `"poll"` silently never matches and your view never renders. The kit's own internal map confirms this format (`meeting_custom`, `extension_poll_custom`, … at lines 55-75). Built-in standard types follow the same rule: text is `"text_message"`, image is `"image_message"` (service docstring `message-bubble-config.service.ts:46-58`).
240
331
 
241
- For rendering a totally custom message type, use `CometChatMessageTemplate`.
332
+ ```typescript
333
+ import { Component, AfterViewInit, ViewChild, TemplateRef, inject } from "@angular/core";
334
+ import {
335
+ CometChatMessageListComponent,
336
+ MessageBubbleConfigService,
337
+ } from "@cometchat/chat-uikit-angular";
338
+
339
+ @Component({
340
+ selector: "app-chat",
341
+ standalone: true,
342
+ imports: [CometChatMessageListComponent],
343
+ template: `
344
+ <cometchat-message-list [user]="selectedUser"></cometchat-message-list>
345
+
346
+ <ng-template #pollContent let-message>
347
+ <div class="poll-card">{{ message?.getCustomData()?.question }}</div>
348
+ </ng-template>`,
349
+ })
350
+ export class AppChatComponent implements AfterViewInit {
351
+ private bubbleConfig = inject(MessageBubbleConfigService);
352
+ @ViewChild("pollContent") pollContent!: TemplateRef<any>;
353
+
354
+ ngAfterViewInit(): void {
355
+ // Replace only the content area of the "poll" custom message type.
356
+ // KEY = `${type}_${category}` → a custom message of type "poll" is category
357
+ // "custom", so the key is "poll_custom" (NOT "poll" — that would never match).
358
+ this.bubbleConfig.setBubbleView("poll_custom", { contentView: this.pollContent });
359
+ }
360
+ }
361
+ ```
362
+
363
+ `MessageBubbleConfigService` is `providedIn: 'root'`, so the config applies to every message list in the app. Call `setBubbleView` once (in `ngAfterViewInit`, after the `@ViewChild` template refs resolve). To render a genuinely new custom message type, register its `contentView` (above) **and send it through the kit** (next subsection) — not the raw SDK.
364
+
365
+ ### 3d. Sending a custom message type — use the UIKit path, not the raw SDK
366
+
367
+ When you create a brand-new message type (`type: "poll"`, `"location"`, …), send it with **`CometChatUIKit.sendCustomMessage(...)`**, never the raw `CometChat.sendCustomMessage(...)`. The UIKit wrapper sets `muid`, stamps the logged-in user as sender, and emits `ccMessageSent` — which is what makes the message **append** to the open list immediately. The raw SDK call skips all three, producing the two classic failures: *"Cannot determine message recipient"* (no proper sender/receiver wiring) and the realtime bubble **replacing an existing message** instead of appending (no `muid` for dedup).
242
368
 
243
369
  ```typescript
244
- // In your component:
245
- import { CometChatMessageTemplate } from "@cometchat/uikit-shared";
246
- import { ChatConfigurator } from "@cometchat/chat-uikit-angular";
247
-
248
- // Get default templates to merge with
249
- const defaultTemplates = ChatConfigurator.getDataSource().getAllMessageTemplates();
250
-
251
- // Create a custom template for a "poll" message type
252
- const pollTemplate = new CometChatMessageTemplate({
253
- type: "poll",
254
- category: "custom",
255
- ContentView: (message: CometChat.BaseMessage, alignment: string) => {
256
- // Return an Angular component reference or HTML string
257
- // For Angular, use a ViewContainerRef approach or pass a component factory
258
- return null; // implement with your Angular component
259
- },
260
- });
370
+ import { CometChatUIKit } from "@cometchat/chat-uikit-angular";
371
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
372
+
373
+ const receiverId = this.selectedUser.getUid(); // or group.getGuid()
374
+ const receiverType = CometChat.RECEIVER_TYPE.USER; // or .GROUP
375
+ const custom = new CometChat.CustomMessage(
376
+ receiverId,
377
+ receiverType,
378
+ "poll", // matches the contentView type
379
+ { question: "Lunch?", options: ["Yes", "No"] }
380
+ );
261
381
 
262
- messageTemplates = [pollTemplate, ...defaultTemplates];
382
+ // kit path — sets muid + sender, emits ccMessageSent → list appends
383
+ await CometChatUIKit.sendCustomMessage(custom);
384
+
385
+ // ❌ raw SDK — no muid/sender/event → "Cannot determine recipient" + realtime replace
386
+ // await CometChat.sendCustomMessage(custom);
263
387
  ```
264
388
 
389
+ Verified: `static sendCustomMessage(message: CometChat.CustomMessage): Promise<CometChat.BaseMessage>` on `CometChatUIKit` (`cometchat-uikit.ts:251`, exported from `@cometchat/chat-uikit-angular`). `CometChat.CustomMessage` has a variadic constructor (`...args: any[]`, `chat-sdk-javascript` `dist/type/lib/models/CustomMessage.d.ts:13`); the canonical 4-arg form is `(receiverId, receiverType, type, customData)`.
390
+
391
+ ### 3e. Custom attachment (composer) options — the `[attachmentOptions]` input is APPENDED to the defaults
392
+
393
+ `<cometchat-message-composer>` exposes `@Input() attachmentOptions?: CometChatMessageComposerAction[]` (verified `components/cometchat-message-composer/cometchat-message-composer.component.ts:137`). **In Angular v5 this is additive, NOT a replace** — the composer first builds the default menu (image / video / audio / file / polls / collaborative doc / whiteboard, each gated by its `hide*` flag), then **appends** your options: `if ((self.attachmentOptions?.length ?? 0) > 0) o.push(...self.attachmentOptions)` (verified `cometchat-message-composer.lifecycle-utils.ts:108`). So you pass **only your custom option(s)** and the defaults are preserved automatically — do NOT reconstruct the defaults yourself.
394
+
395
+ > ⚠️ This differs from the **React** kit, where the composer's `attachmentOptions` prop genuinely **replaces** the list (there you must seed from `getDataSource().getAttachmentOptions(...)`). Don't cross-port React's seed-the-defaults pattern to Angular — here it would duplicate every default option.
396
+
397
+ `CometChatMessageComposerAction` is exported from `@cometchat/chat-uikit-angular` (`modals/index.ts:11`); its constructor takes `Partial<CometChatMessageComposerAction>` with fields `id`, `iconURL`, `title?`, `onClick: (() => void) | null` (`modals/CometChatMessageComposerAction.ts`).
398
+
265
399
  ```html
266
- <cometchat-message-list
267
- [user]="selectedUser"
268
- [templates]="messageTemplates"
269
- ></cometchat-message-list>
400
+ <!-- ✅ "Send Location" is ADDED after the default photo/video/file/poll options -->
401
+ <cometchat-message-composer [attachmentOptions]="[locationOption]">
402
+ </cometchat-message-composer>
270
403
  ```
271
404
 
272
- ---
405
+ ```typescript
406
+ import { CometChatMessageComposerAction } from "@cometchat/chat-uikit-angular";
407
+
408
+ // Pass ONLY your custom option — the kit keeps its defaults and appends this.
409
+ locationOption = new CometChatMessageComposerAction({
410
+ id: "location",
411
+ title: "Send Location",
412
+ iconURL: "assets/location.svg",
413
+ onClick: () => this.shareLocation(),
414
+ });
415
+ ```
273
416
 
274
- ## Tier 4Event bus + DataSource decorators
417
+ To only *remove* built-in options (the common ask), do **not** touch `attachmentOptions` use the dedicated boolean inputs, which preserve everything else: `[hideImageAttachmentOption]`, `[hideVideoAttachmentOption]`, `[hideAudioAttachmentOption]`, `[hideFileAttachmentOption]`, `[hidePollsOption]`, `[hideCollaborativeDocumentOption]`, `[hideCollaborativeWhiteboardOption]`. All verified as `@Input`s on `CometChatMessageComposerComponent` (`components/cometchat-message-composer/cometchat-message-composer.component.ts:139-140`).
418
+
419
+ ---
275
420
 
276
- ### 4a. Event bus RxJS subscriptions
421
+ ## Tier 4 — Event bus (RxJS subscriptions)
277
422
 
278
- Subscribe to events that UI Kit components emit so your own code can react.
423
+ Subscribe to the kit's static event classes so your own code reacts to activity inside the UI Kit. All event classes are exported from `@cometchat/chat-uikit-angular` and expose `Subject`s you `.subscribe()` to.
279
424
 
280
425
  ```typescript
281
426
  import { Component, OnInit, OnDestroy } from "@angular/core";
@@ -287,126 +432,169 @@ import {
287
432
  } from "@cometchat/chat-uikit-angular";
288
433
  import { CometChat } from "@cometchat/chat-sdk-javascript";
289
434
 
290
- @Component({ /* ... */ })
435
+ @Component({ selector: "app-root", standalone: true, template: `...` })
291
436
  export class AppComponent implements OnInit, OnDestroy {
292
- private subscriptions: Subscription[] = [];
437
+ private subs: Subscription[] = [];
293
438
 
294
439
  ngOnInit(): void {
295
- this.subscriptions.push(
296
- CometChatMessageEvents.ccMessageSent.subscribe(
297
- ({ message, status }: { message: CometChat.BaseMessage; status: string }) => {
298
- if (status === "sent") {
299
- // analytics.track("message_sent", { id: message.getId() });
300
- }
301
- }
302
- ),
440
+ this.subs.push(
441
+ // payload is IMessages: { message, status, parentMessageId? }
442
+ CometChatMessageEvents.ccMessageSent.subscribe(({ message, status }) => {
443
+ // analytics.track("message_sent", { id: message.getId(), status });
444
+ }),
303
445
  CometChatConversationEvents.ccConversationDeleted.subscribe(
304
446
  (conversation: CometChat.Conversation) => {
305
- // Remove from local cache
447
+ // remove from local cache
306
448
  }
307
449
  ),
308
- CometChatGroupEvents.ccGroupLeft.subscribe(
309
- ({ userLeft, leftGroup }: any) => {
310
- // Handle group leave
311
- }
312
- )
450
+ CometChatGroupEvents.ccGroupLeft.subscribe((payload) => {
451
+ // payload is IGroupLeft
452
+ })
313
453
  );
314
454
  }
315
455
 
316
456
  ngOnDestroy(): void {
317
- this.subscriptions.forEach((sub) => sub.unsubscribe());
457
+ this.subs.forEach((s) => s.unsubscribe());
318
458
  }
319
459
  }
320
460
  ```
321
461
 
322
- **Always unsubscribe in `ngOnDestroy`.** Angular components are destroyed on navigation leaked subscriptions cause duplicate event handling.
462
+ **Always unsubscribe in `ngOnDestroy`.** Angular components are destroyed on navigation; leaked subscriptions fire handlers twice. (Each event class also exposes typed `on*(cb, destroyRef?)` helpers — e.g. `CometChatMessageEvents.onMessageSent(cb, destroyRef)` — that auto-clean up when you pass a `DestroyRef`; use those if you prefer not to track `Subscription`s manually.)
323
463
 
324
- ### Available event streams
464
+ ### Available event streams (verified subjects)
325
465
 
326
- | Event class | Key events |
466
+ | Event class | Key subjects |
327
467
  |---|---|
328
- | `CometChatMessageEvents` | `ccMessageSent`, `ccMessageEdited`, `ccMessageDeleted`, `ccMessageRead`, `ccLiveReaction` |
468
+ | `CometChatMessageEvents` | `ccMessageSent`, `ccMessageEdited`, `ccMessageDeleted`, `ccMessageRead`, `ccReplyToMessage`, `ccMessageTranslated` (+ low-level `onTextMessageReceived`, `onTypingStarted`, `onMessageReactionAdded`, …) |
329
469
  | `CometChatConversationEvents` | `ccConversationDeleted`, `ccUpdateConversation` |
330
- | `CometChatGroupEvents` | `ccGroupCreated`, `ccGroupDeleted`, `ccGroupLeft`, `ccGroupMemberScopeChanged`, `ccGroupMemberKicked`, `ccGroupMemberBanned`, `ccGroupMemberJoined`, `ccGroupMemberAdded`, `ccOwnershipChanged` |
470
+ | `CometChatGroupEvents` | `ccGroupCreated`, `ccGroupDeleted`, `ccGroupMemberJoined`, `ccGroupLeft`, `ccGroupMemberAdded`, `ccGroupMemberScopeChanged`, `ccGroupMemberKicked`, `ccGroupMemberBanned`, `ccGroupMemberUnbanned`, `ccOwnershipChanged` |
331
471
  | `CometChatUserEvents` | `ccUserBlocked`, `ccUserUnblocked` |
472
+ | `CometChatUIEvents` | `ccActiveChatChanged`, `ccOpenChat`, `ccShowOngoingCall`, `ccShowPanel`/`ccHidePanel`, `ccShowModal`/`ccHideModal`, `ccComposeMessage`, … |
473
+ | `CometChatCallEvents` | call lifecycle subjects (see `cometchat-angular-calls`) |
332
474
 
333
- ### 4b. DataSource decorators
475
+ Confirm the exact subject name and payload type in the bundled `.d.ts` before subscribing — some carry typed interfaces (`IMessages`, `IGroupLeft`, `IGroupMemberJoined`, `IActiveChatChanged`, …), not raw SDK objects.
334
476
 
335
- `DataSourceDecorator` wraps the kit's internal data source to override specific methods without forking the whole kit.
477
+ ---
336
478
 
337
- ```typescript
338
- import {
339
- DataSource,
340
- DataSourceDecorator,
341
- ChatConfigurator,
342
- } from "@cometchat/chat-uikit-angular";
479
+ ## Services / state-management layer
343
480
 
344
- class MyDataSource extends DataSourceDecorator {
345
- constructor(source: DataSource) {
346
- super(source);
347
- }
481
+ The kit ships a set of injectable services (verified in `projects/cometchat-uikit/src/lib/services/`, all exported from `@cometchat/chat-uikit-angular`). Most are `providedIn: 'root'` singletons; you `inject()` them and read **signals** (snapshot, template-friendly) or **`$` Observables** (RxJS). This is the seam below the `@Input` tiers above — use it for app-wide state and cross-component coordination, not per-instance tweaks.
348
482
 
349
- // Override only the method you want to change
350
- override getConversationsRequestBuilder() {
351
- const builder = super.getConversationsRequestBuilder();
352
- builder.setUserAndGroupTags(true);
353
- return builder;
354
- }
355
- }
483
+ ### `ChatStateService` the active-chat single source of truth
484
+
485
+ `providedIn: 'root'`. Holds the currently active `CometChat.User` / `CometChat.Group` / `CometChat.Conversation` and enforces **mutual exclusivity**: setting a user clears the active group and vice versa. The kit's list components (`<cometchat-conversations>`, `<cometchat-users>`, `<cometchat-groups>`) call its setters on selection, and the message components subscribe to it — so in the **service-based** wiring you place components in the template and they sync automatically with no `(itemClick)` plumbing.
486
+
487
+ Each piece of state is exposed **both** as a readonly signal and as an `$` Observable:
488
+
489
+ ```typescript
490
+ import { Component, inject } from "@angular/core";
491
+ import { ChatStateService } from "@cometchat/chat-uikit-angular";
492
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
356
493
 
357
- // Register before init — wraps the default data source
358
- ChatConfigurator.dataSource = new MyDataSource(ChatConfigurator.getDataSource());
359
- // Then call CometChatUIKit.init(settings)
494
+ @Component({
495
+ selector: "app-chat",
496
+ standalone: true,
497
+ template: `
498
+ <cometchat-conversations></cometchat-conversations>
499
+ @if (chatState.activeUser() || chatState.activeGroup()) {
500
+ <cometchat-message-header></cometchat-message-header>
501
+ <cometchat-message-list></cometchat-message-list>
502
+ <cometchat-message-composer></cometchat-message-composer>
503
+ }
504
+ `,
505
+ })
506
+ export class ChatComponent {
507
+ chatState = inject(ChatStateService);
508
+
509
+ // signals (snapshot / template): activeUser(), activeGroup(), activeConversation()
510
+ // observables: activeUser$, activeGroup$, activeConversation$ (subscribe in TS)
511
+ // setters: setActiveUser(u) | setActiveGroup(g) | setActiveConversation(c)
512
+ // snapshots: getActiveUser() | getActiveGroup() | getActiveChatEntity()
513
+ // teardown: clearActiveChat() ← call on logout / ngOnDestroy
514
+ }
360
515
  ```
361
516
 
362
- **This is an escape hatch, not a first tool.** Re-check whether Tier 1 (inputs) or Tier 3 (templates) could have solved it before reaching for Tier 4.
517
+ `setActiveConversation(c)` extracts the `User` or `Group` from the conversation and delegates to the right setter. Use the **props-based** alternative (`[user]` / `[group]` `@Input`s, Tier 1 wiring) instead of the service for multi-panel layouts where each panel needs independent state.
518
+
519
+ > **Don't scope `ChatStateService`** in a component's `providers: []` — it is intentionally an app-wide singleton; a local copy breaks cross-component sync. Use props for isolated panels instead.
520
+
521
+ ### The customization services — concise reference
522
+
523
+ All exported from `@cometchat/chat-uikit-angular`; `inject()` them. The two **search** services are `@Injectable()` (component-provided, not root) — they back the search components and you rarely inject them directly. The rest are `providedIn: 'root'`.
524
+
525
+ | Service | One-liner | Key members (verified) |
526
+ |---|---|---|
527
+ | `MessageBubbleConfigService` | Per-type / global bubble part overrides (Tier 3c) | `setBubbleView(type, partMap)`, `setGlobalView(part, ref)`, `setGlobalViews(map)`, `setMessageTemplates(record)`, `getView(type, part)`, `clearType(type)`, `clearAll()`; `configVersion` signal + `configChanged$` |
528
+ | `FormatterConfigService` | App-wide default text formatters (the `[textFormatters]` of Tier 3a, set once globally) | `getDefaultFormatters()`, `setDefaultFormatters(fmts)`, `addFormatters(fmts)`, `getFormattersWithContext(user?, alignment?)`, `resetToDefaults()` |
529
+ | `CometChatTemplatesService` | SDK-wide loading / empty / error / item templates for **all** list components at once | `setSharedTemplates(t)` (all lists) + per-component `setConversationTemplates` / `setUserTemplates` / `setGroupTemplates` / `setGroupMemberTemplates` / `setCallLogTemplates` / `setMessageListTemplates` / `setSearchTemplates`; each has matching `get*` / `clear*`; `clearAllTemplates()`. Every section also exposes a `*Templates` signal + `*Templates$` Observable. Priority: component `@Input` > component-service > shared > default |
530
+ | `RichTextEditorService` | Drives the rich-text composer (bold/italic/lists/links/mentions) | `createEditor(config?, el?)`, `destroyEditor(e)`, `toggleBold/Italic/Underline/Strikethrough/Code/CodeBlock/Blockquote/OrderedList/BulletList(e)`, `setLink(e, url, text?)`, `insertMention(e, id, label, n)`, `getHTML(e)` / `getText(e)` / `getTextWithMentionFormat(e)`, `undo/redo(e)`; `formatState` signal |
531
+ | `SearchConversationsService` | Backs conversation search — query + live-listener state | `search(keyword, filters, builder?)`, `loadMore()`, `attachListeners(user)` / `detachListeners()`, `reset()`; `conversations`, `fetchState`, `hasMoreResults`, `typingIndicatorMap` signals |
532
+ | `SearchMessagesService` | Backs message search | `search(keyword, filters, uid?, guid?, builder?, alwaysShowSeeMore?)`, `loadMore()`, `reset()`; `messages`, `fetchState`, `hasMoreResults` signals |
533
+
534
+ `FormatterConfigService`, `MessageBubbleConfigService`, `CometChatTemplatesService`, and `RichTextEditorService` are the four services you *can* deliberately re-provide in a component's `providers: []` to scope a customization to one subtree (e.g. a thread panel with minimal styling) without touching the global singleton — they cross-link directly to the formatter (Tier 3a), bubble (Tier 3c), and slot-template (Tier 1) work above.
535
+
536
+ > **Read signals in templates, subscribe to `$` Observables in TS.** Don't call `.subscribe()` on a signal or invoke an Observable like a function — they are distinct APIs on the same state.
363
537
 
364
538
  ---
365
539
 
366
- ## 5. Recipes (common customization asks → right tier)
540
+ ## Recipes (common asks → right tier)
367
541
 
368
542
  ### "Filter the conversation list to just premium users"
369
- **Tier 2** — `[conversationsRequestBuilder]` with `.setUserTags(["premium"])`.
543
+ **Tier 2** — `[conversationsRequestBuilder]` with `.setTags(["premium"])`.
370
544
 
371
545
  ### "Custom empty state for the users list"
372
- **Tier 1** — `[emptyStateView]` slot input on `<cometchat-users>`.
546
+ **Tier 1** — `[emptyView]` slot on `<cometchat-users>`.
373
547
 
374
- ### "Custom list item for conversations"
375
- **Tier 1** — `[listItemView]` slot input on `<cometchat-conversations>`.
548
+ ### "Custom row for conversations"
549
+ **Tier 1** — `[itemView]` slot on `<cometchat-conversations>`.
376
550
 
377
- ### "Show a custom view when the user types @"
378
- **Tier 3a** — subclass `CometChatMentionsFormatter`, implement `search(key)` with your own suggestion source.
551
+ ### "Highlight hashtags in messages"
552
+ **Tier 3a** — subclass `CometChatTextFormatter` (`id` + `getRegex()` + `format()`), pass it in `textFormatters` to list AND composer.
379
553
 
380
- ### "When a message is sent, log it to our analytics"
381
- **Tier 4a** — `CometChatMessageEvents.ccMessageSent.subscribe(...)`.
554
+ ### "Add a 'Pin message' action to the menu"
555
+ **Tier 3b** — push a `CometChatActionsIcon` into `[additionalOptions]`.
382
556
 
383
- ### "When a group is deleted, navigate away"
384
- **Tier 4a** — `CometChatGroupEvents.ccGroupDeleted.subscribe(...)`.
557
+ ### "Remove the Translate action"
558
+ **Tier 1** — `[hideTranslateMessageOption]="true"` on `<cometchat-message-list>`.
559
+
560
+ ### "Render a custom card for our 'poll' message type"
561
+ **Tier 3c** — `MessageBubbleConfigService.setBubbleView("poll_custom", { contentView: tmplRef })`. The key is `"{type}_{category}"` — a `type: "poll"` custom message is category `custom`, so the key is `poll_custom`, not `poll`.
385
562
 
386
- ### "Render custom avatars for all users based on their department"
387
- **Tier 1** — `[listItemView]` slot on `<cometchat-conversations>` + `<cometchat-users>`.
563
+ ### "When a message is sent, log it to analytics"
564
+ **Tier 4** — `CometChatMessageEvents.ccMessageSent.subscribe(({ message }) => …)`.
388
565
 
389
- ### "Disable the file attachment option"
390
- **Tier 1** — filter the `[attachmentOptions]` input on `<cometchat-message-composer>`.
566
+ ### "When a group is deleted, navigate away"
567
+ **Tier 4** — `CometChatGroupEvents.ccGroupDeleted.subscribe(group => router.navigate([...]))`.
568
+
569
+ ### "Sync the active conversation across my own components"
570
+ **Services** — `inject(ChatStateService)`; read `activeUser()` / `activeGroup()` signals (or `activeUser$` / `activeGroup$`), set with `setActiveConversation(c)`, clear with `clearActiveChat()`.
391
571
 
392
- ### "Custom message type: a 'ping' message"
393
- **Tier 3b** — create a `CometChatMessageTemplate` with `category: "custom"` + `type: "ping"`, render a custom Angular component, send via `CometChat.sendCustomMessage`.
572
+ ### "Apply one branded empty/loading state to every list at once"
573
+ **Services** — `CometChatTemplatesService.setSharedTemplates({ loadingView, emptyView })`; override a single list with `setUserTemplates(...)` etc.
394
574
 
395
575
  ---
396
576
 
397
- ## 6. Anti-patterns
577
+ ## Anti-patterns
578
+
579
+ 1. **Don't reach for v4 symbols.** `CometChatMessageTemplate`, `DataSource`, `DataSourceDecorator`, `ChatConfigurator`, `CometChatThemeService`, `CometChatUrlsFormatter` (plural), and the v4 `CometChatTextFormatter` API are all **phantom in v5**. They will fail to import.
580
+
581
+ 2. **Don't expect a `templates` @Input on `<cometchat-message-list>`.** It doesn't exist in v5. Custom bubbles go through `MessageBubbleConfigService.setBubbleView` or the `bubbleFooterView` / `appendView` slots.
398
582
 
399
- 1. **Don't hand-roll a bubble when a template will do.** `CometChatMessageTemplate` (Tier 3b) gives you full control over rendering + options without losing theming, reactions, typing, receipts.
583
+ 3. **Don't write the v4 formatter shape.** v5 formatters need `id` + `getRegex()` + `format(text)` not `setTrackingCharacter` / `setRegexPatterns` / `getFormattedText(input)`.
400
584
 
401
- 2. **Don't post-filter a list's data after render.** If you want "only online users," use Tier 2 `usersRequestBuilder.setStatus("online")` — don't fetch everyone then hide rows with `*ngIf`.
585
+ 4. **Don't pass different `textFormatters` arrays** to the list and the composer text will render inconsistently.
402
586
 
403
- 3. **Don't forget to unsubscribe in `ngOnDestroy`.** Angular components are destroyed on navigation; leaked subscriptions cause duplicate event handling.
587
+ 5. **Don't post-filter a list after render.** For "only online users", use Tier 2 `usersRequestBuilder.setStatus(...)`; don't fetch everyone and hide rows with `*ngIf`.
404
588
 
405
- 4. **Don't put `CometChatTextFormatter` instances in component state that gets recreated.** Construct them once at class level (as a property, not in `ngOnInit`); re-creating them on every change detection cycle loses the internal suggestion state.
589
+ 6. **Don't construct formatters or request builders inside a getter / `ngOnInit` that re-runs.** Build them once as class properties recreating them per change-detection cycle drops formatter state or forces list refetches.
406
590
 
407
- 5. **Don't fork or patch `@cometchat/chat-uikit-angular` directly.** Every customization should be possible via Tiers 1-4. Forking breaks on kit upgrades.
591
+ 7. **Don't forget `ngOnDestroy` unsubscribe** (or pass a `DestroyRef` to the `on*` helpers). Leaked subscriptions double-fire after navigation.
408
592
 
409
- 6. **Don't reach for Tier 4 before trying 1-3.** DataSource decorators are powerful but fragile to kit internal changes. Inputs, request builders, and templates are stable surface area.
593
+ 8. **Don't add `CUSTOM_ELEMENTS_SCHEMA`** v5 components are real Angular standalone components; import the class into `imports: []`.
594
+
595
+ 9. **Don't fork or patch `@cometchat/chat-uikit-angular`.** Every customization here is achievable via Tiers 1–4. Forking breaks on kit upgrades.
596
+
597
+ 10. **Don't escalate past Tier 1 without checking the catalog.** A `[hide*]` flag or a `[*View]` slot solves most asks in one line.
410
598
 
411
599
  ---
412
600
 
@@ -414,11 +602,15 @@ ChatConfigurator.dataSource = new MyDataSource(ChatConfigurator.getDataSource())
414
602
 
415
603
  | Skill | When to route |
416
604
  |---|---|
417
- | `cometchat-angular-core` | Init / login / module setup |
418
- | `cometchat-angular-components` | Input reference which `[hide*]`, `[*View]`, `[*RequestBuilder]` is available |
605
+ | `cometchat-angular-core` | Init / login / standalone setup — read first |
606
+ | `cometchat-angular-components` | The `@Input`/`@Output`/slot-view reference these tiers build on |
419
607
  | `cometchat-angular-placement` | Where to put the customized components |
420
- | `cometchat-angular-theming` | App-wide color / typography Tier 1 alternative to `[*Style]` |
421
- | `cometchat-angular-features` | Which out-of-the-box features exist |
422
- | `cometchat-angular-customization` | This skill — four-tier triage + custom formatters / templates / DataSource / events |
608
+ | `cometchat-angular-theming` | App-wide colour / typography via CSS variables |
609
+ | `cometchat-angular-features` | Out-of-the-box features (calls, extensions, AI) |
610
+ | `cometchat-angular-customization` | This skill — four-tier triage + formatters / options / bubble views / events |
423
611
  | `cometchat-angular-production` | When customization depends on production auth |
424
- | `cometchat-angular-troubleshooting` | Formatter doesn't apply, listener fires twice, slot view renders nothing |
612
+ | `cometchat-angular-troubleshooting` | Formatter doesn't apply, slot renders nothing, listener fires twice |
613
+
614
+ ## Sound (in-app message + call sounds)
615
+
616
+ Sound is a customization sub-dimension. The UI Kit plays incoming/outgoing message + call sounds via `CometChatSoundManager` — mute it, swap custom audio, or play a specific sound. The full API + recipe lives in **`cometchat-angular-theming`** (Sound section). Verify the access path against the installed kit before relying on it.