@acorex/components 20.2.38 → 20.2.40

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 (39) hide show
  1. package/button/index.d.ts +38 -17
  2. package/conversation2/README.md +426 -0
  3. package/conversation2/index.d.ts +6139 -0
  4. package/data-table/index.d.ts +78 -6
  5. package/fesm2022/acorex-components-button.mjs +50 -10
  6. package/fesm2022/acorex-components-button.mjs.map +1 -1
  7. package/fesm2022/acorex-components-command.mjs +1 -1
  8. package/fesm2022/acorex-components-command.mjs.map +1 -1
  9. package/fesm2022/acorex-components-conversation.mjs +1 -1
  10. package/fesm2022/acorex-components-conversation.mjs.map +1 -1
  11. package/fesm2022/acorex-components-conversation2.mjs +17641 -0
  12. package/fesm2022/acorex-components-conversation2.mjs.map +1 -0
  13. package/fesm2022/acorex-components-cron-job.mjs +6 -6
  14. package/fesm2022/acorex-components-cron-job.mjs.map +1 -1
  15. package/fesm2022/acorex-components-data-pager.mjs +1 -1
  16. package/fesm2022/acorex-components-data-pager.mjs.map +1 -1
  17. package/fesm2022/acorex-components-data-table.mjs +416 -62
  18. package/fesm2022/acorex-components-data-table.mjs.map +1 -1
  19. package/fesm2022/acorex-components-decorators.mjs +3 -10
  20. package/fesm2022/acorex-components-decorators.mjs.map +1 -1
  21. package/fesm2022/acorex-components-editor.mjs +5 -2
  22. package/fesm2022/acorex-components-editor.mjs.map +1 -1
  23. package/fesm2022/acorex-components-form.mjs +28 -5
  24. package/fesm2022/acorex-components-form.mjs.map +1 -1
  25. package/fesm2022/acorex-components-media-viewer.mjs +20 -5
  26. package/fesm2022/acorex-components-media-viewer.mjs.map +1 -1
  27. package/fesm2022/acorex-components-phone-box.mjs +1 -1
  28. package/fesm2022/acorex-components-phone-box.mjs.map +1 -1
  29. package/fesm2022/acorex-components-rrule.mjs +1 -1
  30. package/fesm2022/acorex-components-rrule.mjs.map +1 -1
  31. package/fesm2022/acorex-components-search-box.mjs +8 -3
  32. package/fesm2022/acorex-components-search-box.mjs.map +1 -1
  33. package/fesm2022/acorex-components-wysiwyg.mjs +11 -5
  34. package/fesm2022/acorex-components-wysiwyg.mjs.map +1 -1
  35. package/form/index.d.ts +3 -3
  36. package/media-viewer/index.d.ts +1 -1
  37. package/package.json +11 -7
  38. package/search-box/index.d.ts +6 -1
  39. package/wysiwyg/index.d.ts +2 -0
package/button/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as i0 from '@angular/core';
1
+ import * as _angular_core from '@angular/core';
2
2
  import { EventEmitter, QueryList, AfterViewInit } from '@angular/core';
3
3
  import { MXInteractiveComponent, MXColorComponent, AXClickEvent, AXStyleColorType, AXItemClickEvent, AXStyleLookType, AXHotKeyAction, MXButtonBaseComponent } from '@acorex/cdk/common';
4
4
  import * as polytype from 'polytype';
@@ -11,7 +11,9 @@ interface AXButtonItemListItem {
11
11
  divided?: boolean;
12
12
  disabled?: boolean;
13
13
  selected?: boolean;
14
+ iconOnly?: boolean;
14
15
  color?: AXStyleColorType;
16
+ loading?: boolean;
15
17
  }
16
18
  declare const AXButtonItemComponent_base: polytype.Polytype.ClusteredConstructor<[typeof MXInteractiveComponent, typeof MXColorComponent]>;
17
19
  /**
@@ -93,8 +95,8 @@ declare class AXButtonItemComponent extends AXButtonItemComponent_base {
93
95
  * @ignore
94
96
  */
95
97
  tabindex: string;
