Skip to content

Commit 0ca2138

Browse files
committed
Merge branch 'rkaraivanov/wc-chat-wrapper' of https://github.com/IgniteUI/igniteui-angular into rkaraivanov/wc-chat-wrapper
2 parents 0250924 + 09c5144 commit 0ca2138

File tree

9 files changed

+119
-32
lines changed

9 files changed

+119
-32
lines changed
File renamed without changes.
File renamed without changes.

projects/igniteui-angular/extras/src/markdown-pipe.spec.ts renamed to projects/igniteui-angular/chat-extras/src/markdown-pipe.spec.ts

File renamed without changes.

projects/igniteui-angular/extras/src/markdown-pipe.ts renamed to projects/igniteui-angular/chat-extras/src/markdown-pipe.ts

File renamed without changes.

projects/igniteui-angular/extras/src/markdown-service.spec.ts renamed to projects/igniteui-angular/chat-extras/src/markdown-service.spec.ts

File renamed without changes.

projects/igniteui-angular/extras/src/markdown-service.ts renamed to projects/igniteui-angular/chat-extras/src/markdown-service.ts

File renamed without changes.
File renamed without changes.

projects/igniteui-angular/src/lib/chat/chat.component.ts

Lines changed: 118 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import {
1111
signal,
1212
TemplateRef,
1313
ViewContainerRef,
14-
untracked,
1514
OnDestroy,
1615
ViewRef,
16+
computed,
1717
} from '@angular/core';
1818
import {
1919
IgcChatComponent,
@@ -40,9 +40,9 @@ type ChatContextType<T extends ChatContextUnion> =
4040
: T extends ChatMessageRenderContext
4141
? IgcChatMessage
4242
: T extends ChatInputRenderContext
43-
? { value: T['value']; attachments: T['attachments'] }
43+
? { value: string; attachments: IgcChatMessageAttachment[] }
4444
: T extends ChatRenderContext
45-
? { instance: T['instance'] }
45+
? { instance: IgcChatComponent }
4646
: never;
4747

4848
type ExtractChatContext<T> = T extends (ctx: infer R) => any ? R : never;
@@ -55,15 +55,51 @@ type ChatTemplatesContextMap = {
5555
};
5656
};
5757

58+
/**
59+
* Template references for customizing chat component rendering.
60+
* Each property corresponds to a specific part of the chat UI that can be customized.
61+
*
62+
* @example
63+
* ```typescript
64+
* templates = {
65+
* messageContent: this.customMessageTemplate,
66+
* attachment: this.customAttachmentTemplate
67+
* }
68+
* ```
69+
*/
5870
export type IgxChatTemplates = {
59-
[K in keyof ChatRenderers]?: TemplateRef<ChatTemplatesContextMap[K]>;
71+
[K in keyof Omit<ChatRenderers, 'typingIndicator'>]?: TemplateRef<ChatTemplatesContextMap[K]>;
6072
};
6173

74+
/**
75+
* Configuration options for the chat component.
76+
*/
6277
export type IgxChatOptions = Omit<IgcChatOptions, 'renderers'>;
6378

6479

