@cometchat/skills 3.0.0 → 4.0.0

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 (101) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -17
  3. package/bin/install.js +389 -43
  4. package/package.json +19 -9
  5. package/skills/cometchat/SKILL.md +1066 -265
  6. package/skills/cometchat-android-v5/SKILL.md +120 -0
  7. package/skills/cometchat-android-v5-components/SKILL.md +430 -0
  8. package/skills/cometchat-android-v5-core/SKILL.md +468 -0
  9. package/skills/cometchat-android-v5-customization/SKILL.md +305 -0
  10. package/skills/cometchat-android-v5-extensions/SKILL.md +124 -0
  11. package/skills/cometchat-android-v5-features/SKILL.md +130 -0
  12. package/skills/cometchat-android-v5-placement/SKILL.md +276 -0
  13. package/skills/cometchat-android-v5-production/SKILL.md +94 -0
  14. package/skills/cometchat-android-v5-push/SKILL.md +620 -0
  15. package/skills/cometchat-android-v5-testing/SKILL.md +187 -0
  16. package/skills/cometchat-android-v5-theming/SKILL.md +166 -0
  17. package/skills/cometchat-android-v5-troubleshooting/SKILL.md +73 -0
  18. package/skills/cometchat-android-v6/SKILL.md +107 -0
  19. package/skills/cometchat-android-v6-builder-settings/SKILL.md +145 -0
  20. package/skills/cometchat-android-v6-compose-components/SKILL.md +202 -0
  21. package/skills/cometchat-android-v6-compose-customization/SKILL.md +280 -0
  22. package/skills/cometchat-android-v6-compose-placement/SKILL.md +213 -0
  23. package/skills/cometchat-android-v6-compose-theming/SKILL.md +224 -0
  24. package/skills/cometchat-android-v6-core/SKILL.md +354 -0
  25. package/skills/cometchat-android-v6-events/SKILL.md +212 -0
  26. package/skills/cometchat-android-v6-extensions/SKILL.md +191 -0
  27. package/skills/cometchat-android-v6-features/SKILL.md +130 -0
  28. package/skills/cometchat-android-v6-kotlin-components/SKILL.md +197 -0
  29. package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +268 -0
  30. package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +248 -0
  31. package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +202 -0
  32. package/skills/cometchat-android-v6-production/SKILL.md +187 -0
  33. package/skills/cometchat-android-v6-push/SKILL.md +274 -0
  34. package/skills/cometchat-android-v6-testing/SKILL.md +279 -0
  35. package/skills/cometchat-android-v6-troubleshooting/SKILL.md +249 -0
  36. package/skills/cometchat-angular-components/SKILL.md +706 -0
  37. package/skills/cometchat-angular-core/SKILL.md +444 -0
  38. package/skills/cometchat-angular-customization/SKILL.md +424 -0
  39. package/skills/cometchat-angular-features/SKILL.md +447 -0
  40. package/skills/cometchat-angular-patterns/SKILL.md +447 -0
  41. package/skills/cometchat-angular-placement/SKILL.md +685 -0
  42. package/skills/cometchat-angular-production/SKILL.md +415 -0
  43. package/skills/cometchat-angular-theming/SKILL.md +365 -0
  44. package/skills/cometchat-angular-troubleshooting/SKILL.md +329 -0
  45. package/skills/cometchat-astro-patterns/SKILL.md +3 -3
  46. package/skills/cometchat-components/SKILL.md +11 -0
  47. package/skills/cometchat-core/SKILL.md +11 -6
  48. package/skills/cometchat-customization/references/component-catalog.md +1 -1
  49. package/skills/cometchat-features/SKILL.md +176 -108
  50. package/skills/cometchat-flutter-v5/SKILL.md +167 -0
  51. package/skills/cometchat-flutter-v5-calls/SKILL.md +192 -0
  52. package/skills/cometchat-flutter-v5-conversations/SKILL.md +117 -0
  53. package/skills/cometchat-flutter-v5-core/SKILL.md +221 -0
  54. package/skills/cometchat-flutter-v5-customization/SKILL.md +227 -0
  55. package/skills/cometchat-flutter-v5-events/SKILL.md +155 -0
  56. package/skills/cometchat-flutter-v5-messages/SKILL.md +258 -0
  57. package/skills/cometchat-flutter-v5-production/SKILL.md +207 -0
  58. package/skills/cometchat-flutter-v5-push/SKILL.md +284 -0
  59. package/skills/cometchat-flutter-v5-theming/SKILL.md +160 -0
  60. package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +129 -0
  61. package/skills/cometchat-flutter-v5-users-groups/SKILL.md +151 -0
  62. package/skills/cometchat-flutter-v6/SKILL.md +445 -0
  63. package/skills/cometchat-flutter-v6-calls/SKILL.md +333 -0
  64. package/skills/cometchat-flutter-v6-components/SKILL.md +365 -0
  65. package/skills/cometchat-flutter-v6-conversations/SKILL.md +210 -0
  66. package/skills/cometchat-flutter-v6-core/SKILL.md +305 -0
  67. package/skills/cometchat-flutter-v6-customization/SKILL.md +666 -0
  68. package/skills/cometchat-flutter-v6-events/SKILL.md +216 -0
  69. package/skills/cometchat-flutter-v6-features/SKILL.md +406 -0
  70. package/skills/cometchat-flutter-v6-messages/SKILL.md +333 -0
  71. package/skills/cometchat-flutter-v6-migration/SKILL.md +381 -0
  72. package/skills/cometchat-flutter-v6-placement/SKILL.md +398 -0
  73. package/skills/cometchat-flutter-v6-production/SKILL.md +632 -0
  74. package/skills/cometchat-flutter-v6-theming/SKILL.md +260 -0
  75. package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +726 -0
  76. package/skills/cometchat-flutter-v6-users-groups/SKILL.md +216 -0
  77. package/skills/cometchat-ios/SKILL.md +323 -0
  78. package/skills/cometchat-ios-components/SKILL.md +651 -0
  79. package/skills/cometchat-ios-core/SKILL.md +822 -0
  80. package/skills/cometchat-ios-customization/SKILL.md +825 -0
  81. package/skills/cometchat-ios-features/SKILL.md +725 -0
  82. package/skills/cometchat-ios-placement/SKILL.md +750 -0
  83. package/skills/cometchat-ios-production/SKILL.md +730 -0
  84. package/skills/cometchat-ios-push/SKILL.md +582 -0
  85. package/skills/cometchat-ios-theming/SKILL.md +631 -0
  86. package/skills/cometchat-ios-troubleshooting/SKILL.md +983 -0
  87. package/skills/cometchat-native-bare-patterns/SKILL.md +470 -0
  88. package/skills/cometchat-native-components/SKILL.md +594 -0
  89. package/skills/cometchat-native-core/SKILL.md +407 -0
  90. package/skills/cometchat-native-customization/SKILL.md +594 -0
  91. package/skills/cometchat-native-expo-patterns/SKILL.md +485 -0
  92. package/skills/cometchat-native-features/SKILL.md +608 -0
  93. package/skills/cometchat-native-placement/SKILL.md +500 -0
  94. package/skills/cometchat-native-production/SKILL.md +694 -0
  95. package/skills/cometchat-native-push/SKILL.md +593 -0
  96. package/skills/cometchat-native-testing/SKILL.md +583 -0
  97. package/skills/cometchat-native-theming/SKILL.md +656 -0
  98. package/skills/cometchat-native-troubleshooting/SKILL.md +433 -0
  99. package/skills/cometchat-nextjs-patterns/SKILL.md +5 -5
  100. package/skills/cometchat-production/SKILL.md +60 -0
  101. package/skills/cometchat-react-router-patterns/SKILL.md +23 -21