96
- static ɵfac: i0.ɵɵFactoryDeclaration<AXButtonItemComponent, never>;
97
- static ɵcmp: i0.ɵɵComponentDeclaration<AXButtonItemComponent, "ax-button-item", never, { "color": { "alias": "color"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "text": { "alias": "text"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; "divided": { "alias": "divided"; "required": false; }; "data": { "alias": "data"; "required": false; }; "name": { "alias": "name"; "required": false; }; }, { "onClick": "onClick"; "onFocus": "onFocus"; "onBlur": "onBlur"; "disabledChange": "disabledChange"; }, never, ["ax-prefix", "ax-loading", "ax-icon", "ax-suffix", "ax-dropdown-panel"], true, never>;
98
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXButtonItemComponent, never>;
99
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AXButtonItemComponent, "ax-button-item", never, { "color": { "alias": "color"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "text": { "alias": "text"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; "divided": { "alias": "divided"; "required": false; }; "data": { "alias": "data"; "required": false; }; "name": { "alias": "name"; "required": false; }; }, { "onClick": "onClick"; "onFocus": "onFocus"; "onBlur": "onBlur"; "disabledChange": "disabledChange"; }, never, ["ax-prefix", "ax-loading", "ax-icon", "ax-suffix", "ax-dropdown-panel"], true, never>;
98
100
  }
99
101
 
100
102
  /**
@@ -110,7 +112,20 @@ declare class AXButtonItemListComponent extends MXInteractiveComponent {
110
112
  *
111
113
  * @defaultValue []
112
114
  */
113
- items: i0.InputSignal<AXButtonItemListItem[]>;
115
+ items: _angular_core.InputSignal<AXButtonItemListItem[]>;
116
+ /**
117
+ * Determines if the parent closable component should be closed automatically when
118
+ * an item is clicked.
119
+ *
120
+ * @defaultValue true
121
+ */
122
+ closeParentOnClick: _angular_core.InputSignal<boolean>;
123
+ /**
124
+ * Locks interaction for all items when any item is loading.
125
+ *
126
+ * @defaultValue false
127
+ */
128
+ lockOnLoading: _angular_core.InputSignal<boolean>;
114
129
  /**
115
130
  * Emits an event when an item is clicked.
116
131
  * The event contains details about the clicked item.
@@ -125,6 +140,8 @@ declare class AXButtonItemListComponent extends MXInteractiveComponent {
125
140
  * @ignore
126
141
  */
127
142
  constructor();
143
+ protected isDisabled(item: AXButtonItemListItem): boolean;
144
+ protected hasAnyLoadingItem(): boolean;
128
145
  /**
129
146
  * Initializes the content of the button item list.
130
147
  * Binds events and properties to content button items and marks for change detection.
@@ -162,6 +179,10 @@ declare class AXButtonItemListComponent extends MXInteractiveComponent {
162
179
  * @ignore
163
180
  */
164
181
  _emitOnItemClickEvent(e: AXClickEvent, item: AXButtonItemComponent): void;
182
+ /**
183
+ * Closes the parent closable component if available.
184
+ */
185
+ closeParent(): void;
165
186
  /**
166
187
  * Generates the CSS classes for the button item list host element.
167
188
  * Includes classes for action list and vertical layout.
@@ -170,8 +191,8 @@ declare class AXButtonItemListComponent extends MXInteractiveComponent {
170
191
  * @ignore
171
192
  */
172
193
  private get __hostClass();
173
- static ɵfac: i0.ɵɵFactoryDeclaration<AXButtonItemListComponent, never>;
174
- static ɵcmp: i0.ɵɵComponentDeclaration<AXButtonItemListComponent, "ax-button-item-list", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; }, { "onItemClick": "onItemClick"; }, ["_contentButtons"], ["*"], true, never>;
194
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXButtonItemListComponent, never>;
195
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AXButtonItemListComponent, "ax-button-item-list", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "closeParentOnClick": { "alias": "closeParentOnClick"; "required": false; "isSignal": true; }; "lockOnLoading": { "alias": "lockOnLoading"; "required": false; "isSignal": true; }; }, { "onItemClick": "onItemClick"; }, ["_contentButtons"], ["*"], true, never>;
175
196
  }
176
197
 
177
198
  type AXButtonType = 'submit' | 'button' | 'cancel' | 'reset';