80+
/**
81+
* Angular wrapper component for the Ignite UI Web Components Chat component.
82+
*
83+
* This component provides an Angular-friendly interface to the igc-chat web component,
84+
* including support for Angular templates, signals, and change detection.
85+
*
86+
* Uses OnPush change detection strategy for optimal performance. All inputs are signals,
87+
* so changes are automatically tracked and propagated to the underlying web component.
88+
*
89+
* @example
90+
* ```typescript
91+
* <igx-chat
92+
* [messages]="messages"
93+
* [draftMessage]="draft"
94+
* [options]="chatOptions"
95+
* [templates]="chatTemplates"
96+
* (messageCreated)="onMessageCreated($event)"
97+
* />
98+
* ```
99+
*/
65100
@Component({
66101
selector: 'igx-chat',
102+
standalone: true,
67103
changeDetection: ChangeDetectionStrategy.OnPush,
68104
schemas: [CUSTOM_ELEMENTS_SCHEMA],
69105
templateUrl: './chat.component.html',
@@ -80,32 +116,64 @@ export class IgxChatComponent implements OnInit, OnDestroy {
80116
private readonly _templateViewRefs = new Map<TemplateRef<any>, Set<ViewRef>>();
81117
private _oldTemplates: IgxChatTemplates = {};
82118

83-
protected readonly _mergedOptions = signal<IgcChatOptions>({});
84119
protected readonly _transformedTemplates = signal<ChatRenderers>({});
85120

121+
protected readonly _mergedOptions = computed<IgcChatOptions>(() => {
122+
const options = this.options();
123+
const transformedTemplates = this._transformedTemplates();
124+
return {
125+
...options,
126+
renderers: transformedTemplates
127+
};
128+
});
129+
86130
//#endregion
87131

88132
//#region Inputs
89133

134+
/** Array of chat messages to display */
90135
public readonly messages = input<IgcChatMessage[]>([]);
136+
137+
/** Draft message with text and optional attachments */
91138
public readonly draftMessage = input<
92139
{ text: string; attachments?: IgcChatMessageAttachment[] } | undefined
93140
>({ text: '' });
141+
142+
/** Configuration options for the chat component */
94143
public readonly options = input<IgxChatOptions>({});
144+
145+
/** Custom templates for rendering chat elements */
95146
public readonly templates = input<IgxChatTemplates>({});
96147

97148
//#endregion
98149

99150
//#region Outputs
100151

152+
/** Emitted when a new message is created */
101153
public readonly messageCreated = output<IgcChatMessage>();
154+
155+
/** Emitted when a user reacts to a message */
102156
public readonly messageReact = output<IgcChatMessageReaction>();
157+
158+
/** Emitted when an attachment is clicked */
103159
public readonly attachmentClick = output<IgcChatMessageAttachment>();
160+
161+
/** Emitted when attachment drag starts */
104162
public readonly attachmentDrag = output<void>();
163+
164+
/** Emitted when attachment is dropped */
105165
public readonly attachmentDrop = output<void>();
166+
167+
/** Emitted when typing indicator state changes */
106168
public readonly typingChange = output<boolean>();
169+
170+
/** Emitted when the input receives focus */
107171
public readonly inputFocus = output<void>();
172+
173+
/** Emitted when the input loses focus */
108174
public readonly inputBlur = output<void>();
175+
176+
/** Emitted when the input value changes */
109177
public readonly inputChange = output<string>();
110178

111179
//#endregion
@@ -124,29 +192,13 @@ export class IgxChatComponent implements OnInit, OnDestroy {
124192
}
125193

126194
constructor() {
127-
// Templates changed - update transformed templates and viewRefs and merge with options
195+
// Templates changed - update transformed templates and viewRefs
128196
effect(() => {
129197
const templates = this.templates();
130198
this._setTemplates(templates ?? {});
131-
this._mergeOptions(untracked(() => this.options()));
132-
});
133-
134-
// Options changed - merge with current template state
135-
effect(() => {
136-
const options = this.options();
137-
this._mergeOptions(options ?? {});
138199
});
139200
}
140201

141-
private _mergeOptions(options: IgxChatOptions): void {
142-
const transformedTemplates = this._transformedTemplates();
143-
const merged: IgcChatOptions = {
144-
...options,
145-
renderers: transformedTemplates
146-
};
147-
this._mergedOptions.set(merged);
148-
}
149-
150202
private _setTemplates(newTemplates: IgxChatTemplates): void {
151203
const templateCopies: ChatRenderers = {};
152204
const newTemplateKeys = Object.keys(newTemplates) as Array<keyof IgxChatTemplates>;
@@ -200,7 +252,8 @@ export class IgxChatComponent implements OnInit, OnDestroy {
200252
angularContext = { $implicit: context.message };
201253
} else if ('value' in context) {
202254
angularContext = {
203-
$implicit: { value: context.value, attachments: context.attachments },
255+
$implicit: context.value,
256+
attachments: context.attachments
204257
};
205258
} else {
206259
angularContext = { $implicit: { instance: context.instance } };
@@ -214,31 +267,65 @@ export class IgxChatComponent implements OnInit, OnDestroy {
214267
}
215268
}
216269

217-
export interface ChatTemplateContext<T> {
218-
$implicit: T;
219-
}
220-
221-
interface ChatInputContext {
270+
/**
271+
* Context provided to the chat input template.
272+
*/
273+
export interface ChatInputContext {
274+
/** The current input value */
222275
$implicit: string;
276+
/** Array of attachments associated with the input */
223277
attachments: IgcChatMessageAttachment[];
224278
}
225279

280+
/**
281+
* Directive providing type information for chat message template contexts.
282+
* Use this directive on ng-template elements that render chat messages.
283+
*
284+
* @example
285+
* ```html
286+
* <ng-template igxChatMessageContext let-message>
287+
* <div>{{ message.text }}</div>
288+
* </ng-template>
289+
* ```
290+
*/
226291
@Directive({ selector: '[igxChatMessageContext]' })
227292
export class IgxChatMessageContextDirective {
228293

229-
public static ngTemplateContextGuard(_: IgxChatMessageContextDirective, ctx: unknown): ctx is ChatTemplateContext<IgcChatMessage> {
294+
public static ngTemplateContextGuard(_: IgxChatMessageContextDirective, ctx: unknown): ctx is { $implicit: IgcChatMessage } {
230295
return true;
231296
}
232-
};
297+
}
233298

299+
/**
300+
* Directive providing type information for chat attachment template contexts.
301+
* Use this directive on ng-template elements that render message attachments.
302+
*
303+
* @example
304+
* ```html
305+
* <ng-template igxChatAttachmentContext let-attachment>
306+
* <img [src]="attachment.url" />
307+
* </ng-template>
308+
* ```
309+
*/
234310
@Directive({ selector: '[igxChatAttachmentContext]' })
235311
export class IgxChatAttachmentContextDirective {
236312

237-
public static ngTemplateContextGuard(_: IgxChatAttachmentContextDirective, ctx: unknown): ctx is ChatTemplateContext<IgcChatMessageAttachment> {
313+
public static ngTemplateContextGuard(_: IgxChatAttachmentContextDirective, ctx: unknown): ctx is { $implicit: IgcChatMessageAttachment } {
238314
return true;
239315
}
240316
}
241317

318+
/**
319+
* Directive providing type information for chat input template contexts.
320+
* Use this directive on ng-template elements that render the chat input.
321+
*
322+
* @example
323+
* ```html
324+
* <ng-template igxChatInputContext let-value let-attachments="attachments">
325+
* <input [value]="value" />
326+
* </ng-template>
327+
* ```
328+
*/
242329
@Directive({ selector: '[igxChatInputContext]' })
243330
export class IgxChatInputContextDirective {
244331

src/app/chat/chat.sample.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
IgxChatMessageContextDirective,
1515
type IgxChatOptions,
1616
} from 'igniteui-angular';
17-
import { MarkdownPipe } from 'igniteui-angular/extras';
17+
import { MarkdownPipe } from 'igniteui-angular/chat-extras';
1818

1919
@Component({
2020
changeDetection: ChangeDetectionStrategy.OnPush,

0 commit comments

Comments
 (0)