1import type { AfterViewInit } from "@angular/core";
2import {
3 ChangeDetectionStrategy,
4 Component,
5 ViewContainerRef,
6 inject,
7 input,
8} from "@angular/core";
9import { CopilotChat } from "@copilotkit/angular";
10import { ActivatedRoute } from "@angular/router";
11
12import { agentIdForRoute } from "../feature-agent";
13import { FeatureHeaderComponent } from "./feature-header.component";
14import {
15 createDynamicComponent,
16 renderDynamicComponent,
17} from "./render-dynamic-component";
18
19interface SlotMessage {
20 id: string;
21 role: "assistant";
22 content?: string;
23}
24
25@Component({
26 selector: "showcase-custom-assistant-message",
27 changeDetection: ChangeDetectionStrategy.OnPush,
28 host: {
29 class: "custom-assistant-message",
30 "data-testid": "custom-assistant-message",
31 "data-slot-label": "MessageView.AssistantMessage",
32 "data-message-role": "assistant",
33 },
34 template: `
35 <p class="feature-eyebrow">Custom Angular assistant slot</p>
36 <div>{{ message().content }}</div>
37 `,
38})
39export class CustomAssistantMessageComponent {
40 readonly message = input.required<SlotMessage>();
41}
42
43@Component({
44 selector: "showcase-chat-slots-feature",
45 imports: [FeatureHeaderComponent],
46 changeDetection: ChangeDetectionStrategy.OnPush,
47 host: { class: "feature-page" },
48 template: `
49 <showcase-feature-header />
50 <main class="chat-surface" aria-label="Customized CopilotKit chat">
51 <ng-container #chatHost />
52 </main>
53 `,
54})
55export class ChatSlotsFeatureComponent implements AfterViewInit {
56 private readonly chatHost = inject(ViewContainerRef);
57 private readonly route = inject(ActivatedRoute);
58
59 ngAfterViewInit(): void {
60 const chat = createDynamicComponent(this.chatHost, CopilotChat);
61 chat.setInput("agentId", agentIdForRoute("chat-slots", this.route));
62 chat.setInput("assistantMessageComponent", CustomAssistantMessageComponent);
63 renderDynamicComponent(chat);
64 }
65}
66