@@ -0,0 +1,424 @@
1
+ ---
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."
4
+ license: "MIT"
5
+ compatibility: "Angular >=12 <=15; @cometchat/chat-uikit-angular ^4; @cometchat/chat-sdk-javascript ^4"
6
+ allowed-tools: "executeBash, readFile, fileSearch, listDirectory, AskUserQuestion"
7
+ metadata:
8
+ author: "CometChat"
9
+ version: "3.0.0"
10
+ tags: "cometchat angular customization formatters events datasource templates ng-template"
11
+ ---
12
+
13
+ ## Purpose
14
+
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:
16
+
17
+ ```
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)
22
+ ```
23
+
24
+ **Always try Tier 1 first.** Escalate only when the tier can't do what the user wants.
25
+
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.
27
+
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.
29
+
30
+ ---
31
+
32
+ ## Four-tier triage — pick the right tier before writing any code
33
+
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.
35
+
36
+ ### Quick task → input lookup
37
+
38
+ Before escalating to any tier, check if an existing component input already does what you need:
39
+
40
+ | User asks for | Likely input on which component |
41
+ |---|---|
42
+ | Search bar | `[hideSearch]="false"` on `<cometchat-conversations>`, `<cometchat-users>`, `<cometchat-groups>` |
43
+ | Filter conversations | `[conversationsRequestBuilder]` on `<cometchat-conversations>` |
44
+ | Filter messages | `[messagesRequestBuilder]` on `<cometchat-message-list>` |
45
+ | 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>` |
50
+ | 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>` |
54
+ | Disable mentions | `[disableMentions]="true"` on `<cometchat-message-composer>` |
55
+ | 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>` |
58
+ | Active conversation highlight | `[activeConversation]` on `<cometchat-conversations>` |
59
+
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.
61
+
62
+ If a matching input exists, **add the input and stop**. No new components, no custom CSS, no new files.
63
+
64
+ | If they want to... | Use Tier | Cost |
65
+ |---|---|---|
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 |
73
+
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.
75
+
76
+ ---
77
+
78
+ ## Tier 1 — Angular inputs (hide / slot views / styles)
79
+
80
+ ### 1a. `[hide*]` inputs
81
+
82
+ Turn features off with a single input binding:
83
+
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
+ ```
113
+
114
+ ```typescript
115
+ import { ViewChild, TemplateRef } from "@angular/core";
116
+
117
+ @Component({ /* ... */ })
118
+ export class AppComponent {
119
+ @ViewChild("customListItem") customListItem!: TemplateRef<any>;
120
+ }
121
+ ```
122
+
123
+ For the message header's subtitle:
124
+
125
+ ```html
126
+ <cometchat-message-header
127
+ [user]="selectedUser"
128
+ [subtitleView]="customSubtitle"
129
+ ></cometchat-message-header>
130
+
131
+ <ng-template #customSubtitle let-user>
132
+ <span style="color: #09C26F; font-size: 12px;">
133
+ {{ user?.getStatus() === 'online' ? 'Online' : 'Offline' }}
134
+ </span>
135
+ </ng-template>
136
+ ```
137
+
138
+ ### 1c. `[*Style]` inputs — per-component styling
139
+
140
+ See `cometchat-angular-theming` § 4 for the full style object reference. Use `[*Style]` for one-off overrides on a single component instance.
141
+
142
+ ---
143
+
144
+ ## Tier 2 — RequestBuilder filtering
145
+
146
+ For "I want to show a subset of X", use the matching `[*RequestBuilder]`. Never post-filter in-render.
147
+
148
+ ```typescript
149
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
150
+
151
+ // Only conversations in a specific tag group
152
+ conversationsRequestBuilder = new CometChat.ConversationsRequestBuilder()
153
+ .setLimit(20)
154
+ .setUserTags(["premium"])
155
+ .setConversationType(CometChat.RECEIVER_TYPE.USER);
156
+
157
+ // Only online users, exclude blocked
158
+ usersRequestBuilder = new CometChat.UsersRequestBuilder()
159
+ .setLimit(30)
160
+ .setStatus("online")
161
+ .hideBlockedUsers(true);
162
+
163
+ // Only groups you've joined
164
+ groupsRequestBuilder = new CometChat.GroupsRequestBuilder()
165
+ .setLimit(30)
166
+ .joinedOnly(true);
167
+
168
+ // Message list — exclude system messages
169
+ messagesRequestBuilder = new CometChat.MessagesRequestBuilder()
170
+ .setUID(this.selectedUser.getUid())
171
+ .setLimit(30)
172
+ .setCategories(["message"]);
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Tier 3 — Text formatters + message templates
178
+
179
+ ### 3a. Custom text formatter — inline text patterns
180
+
181
+ `CometChatTextFormatter` is an abstract base class for matching inline text patterns and replacing them with custom HTML.
182
+
183
+ ```typescript
184
+ // hashtag-formatter.ts
185
+ import { CometChatTextFormatter } from "@cometchat/uikit-shared";
186
+
187
+ export class HashtagFormatter extends CometChatTextFormatter {
188
+ constructor() {
189
+ super();
190
+ this.setTrackingCharacter("#");
191
+ this.setRegexPatterns([/\B#(\w+)\b/g]);
192
+ this.setRegexToReplaceFormatting([/#(\w+)/g]);
193
+ }
194
+
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>'
200
+ );
201
+ }
202
+
203
+ override getOriginalText(inputText: string): string {
204
+ if (!inputText) return "";
205
+ return inputText.replace(/<span[^>]*>(#\w+)<\/span>/g, "$1");
206
+ }
207
+ }
208
+ ```
209
+
210
+ Register by passing to both `<cometchat-message-list>` and `<cometchat-message-composer>`:
211
+
212
+ ```typescript
213
+ // In your component:
214
+ import { HashtagFormatter } from "./hashtag-formatter";
215
+ import { CometChatMentionsFormatter, CometChatUrlsFormatter } from "@cometchat/uikit-shared";
216
+
217
+ textFormatters = [
218
+ 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
+ ]),
222
+ new HashtagFormatter(),
223
+ ];
224
+ ```
225
+
226
+ ```html
227
+ <cometchat-message-list
228
+ [user]="selectedUser"
229
+ [textFormatters]="textFormatters"
230
+ ></cometchat-message-list>
231
+ <cometchat-message-composer
232
+ [user]="selectedUser"
233
+ [textFormatters]="textFormatters"
234
+ ></cometchat-message-composer>
235
+ ```
236
+
237
+ **⚠️ Pass the same `textFormatters` array to both list and composer.** If they differ, messages look different when sent vs. received.
238
+
239
+ ### 3b. Custom message template — entire custom bubble
240
+
241
+ For rendering a totally custom message type, use `CometChatMessageTemplate`.
242
+
243
+ ```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
+ });
261
+
262
+ messageTemplates = [pollTemplate, ...defaultTemplates];
263
+ ```
264
+
265
+ ```html
266
+ <cometchat-message-list
267
+ [user]="selectedUser"
268
+ [templates]="messageTemplates"
269
+ ></cometchat-message-list>
270
+ ```
271
+
272
+ ---
273
+
274
+ ## Tier 4 — Event bus + DataSource decorators
275
+
276
+ ### 4a. Event bus — RxJS subscriptions
277
+
278
+ Subscribe to events that UI Kit components emit so your own code can react.
279
+
280
+ ```typescript
281
+ import { Component, OnInit, OnDestroy } from "@angular/core";
282
+ import { Subscription } from "rxjs";
283
+ import {
284
+ CometChatMessageEvents,
285
+ CometChatConversationEvents,
286
+ CometChatGroupEvents,
287
+ } from "@cometchat/chat-uikit-angular";
288
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
289
+
290
+ @Component({ /* ... */ })
291
+ export class AppComponent implements OnInit, OnDestroy {
292
+ private subscriptions: Subscription[] = [];
293
+
294
+ 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
+ ),
303
+ CometChatConversationEvents.ccConversationDeleted.subscribe(
304
+ (conversation: CometChat.Conversation) => {
305
+ // Remove from local cache
306
+ }
307
+ ),
308
+ CometChatGroupEvents.ccGroupLeft.subscribe(
309
+ ({ userLeft, leftGroup }: any) => {
310
+ // Handle group leave
311
+ }
312
+ )
313
+ );
314
+ }
315
+
316
+ ngOnDestroy(): void {
317
+ this.subscriptions.forEach((sub) => sub.unsubscribe());
318
+ }
319
+ }
320
+ ```
321
+
322
+ **Always unsubscribe in `ngOnDestroy`.** Angular components are destroyed on navigation — leaked subscriptions cause duplicate event handling.
323
+
324
+ ### Available event streams
325
+
326
+ | Event class | Key events |
327
+ |---|---|
328
+ | `CometChatMessageEvents` | `ccMessageSent`, `ccMessageEdited`, `ccMessageDeleted`, `ccMessageRead`, `ccLiveReaction` |
329
+ | `CometChatConversationEvents` | `ccConversationDeleted`, `ccUpdateConversation` |
330
+ | `CometChatGroupEvents` | `ccGroupCreated`, `ccGroupDeleted`, `ccGroupLeft`, `ccGroupMemberScopeChanged`, `ccGroupMemberKicked`, `ccGroupMemberBanned`, `ccGroupMemberJoined`, `ccGroupMemberAdded`, `ccOwnershipChanged` |
331
+ | `CometChatUserEvents` | `ccUserBlocked`, `ccUserUnblocked` |
332
+
333
+ ### 4b. DataSource decorators
334
+
335
+ `DataSourceDecorator` wraps the kit's internal data source to override specific methods without forking the whole kit.
336
+
337
+ ```typescript
338
+ import {
339
+ DataSource,
340
+ DataSourceDecorator,
341
+ ChatConfigurator,
342
+ } from "@cometchat/chat-uikit-angular";
343
+
344
+ class MyDataSource extends DataSourceDecorator {
345
+ constructor(source: DataSource) {
346
+ super(source);
347
+ }
348
+
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
+ }
356
+
357
+ // Register before init — wraps the default data source
358
+ ChatConfigurator.dataSource = new MyDataSource(ChatConfigurator.getDataSource());
359
+ // Then call CometChatUIKit.init(settings)
360
+ ```
361
+
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.
363
+
364
+ ---
365
+
366
+ ## 5. Recipes (common customization asks → right tier)
367
+
368
+ ### "Filter the conversation list to just premium users"
369
+ **Tier 2** — `[conversationsRequestBuilder]` with `.setUserTags(["premium"])`.
370
+
371
+ ### "Custom empty state for the users list"
372
+ **Tier 1** — `[emptyStateView]` slot input on `<cometchat-users>`.
373
+
374
+ ### "Custom list item for conversations"
375
+ **Tier 1** — `[listItemView]` slot input on `<cometchat-conversations>`.
376
+
377
+ ### "Show a custom view when the user types @"
378
+ **Tier 3a** — subclass `CometChatMentionsFormatter`, implement `search(key)` with your own suggestion source.
379
+
380
+ ### "When a message is sent, log it to our analytics"
381
+ **Tier 4a** — `CometChatMessageEvents.ccMessageSent.subscribe(...)`.
382
+
383
+ ### "When a group is deleted, navigate away"
384
+ **Tier 4a** — `CometChatGroupEvents.ccGroupDeleted.subscribe(...)`.
385
+
386
+ ### "Render custom avatars for all users based on their department"
387
+ **Tier 1** — `[listItemView]` slot on `<cometchat-conversations>` + `<cometchat-users>`.
388
+
389
+ ### "Disable the file attachment option"
390
+ **Tier 1** — filter the `[attachmentOptions]` input on `<cometchat-message-composer>`.
391
+
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`.
394
+
395
+ ---
396
+
397
+ ## 6. Anti-patterns
398
+
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.
400
+
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`.
402
+
403
+ 3. **Don't forget to unsubscribe in `ngOnDestroy`.** Angular components are destroyed on navigation; leaked subscriptions cause duplicate event handling.
404
+
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.
406
+
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.
408
+
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.
410
+
411
+ ---
412
+
413
+ ## Skill routing reference
414
+
415
+ | Skill | When to route |
416
+ |---|---|
417
+ | `cometchat-angular-core` | Init / login / module setup |
418
+ | `cometchat-angular-components` | Input reference — which `[hide*]`, `[*View]`, `[*RequestBuilder]` is available |
419
+ | `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 |
423
+ | `cometchat-angular-production` | When customization depends on production auth |
424
+ | `cometchat-angular-troubleshooting` | Formatter doesn't apply, listener fires twice, slot view renders nothing |