Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libs/chat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
},
"sideEffects": [
"**/chat-tokens.ts",
"./fesm2022/ngaf-chat.mjs",
"**/*.css"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import { NgTemplateOutlet } from '@angular/common';
import type { AgentWithHistory } from '../../agent';
import { CHAT_DEBUG_TOKENS } from './chat-debug-tokens';
import { ensureChatRootStyles } from '../../styles/chat-tokens';
import { ChatDebugControlsDirective } from './chat-debug-controls.directive';
import { ChatDebugInspectorDirective } from './chat-debug-inspector.directive';
import { TimelineInspectorComponent } from './inspectors/timeline-inspector.component';
Expand Down Expand Up @@ -399,6 +400,10 @@ export class ChatDebugComponent {
private readonly hostEl: ElementRef<HTMLElement> = inject(ElementRef);

constructor() {
// Inject chat lib root CSS custom properties so the theme-attribute
// mappings + edge-claim primitive are in the document, even when
// chat-debug is mounted without a sibling chat composition.
ensureChatRootStyles();
// Restore once from storage on construction; inputs seed the fallback.
// `storageKey` is read-once: rebinding it at runtime is not supported.
const restore = createPersistence(this.storageKey());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { ViewRegistry } from '@ngaf/render';
import { ChatComponent } from '../chat/chat.component';
import type { ChatSelectOption } from '../../primitives/chat-select/chat-select.component';
import { ChatLauncherButtonComponent } from '../../primitives/chat-launcher-button/chat-launcher-button.component';
import { CHAT_HOST_TOKENS } from '../../styles/chat-tokens';
import { CHAT_HOST_TOKENS, ensureChatRootStyles } from '../../styles/chat-tokens';

@Component({
selector: 'chat-popup',
Expand Down Expand Up @@ -106,6 +106,9 @@ export class ChatPopupComponent {
private readonly document = inject(DOCUMENT);

constructor() {
// Inject chat lib root CSS custom properties — see ChatComponent
// for the full rationale. Idempotent + lifecycle-guaranteed.
ensureChatRootStyles();
effect(() => {
// Re-bind whenever shortcut/closeOnEscape change.
const shortcut = this.shortcut();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { ViewRegistry } from '@ngaf/render';
import { ChatComponent } from '../chat/chat.component';
import { ChatLauncherButtonComponent } from '../../primitives/chat-launcher-button/chat-launcher-button.component';
import type { ChatSelectOption } from '../../primitives/chat-select/chat-select.component';
import { CHAT_HOST_TOKENS } from '../../styles/chat-tokens';
import { CHAT_HOST_TOKENS, ensureChatRootStyles } from '../../styles/chat-tokens';

@Component({
selector: 'chat-sidebar',
Expand Down Expand Up @@ -104,6 +104,9 @@ export class ChatSidebarComponent {
readonly forkRequested = output<string>();

constructor() {
// Inject chat lib root CSS custom properties — see ChatComponent
// for the full rationale. Idempotent + lifecycle-guaranteed.
ensureChatRootStyles();
// Publish the right-edge claim while the panel is open. Peer panels
// (e.g. chat-debug) read --ngaf-chat-occupy-right to leave room.
effect(() => {
Expand Down
15 changes: 14 additions & 1 deletion libs/chat/src/lib/compositions/chat/chat.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { createContentClassifier, type ContentClassifier } from '../../streaming
import { createPartialArgsBridge, type PartialArgsBridge } from '../../a2ui/partial-args-bridge';
import { createA2uiSurfaceStore, type A2uiSurfaceStore } from '../../a2ui/surface-store';
import { messageContent } from '../shared/message-utils';
import { CHAT_HOST_TOKENS } from '../../styles/chat-tokens';
import { CHAT_HOST_TOKENS, ensureChatRootStyles } from '../../styles/chat-tokens';
import type { ChatRenderEvent } from './chat-render-event';
import { CHAT_LIFECYCLE, type ChatLifecycle } from '../../lifecycle';

Expand Down Expand Up @@ -395,6 +395,19 @@ export class ChatComponent {
private static readonly PIN_TOLERANCE_PX = 150;

constructor() {
// Inject the chat lib's root CSS custom properties (--ngaf-chat-bg,
// --ngaf-chat-surface, --ngaf-chat-radius-input, etc.) the first
// time any chat composition is constructed. The module-eval side
// effect that previously handled this is unreliable under
// aggressive production tree-shaking — bundlers that don't see
// the source `chat-tokens.ts` path in the published artifact's
// `sideEffects` glob drop the call entirely, leaving consumers
// with zero token defaults (sidenav has no width, input has no
// border, chips have no chrome — everything renders as plain
// text on the page background). Calling from a constructor that
// is unconditionally reachable from user code defeats that
// tree-shaking and is idempotent. */
ensureChatRootStyles();
effect(() => {
if (this.eventsSubscribed) return;
let agent: ReturnType<typeof this.agent>;
Expand Down
Loading