@@ -204,10 +225,10 @@ interface AXButtonItem {
204
225
  * @category Components
205
226
  */
206
227
  declare class AXButtonComponent extends MXButtonBaseComponent implements AfterViewInit {
207
- iconOnly: i0.InputSignal<boolean>;
208
- protected showIcon: i0.Signal<boolean>;
209
- protected loadingIcon: i0.Signal<AXLoadingComponent>;
210
- protected hasLoadingIcon: i0.Signal<boolean>;
228
+ iconOnly: _angular_core.InputSignal<boolean>;
229
+ protected showIcon: _angular_core.Signal<boolean>;
230
+ protected loadingIcon: _angular_core.Signal<AXLoadingComponent>;
231
+ protected hasLoadingIcon: _angular_core.Signal<boolean>;
211
232
  /**
212
233
  * Fires each time the user clicks the button.
213
234
  * @event
@@ -218,13 +239,13 @@ declare class AXButtonComponent extends MXButtonBaseComponent implements AfterVi
218
239
  *
219
240
  * @defaultValue 'button'
220
241
  */
221
- type: i0.InputSignal<AXButtonType>;
242
+ type: _angular_core.InputSignal<AXButtonType>;
222
243
  /**
223
244
  * Defines the text displayed while the action sheet is loading.
224
245
  *
225
246
  * @defaultValue null
226
247
  */
227
- loadingText: i0.ModelSignal<string>;
248
+ loadingText: _angular_core.ModelSignal<string>;
228
249
  /**
229
250
  * @ignore
230
251
  */
@@ -255,14 +276,14 @@ declare class AXButtonComponent extends MXButtonBaseComponent implements AfterVi
255
276
  * when the button loses focus.
256
277
  */
257
278
  blur(): void;
258
- static ɵfac: i0.ɵɵFactoryDeclaration<AXButtonComponent, never>;
259
- static ɵcmp: i0.ɵɵComponentDeclaration<AXButtonComponent, "ax-button", never, { "disabled": { "alias": "disabled"; "required": false; }; "size": { "alias": "size"; "required": false; }; "tabIndex": { "alias": "tabIndex"; "required": false; }; "color": { "alias": "color"; "required": false; }; "look": { "alias": "look"; "required": false; }; "text": { "alias": "text"; "required": false; }; "toggleable": { "alias": "toggleable"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; "iconOnly": { "alias": "iconOnly"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "loadingText": { "alias": "loadingText"; "required": false; "isSignal": true; }; }, { "onBlur": "onBlur"; "onFocus": "onFocus"; "onClick": "onClick"; "selectedChange": "selectedChange"; "toggleableChange": "toggleableChange"; "lookChange": "lookChange"; "colorChange": "colorChange"; "disabledChange": "disabledChange"; "loadingText": "loadingTextChange"; }, ["loadingIcon"], ["ax-loading, ax-loading-spinner", "ax-prefix, ax-icon", "ax-content", "ax-suffix", "ax-dropdown-panel", ".tab-content", "*"], true, never>;
279
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXButtonComponent, never>;
280
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AXButtonComponent, "ax-button", never, { "disabled": { "alias": "disabled"; "required": false; }; "size": { "alias": "size"; "required": false; }; "tabIndex": { "alias": "tabIndex"; "required": false; }; "color": { "alias": "color"; "required": false; }; "look": { "alias": "look"; "required": false; }; "text": { "alias": "text"; "required": false; }; "toggleable": { "alias": "toggleable"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; "iconOnly": { "alias": "iconOnly"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "loadingText": { "alias": "loadingText"; "required": false; "isSignal": true; }; }, { "onBlur": "onBlur"; "onFocus": "onFocus"; "onClick": "onClick"; "selectedChange": "selectedChange"; "toggleableChange": "toggleableChange"; "lookChange": "lookChange"; "colorChange": "colorChange"; "disabledChange": "disabledChange"; "loadingText": "loadingTextChange"; }, ["loadingIcon"], ["ax-loading, ax-loading-spinner", "ax-prefix, ax-icon", "ax-content", "ax-suffix", "ax-dropdown-panel", ".tab-content", "*"], true, never>;
260
281
  }
261
282
 
262
283
  declare class AXButtonModule {
263
- static ɵfac: i0.ɵɵFactoryDeclaration<AXButtonModule, never>;
264
- static ɵmod: i0.ɵɵNgModuleDeclaration<AXButtonModule, never, [typeof AXButtonComponent, typeof AXButtonItemComponent, typeof AXButtonItemListComponent], [typeof AXButtonComponent, typeof AXButtonItemComponent, typeof AXButtonItemListComponent]>;
265
- static ɵinj: i0.ɵɵInjectorDeclaration<AXButtonModule>;
284
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXButtonModule, never>;
285
+ static ɵmod: _angular_core.ɵɵNgModuleDeclaration<AXButtonModule, never, [typeof AXButtonComponent, typeof AXButtonItemComponent, typeof AXButtonItemListComponent], [typeof AXButtonComponent, typeof AXButtonItemComponent, typeof AXButtonItemListComponent]>;
286
+ static ɵinj: _angular_core.ɵɵInjectorDeclaration<AXButtonModule>;
266
287
  }
267
288
 
268
289
  export { AXButtonComponent, AXButtonItemComponent, AXButtonItemListComponent, AXButtonModule };
@@ -0,0 +1,426 @@
1
+ # @acorex/components/conversation2
2
+
3
+ A modern, fully-featured conversation/chat component for Angular 18+. Built with signals, standalone components, and extensibility in mind.
4
+
5
+ ## 🚀 Features
6
+
7
+ - **Real-time Messaging** - Live message updates with WebSocket support
8
+ - **Multiple Message Types** - Text, images, videos, audio, voice, files, locations, stickers, contacts
9
+ - **Rich Interactions** - Reactions, replies, message editing, deletion, forwarding
10
+ - **Group & Private Chats** - Support for 1-on-1 and group conversations
11
+ - **Typing Indicators** - Real-time typing status
12
+ - **Read Receipts** - Message delivery and read status
13
+ - **Infinite Scroll** - Efficient pagination for message history
14
+ - **Search** - Search within conversations and messages
15
+ - **Extensible** - Plugin system for custom message renderers and actions
16
+ - **Responsive** - Mobile-friendly design
17
+ - **Accessibility** - ARIA labels and keyboard navigation
18
+
19
+ ## 📦 Installation
20
+
21
+ ```bash
22
+ npm install @acorex/components/conversation2
23
+ ```
24
+
25
+ ## 🔧 Peer Dependencies
26
+
27
+ This package requires the following peer dependencies:
28
+
29
+ ### Required Angular Dependencies
30
+
31
+ ```json
32
+ {
33
+ "@angular/common": "^18.0.0",
34
+ "@angular/core": "^18.0.0",
35
+ "@angular/forms": "^18.0.0",
36
+ "rxjs": "^7.8.0"
37
+ }
38
+ ```
39
+
40
+ ### Required Acorex Dependencies
41
+
42
+ #### Core Packages
43
+
44
+ - `@acorex/cdk/common` - Common utilities and directives
45
+ - `@acorex/core/date-time` - Date and time formatting
46
+ - `@acorex/core/format` - General formatting utilities
47
+
48
+ #### Component Packages
49
+
50
+ - `@acorex/components/avatar` - User avatars
51
+ - `@acorex/components/badge` - Notification badges
52
+ - `@acorex/components/button` - Button components
53
+ - `@acorex/components/decorators` - Decorative elements
54
+ - `@acorex/components/dialog` - Dialog service
55
+ - `@acorex/components/dropdown` - Dropdown panels
56
+ - `@acorex/components/image` - Image components
57
+ - `@acorex/components/label` - Label components
58
+ - `@acorex/components/loading` - Loading indicators
59
+ - `@acorex/components/menu` - Context menus
60
+ - `@acorex/components/popover` - Popover components
61
+ - `@acorex/components/popup` - Popup service
62
+ - `@acorex/components/search-box` - Search functionality
63
+ - `@acorex/components/select-box` - Select dropdowns
64
+ - `@acorex/components/tabs` - Tab components
65
+ - `@acorex/components/text-area` - Text input areas
66
+ - `@acorex/components/text-box` - Text input boxes
67
+ - `@acorex/components/toast` - Toast notifications
68
+ - `@acorex/components/tooltip` - Tooltips
69
+ - `@acorex/components/uploader` - File upload functionality
70
+
71
+ ## 🎯 Quick Start
72
+
73
+ > **New to Conversation2?** Check out our [5-Minute Quick Start Guide](./docs/QUICK-START.md) for the fastest way to get started!
74
+
75
+ ### Detailed Setup
76
+
77
+ ### 1. Standalone Application (Recommended)
78
+
79
+ ```typescript
80
+ import { ApplicationConfig } from '@angular/core';
81
+ import { provideConversation, AXIndexedDBApi } from '@acorex/components/conversation2';
82
+
83
+ export const appConfig: ApplicationConfig = {
84
+ providers: [
85
+ provideConversation({
86
+ api: AXIndexedDBApi, // or your custom API implementation
87
+ config: {
88
+ pageSize: 20,
89
+ maxFileSize: 10 * 1024 * 1024, // 10MB
90
+ allowedFileTypes: ['image/*', 'video/*', 'audio/*', 'application/pdf'],
91
+ },
92
+ registry: {
93
+ // Optional: Register custom message renderers, actions, etc.
94
+ }
95
+ })
96
+ ]
97
+ };
98
+ ```
99
+
100
+ ### 2. NgModule Application (Legacy)
101
+
102
+ ```typescript
103
+ import { NgModule } from '@angular/core';
104
+ import { AXConversation2Module, AXIndexedDBApi } from '@acorex/components/conversation2';
105
+
106
+ @NgModule({
107
+ imports: [
108
+ AXConversation2Module.forRoot({
109
+ api: AXIndexedDBApi,
110
+ config: { /* ... */ }
111
+ })
112
+ ]
113
+ })
114
+ export class AppModule { }
115
+ ```
116
+
117
+ ### 3. Use in Template
118
+
119
+ ```html
120
+ <ax-conversation-container></ax-conversation-container>
121
+ ```
122
+
123
+ ## 🔌 API Implementation
124
+
125
+ You must provide an API implementation that extends `AXConversationApi`:
126
+
127
+ ```typescript
128
+ import { Injectable } from '@angular/core';
129
+ import { HttpClient } from '@angular/common/http';
130
+ import { AXConversationApi, AXPagination, AXPaginatedResult } from '@acorex/components/conversation2';
131
+
132
+ @Injectable()
133
+ export class MyConversationApi extends AXConversationApi {
134
+ constructor(private http: HttpClient) {
135
+ super();
136
+ }
137
+
138
+ async connect(): Promise<void> {
139
+ // Initialize WebSocket connection
140
+ }
141
+
142
+ async fetchConversations(pagination: AXPagination): Promise<AXPaginatedResult<AXConversation>> {
143
+ const response = await this.http.get('/api/conversations', {
144
+ params: { page: pagination.page, pageSize: pagination.pageSize }
145
+ }).toPromise();
146
+ return response;
147
+ }
148
+
149
+ // Implement other required methods...
150
+ }
151
+ ```
152
+
153
+ ### Built-in API Implementations
154
+
155
+ #### IndexedDB API (Development/Demo)
156
+
157
+ ```typescript
158
+ import { AXIndexedDBApi } from '@acorex/components/conversation2';
159
+
160
+ // Provides in-memory storage with sample data
161
+ // Perfect for development and demos
162
+ provideConversation({ api: AXIndexedDBApi })
163
+ ```
164
+
165
+ #### IndexedDB with AI API (AI-Powered Demo)
166
+
167
+ ```typescript
168
+ import { AXIndexedDBAIApi } from '@acorex/components/conversation2';
169
+
170
+ // Includes AI-powered auto-responses
171
+ provideConversation({ api: AXIndexedDBAIApi })
172
+ ```
173
+
174
+ ## ⚙️ Configuration
175
+
176
+ ### Conversation Config
177
+
178
+ ```typescript
179
+ interface AXConversationConfig {
180
+ // Pagination
181
+ pageSize?: number; // Default: 20
182
+ infiniteScrollThreshold?: number; // Default: 200px
183
+ scrollThreshold?: number; // Default: 100px
184
+
185
+ // File Upload
186
+ maxFileSize?: number; // Default: 10MB
187
+ allowedFileTypes?: string[]; // Default: all types
188
+
189
+ // UI Behavior
190
+ messageHighlightDuration?: number; // Default: 2000ms
191
+ typingIndicatorTimeout?: number; // Default: 3000ms
192
+
193
+ // Features
194
+ enableReactions?: boolean; // Default: true
195
+ enableReplies?: boolean; // Default: true
196
+ enableEditing?: boolean; // Default: true
197
+ enableDeletion?: boolean; // Default: true
198
+ }
199
+ ```
200
+
201
+ ### Registry Configuration
202
+
203
+ ```typescript
204
+ interface AXRegistryConfiguration {
205
+ messageRenderers?: AXMessageRenderer[];
206
+ messageActions?: AXMessageAction[];
207
+ composerActions?: AXComposerAction[];
208
+ composerTabs?: AXComposerTab[];
209
+ conversationTabs?: AXConversationTab[];
210
+ infoBarActions?: AXInfoBarAction[];
211
+ conversationItemActions?: AXConversationItemAction[];
212
+ }
213
+ ```
214
+
215
+ ## 🎨 Customization
216
+
217
+ ### Custom Message Renderer
218
+
219
+ ```typescript
220
+ import { Component, input } from '@angular/core';
221
+ import { AXMessageRenderer } from '@acorex/components/conversation2';
222
+
223
+ @Component({
224
+ selector: 'my-custom-renderer',
225
+ template: `<div>{{ message().payload.customData }}</div>`
226
+ })
227
+ export class MyCustomRendererComponent {
228
+ message = input.required<AXMessage>();
229
+ }
230
+
231
+ const myRenderer: AXMessageRenderer = {
232
+ type: 'custom',
233
+ component: MyCustomRendererComponent,
234
+ priority: 100
235
+ };
236
+
237
+ // Register in config
238
+ provideConversation({
239
+ api: MyApi,
240
+ registry: {
241
+ messageRenderers: [myRenderer]
242
+ }
243
+ });
244
+ ```
245
+
246
+ ### Custom Message Action
247
+
248
+ ```typescript
249
+ const forwardAction: AXMessageAction = {
250
+ id: 'forward',
251
+ label: 'Forward',
252
+ icon: 'forward',
253
+ shortcut: 'Ctrl+F',
254
+ enabled: (message, user) => message.senderId === user.id,
255
+ execute: async (message, service) => {
256
+ // Forward logic
257
+ }
258
+ };
259
+
260
+ provideConversation({
261
+ api: MyApi,
262
+ registry: {
263
+ messageActions: [forwardAction]
264
+ }
265
+ });
266
+ ```
267
+
268
+ ## 📱 Components
269
+
270
+ ### Main Components
271
+
272
+ - `<ax-conversation-container>` - Full conversation UI with sidebar, messages, and composer
273
+ - `<ax-conversation-sidebar>` - Conversation list sidebar
274
+ - `<ax-conversation-message-list>` - Message list with virtual scrolling
275
+ - `<ax-conversation-composer>` - Message input area
276
+ - `<ax-conversation-info-bar>` - Conversation header with actions
277
+
278
+ ### Usage Examples
279
+
280
+ ```html
281
+ <!-- Full conversation UI -->
282
+ <ax-conversation-container></ax-conversation-container>
283
+
284
+ <!-- Custom layout -->
285
+ <div class="my-chat-layout">
286
+ <ax-conversation-sidebar></ax-conversation-sidebar>
287
+ <div class="chat-main">
288
+ <ax-conversation-info-bar></ax-conversation-info-bar>
289
+ <ax-conversation-message-list></ax-conversation-message-list>
290
+ <ax-conversation-composer></ax-conversation-composer>
291
+ </div>
292
+ </div>
293
+ ```
294
+
295
+ ## 🎭 Services
296
+
297
+ ### AXConversationService
298
+
299
+ Main service for conversation operations:
300
+
301
+ ```typescript
302
+ import { inject } from '@angular/core';
303
+ import { AXConversationService } from '@acorex/components/conversation2';
304
+
305
+ export class MyComponent {
306
+ private conversationService = inject(AXConversationService);
307
+
308
+ async sendMessage() {
309
+ await this.conversationService.sendMessage({
310
+ conversationId: 'conv-123',
311
+ type: 'text',
312
+ payload: { text: 'Hello!' }
313
+ });
314
+ }
315
+
316
+ async createConversation() {
317
+ const conv = await this.conversationService.createConversation(
318
+ ['user-1', 'user-2'],
319
+ 'private'
320
+ );
321
+ }
322
+ }
323
+ ```
324
+
325
+ ## 🧪 Testing
326
+
327
+ ```typescript
328
+ import { TestBed } from '@angular/core/testing';
329
+ import { provideConversation, AXConversationService } from '@acorex/components/conversation2';
330
+ import { MockConversationApi } from './mocks/mock-api';
331
+
332
+ describe('MyComponent', () => {
333
+ beforeEach(() => {
334
+ TestBed.configureTestingModule({
335
+ providers: [
336
+ provideConversation({ api: MockConversationApi })
337
+ ]
338
+ });
339
+ });
340
+
341
+ it('should send message', async () => {
342
+ const service = TestBed.inject(AXConversationService);
343
+ const message = await service.sendMessage({
344
+ conversationId: 'test',
345
+ type: 'text',
346
+ payload: { text: 'Test' }
347
+ });
348
+ expect(message).toBeDefined();
349
+ });
350
+ });
351
+ ```
352
+
353
+ ## 🎯 Message Types
354
+
355
+ Supported message types out of the box:
356
+
357
+ - **text** - Plain text messages
358
+ - **image** - Image messages with thumbnails
359
+ - **video** - Video messages with playback
360
+ - **audio** - Audio file messages
361
+ - **voice** - Voice recordings
362
+ - **file** - Generic file attachments
363
+ - **location** - Location sharing
364
+ - **sticker** - Sticker messages
365
+ - **contact** - Contact card sharing
366
+ - **system** - System notifications
367
+
368
+ ## 🔒 Security Considerations
369
+
370
+ - **API Keys**: Never hardcode API keys in source code. Use environment variables or injection tokens.
371
+ - **File Upload**: Validate file types and sizes on both client and server.
372
+ - **XSS Protection**: All user content is sanitized by default.
373
+ - **Authentication**: Implement proper authentication in your API layer.
374
+
375
+ ## 📊 Performance Tips
376
+
377
+ 1. **Virtual Scrolling**: Enabled by default for large message lists
378
+ 2. **Lazy Loading**: Images and media are loaded on demand
379
+ 3. **Pagination**: Messages are loaded in pages to reduce initial load
380
+ 4. **Debouncing**: Typing indicators are debounced to reduce network traffic
381
+ 5. **Memoization**: Use computed signals for expensive calculations
382
+
383
+ ## 🐛 Troubleshooting
384
+
385
+ ### Common Issues
386
+
387
+ **Issue**: Messages not appearing
388
+
389
+ - Check if API is connected: `conversationService.connectionStatus$()`
390
+ - Verify API implementation returns correct data structure
391
+
392
+ **Issue**: File upload fails
393
+
394
+ - Check `maxFileSize` and `allowedFileTypes` configuration
395
+ - Verify API `uploadFile()` implementation
396
+
397
+ **Issue**: Styling issues
398
+
399
+ - Ensure all Acorex component styles are imported
400
+ - Check for CSS conflicts with global styles
401
+
402
+ ## 📚 Additional Resources
403
+
404
+ - [Quick Start Guide](./docs/QUICK-START.md) - Get started in 5 minutes
405
+ - [Architecture Overview](./docs/ARCHITECTURE-OVERVIEW.md) - Understand the module structure
406
+ - [API Documentation](./docs/ARCHITECTURE-APIS.md) - Implement custom backends
407
+ - [Component Guide](./docs/ARCHITECTURE-COMPONENTS.md) - Learn about components
408
+ - [Plugin System](./docs/ARCHITECTURE-PLUGINS.md) - Extend functionality
409
+ - [Usage Guide](./docs/USAGE-GUIDE.md) - Advanced usage patterns
410
+
411
+ ## 🤝 Contributing
412
+
413
+ Contributions are welcome! Please read our [Contributing Guide](./CONTRIBUTING.md) for details.
414
+
415
+ ## 📄 License
416
+
417
+ MIT License - see LICENSE file for details
418
+
419
+ ## 🔄 Changelog
420
+
421
+ See [CHANGELOG.md](./CHANGELOG.md) for version history and updates.
422
+
423
+ ## 💬 Support
424
+
425
+ - GitHub Issues: [Report a bug](https://github.com/acorexui/acorex-ui/issues)
426
+ - Discussions: [Ask questions](https://github.com/acorexui/acorex-ui/discussions)