@aparte/angular 0.2.0-alpha.0 → 0.4.0-alpha.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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { InjectionToken, inject, Injectable, makeEnvironmentProviders, provideAppInitializer, DestroyRef, effect, ElementRef, signal, output, computed, numberAttribute, booleanAttribute, ViewChildren, ViewChild, Input, ChangeDetectionStrategy, CUSTOM_ELEMENTS_SCHEMA, Component, Renderer2 } from '@angular/core';
|
|
3
|
-
import { AparteClient, AparteConfig, AparteChatHost, DEFAULT_UI_EVENTS, applyElementProps, ConversationManager } from '@aparte/core';
|
|
3
|
+
import { AparteClient, AparteConfig, isAwaitingReply, AparteChatHost, DEFAULT_UI_EVENTS, applyElementProps, ConversationManager } from '@aparte/core';
|
|
4
4
|
export { AparteConfig } from '@aparte/core';
|
|
5
5
|
import { NgTemplateOutlet } from '@angular/common';
|
|
6
6
|
|
|
@@ -213,6 +213,12 @@ class AparteChatComponent {
|
|
|
213
213
|
});
|
|
214
214
|
}
|
|
215
215
|
elementRef = inject(ElementRef);
|
|
216
|
+
/**
|
|
217
|
+
* Template bridge to core's shared `isAwaitingReply` (an Angular template can't
|
|
218
|
+
* call an imported function). One rule for the four wrappers and core itself,
|
|
219
|
+
* so "is this bubble in flight" can't drift between them.
|
|
220
|
+
*/
|
|
221
|
+
awaitingReply = isAwaitingReply;
|
|
216
222
|
// ── Input Signals ────────────────────────────────────────────────────────
|
|
217
223
|
/** Messages to display */
|
|
218
224
|
set messagesInput(val) {
|
|
@@ -243,6 +249,17 @@ class AparteChatComponent {
|
|
|
243
249
|
*/
|
|
244
250
|
set centerWhenEmptyInput(val) { this.centerWhenEmpty.set(val); }
|
|
245
251
|
centerWhenEmpty = signal(false);
|
|
252
|
+
/**
|
|
253
|
+
* Add the file picker + chips strip to the default composer shell. **Off by
|
|
254
|
+
* default**, because the capability needs a host that consumes the files: an
|
|
255
|
+
* `AparteClient` inlines them per its `rawFileInject` option, but if you drive
|
|
256
|
+
* your own loop you must read `event.files` on `(messageSent)` — otherwise the
|
|
257
|
+
* file the user deliberately attached is dropped in silence. No effect when you
|
|
258
|
+
* project a `[slot='composer']` (drop `<aparte-composer-add-attachment>` and
|
|
259
|
+
* `<aparte-composer-attachments>` in it yourself).
|
|
260
|
+
*/
|
|
261
|
+
set attachmentsInput(val) { this.attachments.set(val); }
|
|
262
|
+
attachments = signal(false);
|
|
246
263
|
/** Whether the assistant is currently typing/streaming */
|
|
247
264
|
set isTypingInput(val) { this.isTyping.set(val); }
|
|
248
265
|
isTyping = signal(false);
|
|
@@ -534,7 +551,7 @@ class AparteChatComponent {
|
|
|
534
551
|
this.messageSent.emit(detail);
|
|
535
552
|
}
|
|
536
553
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AparteChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
537
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AparteChatComponent, isStandalone: true, selector: "aparte-chat", inputs: { messagesInput: ["messages", "messagesInput"], placeholderInput: ["placeholder", "placeholderInput"], disabledInput: ["disabled", "disabledInput", booleanAttribute], submitOnEnterInput: ["submitOnEnter", "submitOnEnterInput", booleanAttribute], centerWhenEmptyInput: ["centerWhenEmpty", "centerWhenEmptyInput", booleanAttribute], isTypingInput: ["isTyping", "isTypingInput", booleanAttribute], typingTextInput: ["typingText", "typingTextInput"], layoutTransitionMs: ["layoutTransitionMs", "layoutTransitionMs", numberAttribute], conversationIdInput: ["conversationId", "conversationIdInput"], config: "config", bubbleTemplate: "bubbleTemplate" }, outputs: { messageSent: "messageSent", action: "action", messagesChange: "messagesChange", messageAppended: "messageAppended", typingChange: "typingChange", conversationCreated: "conversationCreated" }, host: { attributes: { "framework-managed": "" } }, viewQueries: [{ propertyName: "viewportRef", first: true, predicate: ["viewport"], descendants: true }, { propertyName: "inputRef", first: true, predicate: ["input"], descendants: true }, { propertyName: "bubbleRefs", predicate: ["bubble"], descendants: true }], ngImport: i0, template: `
|
|
554
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AparteChatComponent, isStandalone: true, selector: "aparte-chat", inputs: { messagesInput: ["messages", "messagesInput"], placeholderInput: ["placeholder", "placeholderInput"], disabledInput: ["disabled", "disabledInput", booleanAttribute], submitOnEnterInput: ["submitOnEnter", "submitOnEnterInput", booleanAttribute], centerWhenEmptyInput: ["centerWhenEmpty", "centerWhenEmptyInput", booleanAttribute], attachmentsInput: ["attachments", "attachmentsInput", booleanAttribute], isTypingInput: ["isTyping", "isTypingInput", booleanAttribute], typingTextInput: ["typingText", "typingTextInput"], layoutTransitionMs: ["layoutTransitionMs", "layoutTransitionMs", numberAttribute], conversationIdInput: ["conversationId", "conversationIdInput"], config: "config", bubbleTemplate: "bubbleTemplate" }, outputs: { messageSent: "messageSent", action: "action", messagesChange: "messagesChange", messageAppended: "messageAppended", typingChange: "typingChange", conversationCreated: "conversationCreated" }, host: { attributes: { "framework-managed": "" } }, viewQueries: [{ propertyName: "viewportRef", first: true, predicate: ["viewport"], descendants: true }, { propertyName: "inputRef", first: true, predicate: ["input"], descendants: true }, { propertyName: "bubbleRefs", predicate: ["bubble"], descendants: true }], ngImport: i0, template: `
|
|
538
555
|
<div
|
|
539
556
|
class="aparte-chat-container"
|
|
540
557
|
[class.aparte-chat-container--auto-center]="centerWhenEmpty()"
|
|
@@ -560,7 +577,7 @@ class AparteChatComponent {
|
|
|
560
577
|
[attr.data-role]="message.role"
|
|
561
578
|
[attr.timestamp]="message.timestamp"
|
|
562
579
|
[attr.content]="message.content"
|
|
563
|
-
[attr.streaming]="(message
|
|
580
|
+
[attr.streaming]="awaitingReply(message) ? '' : null"
|
|
564
581
|
></aparte-chat-bubble>
|
|
565
582
|
}
|
|
566
583
|
}
|
|
@@ -580,13 +597,18 @@ class AparteChatComponent {
|
|
|
580
597
|
(aparte-send)="onAparteSend($event)"
|
|
581
598
|
>
|
|
582
599
|
<!-- Custom composer via [slot='composer']; falls back to the default
|
|
583
|
-
shell (
|
|
584
|
-
|
|
600
|
+
shell (input · send + footer slots, plus the attachment primitives
|
|
601
|
+
when the attachments input is set). Project your own
|
|
602
|
+
aparte-composer-* layout for a skin-specific composer. -->
|
|
585
603
|
<ng-content select="[slot='composer']">
|
|
586
604
|
<div class="aparte-composer-shell">
|
|
587
|
-
|
|
605
|
+
@if (attachments()) {
|
|
606
|
+
<aparte-composer-attachments></aparte-composer-attachments>
|
|
607
|
+
}
|
|
588
608
|
<div class="aparte-composer-row">
|
|
589
|
-
|
|
609
|
+
@if (attachments()) {
|
|
610
|
+
<aparte-composer-add-attachment></aparte-composer-add-attachment>
|
|
611
|
+
}
|
|
590
612
|
<aparte-composer-input></aparte-composer-input>
|
|
591
613
|
<aparte-composer-send></aparte-composer-send>
|
|
592
614
|
</div>
|
|
@@ -629,7 +651,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
629
651
|
[attr.data-role]="message.role"
|
|
630
652
|
[attr.timestamp]="message.timestamp"
|
|
631
653
|
[attr.content]="message.content"
|
|
632
|
-
[attr.streaming]="(message
|
|
654
|
+
[attr.streaming]="awaitingReply(message) ? '' : null"
|
|
633
655
|
></aparte-chat-bubble>
|
|
634
656
|
}
|
|
635
657
|
}
|
|
@@ -649,13 +671,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
649
671
|
(aparte-send)="onAparteSend($event)"
|
|
650
672
|
>
|
|
651
673
|
<!-- Custom composer via [slot='composer']; falls back to the default
|
|
652
|
-
shell (
|
|
653
|
-
|
|
674
|
+
shell (input · send + footer slots, plus the attachment primitives
|
|
675
|
+
when the attachments input is set). Project your own
|
|
676
|
+
aparte-composer-* layout for a skin-specific composer. -->
|
|
654
677
|
<ng-content select="[slot='composer']">
|
|
655
678
|
<div class="aparte-composer-shell">
|
|
656
|
-
|
|
679
|
+
@if (attachments()) {
|
|
680
|
+
<aparte-composer-attachments></aparte-composer-attachments>
|
|
681
|
+
}
|
|
657
682
|
<div class="aparte-composer-row">
|
|
658
|
-
|
|
683
|
+
@if (attachments()) {
|
|
684
|
+
<aparte-composer-add-attachment></aparte-composer-add-attachment>
|
|
685
|
+
}
|
|
659
686
|
<aparte-composer-input></aparte-composer-input>
|
|
660
687
|
<aparte-composer-send></aparte-composer-send>
|
|
661
688
|
</div>
|
|
@@ -684,6 +711,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
684
711
|
}], centerWhenEmptyInput: [{
|
|
685
712
|
type: Input,
|
|
686
713
|
args: [{ alias: 'centerWhenEmpty', transform: booleanAttribute }]
|
|
714
|
+
}], attachmentsInput: [{
|
|
715
|
+
type: Input,
|
|
716
|
+
args: [{ alias: 'attachments', transform: booleanAttribute }]
|
|
687
717
|
}], isTypingInput: [{
|
|
688
718
|
type: Input,
|
|
689
719
|
args: [{ alias: 'isTyping', transform: booleanAttribute }]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aparte-angular.mjs","sources":["../../src/lib/aparte-ai.service.ts","../../src/lib/provide-aparte.ts","../../src/lib/aparte-chat.component.ts","../../src/lib/aparte-ui.component.ts","../../src/lib/conversation-manager.service.ts","../../src/index.ts","../../src/aparte-angular.ts"],"sourcesContent":["import { Injectable, OnDestroy, inject, InjectionToken } from '@angular/core';\nimport { AparteClient, AparteClientOptions } from '@aparte/core';\n\n/**\n * Injection token for AparteClient configuration. Provided by `provideAparte()`;\n * omit it and the service falls back to `{}`.\n */\nexport const APARTE_CLIENT_OPTIONS = new InjectionToken<AparteClientOptions>('APARTE_CLIENT_OPTIONS');\n\n/**\n * AparteAiService\n *\n * Angular service to bridge the UI events with AI Providers.\n * Uses the agnostic `AparteClient` under the hood.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class AparteAiService implements OnDestroy {\n private readonly _clientOptions = inject(APARTE_CLIENT_OPTIONS, { optional: true });\n private _client: AparteClient = new AparteClient(this._clientOptions ?? {});\n\n /**\n * Start listening to `aparte-send` events globally.\n * This connects the <aparte-chat> components to the AI Providers.\n *\n * `provideAparte()` calls this for you on app init (its `autoConnect`,\n * on by default). Idempotent — a manual call on top of that is a no-op,\n * so it stays the escape hatch when configuring without `provideAparte`.\n */\n connect(): void {\n this._client.start();\n }\n\n /**\n * Stop listening.\n */\n disconnect(): void {\n this._client.stop();\n }\n\n /**\n * Abort the current AI response and all active tool calls.\n */\n abort(): void {\n this._client.abort();\n }\n\n ngOnDestroy(): void {\n this.disconnect();\n }\n}\n","import {\n DestroyRef,\n InjectionToken,\n inject,\n makeEnvironmentProviders,\n provideAppInitializer,\n type EnvironmentProviders,\n} from '@angular/core';\nimport {\n AparteConfig,\n type AparteAIProvider,\n type AparteClientOptions,\n type AparteIconProvider,\n type AparteLocale,\n type AparteMarkdownProvider,\n type AparteModelConfig,\n type AparteSkeletonProvider,\n} from '@aparte/core';\nimport { APARTE_CLIENT_OPTIONS, AparteAiService } from './aparte-ai.service';\n\n/**\n * Any function that initialises a plugin — sync or async, so it can wrap a\n * dynamic `import()` of a package YOU choose:\n * `() => import('@aparte/plugin-model-selector')`.\n */\nexport type ApartePluginLoader = () => void | Promise<void>;\n\n/**\n * Config for {@link provideAparte}. Deliberately **instance-agnostic**: every\n * plugin/locale slot takes a provider OBJECT or a LOADER function you supply —\n * this package never hardcodes (nor depends on) a catalog of `@aparte/*` package\n * names, so it stays a leaf with only `@aparte/core` + Angular as peers.\n */\nexport interface ProvideAparteOptions {\n /** AI providers to register (e.g. from `@aparte/provider-openai-compat`). */\n providers?: AparteAIProvider[];\n\n /** Optional plugin wiring — objects or loaders, never package-name strings. */\n plugins?: {\n /** Action plugins, as loaders: `[() => import('@aparte/plugin-model-selector')]`. */\n actions?: ApartePluginLoader[];\n /** An icon provider object, or a loader that registers one. */\n icons?: AparteIconProvider | ApartePluginLoader;\n /** A skeleton provider object, or a loader that registers one. */\n skeleton?: AparteSkeletonProvider | ApartePluginLoader;\n /** A loader that applies a theme. */\n theme?: ApartePluginLoader;\n /** A markdown provider `(raw: string) => string`, or a loader that registers one. */\n markdown?: AparteMarkdownProvider | ApartePluginLoader;\n };\n\n /** Model selection configuration. */\n modelConfig?: AparteModelConfig;\n\n /** A locale OBJECT (e.g. `fr` from `@aparte/locale-fr`) — not a package-name string. */\n locale?: AparteLocale;\n\n /** Theme mode; `'auto'` follows the system preference. */\n themeMode?: 'light' | 'dark' | 'auto';\n\n /** Options for the `AparteClient` mounted by {@link AparteAiService}. */\n clientOptions?: AparteClientOptions;\n\n /**\n * Start the {@link AparteAiService} client once the app initialises (after\n * providers/plugins are registered), so sends stream without a manual\n * `AparteAiService.connect()` — \"wire the config and it works\", same as the\n * React/Vue/Svelte wrappers. Default `true`; set `false` to control the\n * client lifecycle yourself.\n */\n autoConnect?: boolean;\n}\n\n/** Holds the resolved aparté config, for consumers that want to inject it. */\nexport const APARTE_CONFIG_TOKEN = new InjectionToken<ProvideAparteOptions>('APARTE_CONFIG');\n\nasync function loadIconPlugin(plugin: AparteIconProvider | ApartePluginLoader): Promise<void> {\n if (typeof plugin === 'object' && plugin !== null) {\n AparteConfig.setIconProvider(plugin);\n return;\n }\n try {\n await (plugin as ApartePluginLoader)();\n } catch (err) {\n console.warn('[aparte] Failed to load icon plugin', err);\n }\n}\n\nasync function loadSkeletonPlugin(plugin: AparteSkeletonProvider | ApartePluginLoader): Promise<void> {\n if (typeof plugin === 'object' && plugin !== null) {\n AparteConfig.setSkeletonProvider(plugin);\n return;\n }\n try {\n await (plugin as ApartePluginLoader)();\n } catch (err) {\n console.warn('[aparte] Failed to load skeleton plugin', err);\n }\n}\n\nasync function loadMarkdownPlugin(plugin: AparteMarkdownProvider | ApartePluginLoader): Promise<void> {\n // A markdown provider takes the raw string; a loader takes nothing.\n if (plugin.length >= 1) {\n AparteConfig.setMarkdownProvider(plugin as AparteMarkdownProvider);\n return;\n }\n try {\n await (plugin as ApartePluginLoader)();\n } catch (err) {\n console.warn('[aparte] Failed to load markdown plugin', err);\n }\n}\n\nasync function runLoader(loader: ApartePluginLoader, label: string): Promise<void> {\n try {\n await loader();\n } catch (err) {\n console.warn(`[aparte] Failed to load ${label} plugin`, err);\n }\n}\n\nasync function loadPlugins(options: ProvideAparteOptions): Promise<void> {\n const plugins = options.plugins;\n if (!plugins) return;\n const pending: Promise<void>[] = [];\n\n for (const action of plugins.actions ?? []) pending.push(runLoader(action, 'action'));\n if (plugins.icons) pending.push(loadIconPlugin(plugins.icons));\n if (plugins.skeleton) pending.push(loadSkeletonPlugin(plugins.skeleton));\n if (plugins.theme) pending.push(runLoader(plugins.theme, 'theme'));\n if (plugins.markdown) pending.push(loadMarkdownPlugin(plugins.markdown));\n\n await Promise.all(pending);\n}\n\n/** Reflect the theme mode on the document root. */\nfunction applyThemeMode(mode: 'light' | 'dark' | 'auto', destroyRef: DestroyRef): void {\n if (mode !== 'auto') {\n document.documentElement.setAttribute('data-aparte-theme', mode);\n return;\n }\n const query = window.matchMedia('(prefers-color-scheme: dark)');\n const onChange = (e: MediaQueryListEvent) => {\n document.documentElement.setAttribute('data-aparte-theme', e.matches ? 'dark' : 'light');\n };\n document.documentElement.setAttribute('data-aparte-theme', query.matches ? 'dark' : 'light');\n query.addEventListener('change', onChange);\n // Released with the environment injector, so repeated bootstraps (TestBed, a\n // multi-instance embed) don't stack listeners on the media query forever.\n destroyRef.onDestroy(() => query.removeEventListener('change', onChange));\n}\n\n/**\n * Configure aparté for a standalone Angular app. Registers your AI providers,\n * model config, locale and optional plugins on the global `AparteConfig`,\n * provides {@link APARTE_CLIENT_OPTIONS} for {@link AparteAiService}, and\n * starts the client (see `autoConnect`) — no manual\n * `AparteAiService.connect()` needed.\n *\n * The components (`AparteChatComponent`, `AparteUiComponent`) are standalone and\n * work WITHOUT this — it is config sugar. You can equally call `AparteConfig.*`\n * yourself, exactly like the React/Vue/Svelte wrappers do.\n *\n * @example\n * bootstrapApplication(App, {\n * providers: [\n * provideAparte({\n * providers: [createOpenAICompatProvider(presets.OPENROUTER)],\n * clientOptions: { keyResolver },\n * }),\n * ],\n * });\n */\nexport function provideAparte(options: ProvideAparteOptions = {}): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: APARTE_CONFIG_TOKEN, useValue: options },\n { provide: APARTE_CLIENT_OPTIONS, useValue: options.clientOptions ?? {} },\n provideAppInitializer(async () => {\n const destroyRef = inject(DestroyRef);\n // inject() only works before the first await — grab the service now,\n // connect at the end (after plugins) so the first send already sees\n // markdown/action providers. SSR-safe: no listener without a window.\n const ai = options.autoConnect !== false && typeof window !== 'undefined'\n ? inject(AparteAiService)\n : null;\n if (options.providers?.length) {\n AparteConfig.registerAIProvider(...options.providers);\n }\n if (options.modelConfig) {\n AparteConfig.setModelConfig(options.modelConfig);\n }\n if (options.locale) {\n AparteConfig.setLocale(options.locale);\n }\n await loadPlugins(options);\n if (options.themeMode) {\n applyThemeMode(options.themeMode, destroyRef);\n }\n ai?.connect();\n }),\n ]);\n}\n","import {\n Component,\n CUSTOM_ELEMENTS_SCHEMA,\n ElementRef,\n OnDestroy,\n ViewChild,\n QueryList,\n ViewChildren,\n output,\n signal,\n computed,\n ChangeDetectionStrategy,\n AfterViewInit,\n Input,\n TemplateRef,\n inject,\n effect,\n booleanAttribute,\n numberAttribute,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { Observable } from 'rxjs';\nimport type {\n AparteMessage,\n AparteSegment,\n AparteSendEventDetail,\n AparteChatHostBinding,\n AparteConfigClass,\n AparteActionEventDetail,\n AparteChatImperativeApi,\n} from '@aparte/core';\nimport { AparteChatHost } from '@aparte/core';\n\n/**\n * AparteChatComponent — Angular 19 Wrapper\n *\n * Standalone component wrapping aparté Web Components with Angular Signals.\n * The streaming / branch-navigation / host-method orchestration (orphan-stream\n * guard, lifecycle tracking, conversation lifecycle, bubble reconciliation)\n * lives in the framework-agnostic `AparteChatHost` from `@aparte/core`; this\n * component only owns the Angular-idiomatic surface (signals, template, DI) and\n * binds the host over its `messages` signal.\n */\n@Component({\n selector: 'aparte-chat',\n standalone: true,\n imports: [NgTemplateOutlet],\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n changeDetection: ChangeDetectionStrategy.OnPush,\n // This selector is ALSO core's `<aparte-chat>` custom element, so the host gets\n // upgraded by core on insert. `framework-managed` tells that shell to keep its\n // hands off: THIS component renders the viewport + composer and drives them\n // through AparteChatHost. Without it, core injects its default composition\n // underneath ours (its own check can't see our children — they render later).\n host: { 'framework-managed': '' },\n template: `\n <div\n class=\"aparte-chat-container\"\n [class.aparte-chat-container--auto-center]=\"centerWhenEmpty()\"\n [attr.data-aparte-empty]=\"centerWhenEmpty() && messages().length === 0 ? '' : null\"\n >\n <aparte-chat-viewport #viewport framework-managed=\"\">\n @if (messages().length === 0) {\n <!-- Welcome / placeholder shown inside the viewport while empty. -->\n <ng-content select=\"[slot='empty-state']\"></ng-content>\n }\n @for (message of messages(); track message.id) {\n @if (bubbleTemplate) {\n <!-- Render your OWN element per message; driven by the reactive\n messages() signal so it streams live. -->\n <ng-container\n [ngTemplateOutlet]=\"bubbleTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: message }\"\n ></ng-container>\n } @else {\n <aparte-chat-bubble\n #bubble\n [attr.message-id]=\"message.id\"\n [attr.data-role]=\"message.role\"\n [attr.timestamp]=\"message.timestamp\"\n [attr.content]=\"message.content\"\n [attr.streaming]=\"(message.status === 'streaming' || message.status === 'pending') ? '' : null\"\n ></aparte-chat-bubble>\n }\n }\n <aparte-chat-status\n [attr.visible]=\"isTyping() ? '' : null\"\n [attr.text]=\"typingText()\"\n ></aparte-chat-status>\n </aparte-chat-viewport>\n\n <ng-content select=\"[slot='above-composer']\"></ng-content>\n\n <aparte-composer\n #input\n [attr.placeholder]=\"placeholder()\"\n [attr.disabled]=\"disabled() ? '' : null\"\n [attr.submit-on-enter]=\"submitOnEnter() ? null : 'false'\"\n (aparte-send)=\"onAparteSend($event)\"\n >\n <!-- Custom composer via [slot='composer']; falls back to the default\n shell (add-attachment · input · send + footer slots). Project your\n own aparte-composer-* layout for a skin-specific composer. -->\n <ng-content select=\"[slot='composer']\">\n <div class=\"aparte-composer-shell\">\n <aparte-composer-attachments></aparte-composer-attachments>\n <div class=\"aparte-composer-row\">\n <aparte-composer-add-attachment></aparte-composer-add-attachment>\n <aparte-composer-input></aparte-composer-input>\n <aparte-composer-send></aparte-composer-send>\n </div>\n <div class=\"aparte-composer-footer\">\n <ng-content select=\"[slot='footer-left']\"></ng-content>\n <ng-content select=\"[slot='footer-center']\"></ng-content>\n <ng-content select=\"[slot='footer-right']\"></ng-content>\n </div>\n </div>\n </ng-content>\n </aparte-composer>\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .aparte-chat-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n }\n\n aparte-chat-viewport {\n flex: 1;\n min-height: 0;\n }\n\n aparte-composer {\n flex-shrink: 0;\n }\n `]\n})\nexport class AparteChatComponent implements AfterViewInit, OnDestroy, AparteChatImperativeApi {\n constructor() {\n // Reactive effect to reconcile bubbles when the messages signal updates.\n // Debounced with requestAnimationFrame so rapid token bursts only trigger\n // one sync per paint frame instead of N syncs for N tokens.\n effect(() => {\n const msgs = this.messages();\n if (msgs.length > 0) {\n if (this._syncRafId !== null) return;\n this._syncRafId = requestAnimationFrame(() => {\n this._syncRafId = null;\n this._host?.syncBubbles();\n });\n }\n });\n }\n\n private elementRef = inject(ElementRef);\n\n // ── Input Signals ────────────────────────────────────────────────────────\n\n /** Messages to display */\n @Input('messages') set messagesInput(val: AparteMessage[]) {\n this.messages.set(val);\n // When messages are cleared (new conversation), reset the host's render cache\n // so the next conversation starts clean — same as React/Vue/Svelte do. (The\n // viewport's own clearMessages() is @deprecated in core and only clears its\n // repo; the host's clearAll() path already owns the real teardown.)\n if (val.length === 0) this._host?.clearRenderCache();\n }\n readonly messages = signal<AparteMessage[]>([]);\n\n /** Input placeholder text */\n @Input('placeholder') set placeholderInput(val: string) { this.placeholder.set(val); }\n readonly placeholder = signal<string>('Type a message...');\n\n /** Whether the input is disabled */\n @Input({ alias: 'disabled', transform: booleanAttribute }) set disabledInput(val: boolean) { this.disabled.set(val); }\n readonly disabled = signal<boolean>(false);\n\n /** When false, Shift+Enter submits and a bare Enter inserts a newline. */\n @Input({ alias: 'submitOnEnter', transform: booleanAttribute }) set submitOnEnterInput(val: boolean) { this.submitOnEnter.set(val); }\n readonly submitOnEnter = signal<boolean>(true);\n\n /**\n * Opt in to the \"centered composer when empty\" layout: the composer sits\n * vertically centered with the `[slot='empty-state']` content above it while\n * the list is empty, then slides to the bottom on the first message (~0.3s).\n * Off by default — additive (adds the `--auto-center` modifier + a\n * `data-aparte-empty` attribute the shipped `aparte.css` recipe keys off).\n */\n @Input({ alias: 'centerWhenEmpty', transform: booleanAttribute }) set centerWhenEmptyInput(val: boolean) { this.centerWhenEmpty.set(val); }\n readonly centerWhenEmpty = signal<boolean>(false);\n\n /** Whether the assistant is currently typing/streaming */\n @Input({ alias: 'isTyping', transform: booleanAttribute }) set isTypingInput(val: boolean) { this.isTyping.set(val); }\n readonly isTyping = signal<boolean>(false);\n\n /** Text to show in the typing status */\n @Input('typingText') set typingTextInput(val: string) { this.typingText.set(val); }\n readonly typingText = signal<string>('Assistant is thinking...');\n\n /** Duration in ms to freeze spacer recalculation after a conversation swap. */\n @Input({ alias: 'layoutTransitionMs', transform: numberAttribute }) layoutTransitionMs = 0;\n\n /**\n * Active conversation id. When provided, the host attaches an\n * `AparteConversationController` that loads/persists messages via the\n * `ConversationManager` registered in `AparteConfig`. Setting a different id\n * mid-stream aborts the previous request; `null` deselects.\n */\n @Input('conversationId') set conversationIdInput(val: string | null | undefined) {\n const next = val ?? null;\n if (next === this._conversationId) return;\n this._conversationId = next;\n if (this._host) void this._host.setConversationId(next);\n }\n private _conversationId: string | null = null;\n\n /**\n * Instance {@link AparteConfigClass} for this chat. When set, aparté components\n * inside resolve THIS config instead of the global `AparteConfig` singleton, so\n * several independently-configured chats can coexist on one page. Omit for the\n * global config. Read once in `ngAfterViewInit` when the host is created.\n */\n @Input() config?: AparteConfigClass;\n\n /**\n * Render your OWN element per message in place of `<aparte-chat-bubble>`.\n * Opt-in — provide a `<ng-template let-message>` and pass its ref. Driven by\n * the reactive `messages()` signal, so it updates live during streaming.\n * The built-in action bar (retry/edit/branch) belongs to the native bubble;\n * a custom bubble owns whatever it wires.\n * @example\n * <aparte-chat [bubbleTemplate]=\"tpl\" />\n * <ng-template #tpl let-message>{{ message.content }}</ng-template>\n */\n @Input() bubbleTemplate?: TemplateRef<{ $implicit: AparteMessage }>;\n\n // ── Outputs ────────────────────────────────────────────────────────────\n\n /**\n * User submitted a message from the composer. It is **appended to the thread\n * automatically** (optimistic UI) before this fires — do NOT add it again in\n * the handler (uncontrolled → duplicates; controlled → mirror it into your\n * own `[messages]`). For side-effects: scroll, analytics, send.\n */\n readonly messageSent = output<AparteSendEventDetail>();\n /**\n * Emitted when a custom bubble action (registered via\n * `AparteConfig.registerAction` with `zones: ['bubble']`) is clicked — a typed\n * wrapper over the bubbling `aparte-action` DOM event. Switch on `$event.actionId`.\n */\n readonly action = output<AparteActionEventDetail>();\n /** Emitted when messages are updated internally (e.g. by AparteClient) */\n readonly messagesChange = output<AparteMessage[]>();\n /** Emitted when a message is added internally (e.g. by appendMessage) */\n readonly messageAppended = output<AparteMessage>();\n /** The typing/\"thinking\" indicator toggled (the host flips it off on the first streamed token). */\n readonly typingChange = output<boolean>();\n /** Emitted when the controller lazily creates a conversation on first send. */\n readonly conversationCreated = output<string>();\n\n // ── View Children ────────────────────────────────────────────────────────\n @ViewChild('viewport') viewportRef?: ElementRef<HTMLElement>;\n @ViewChild('input') inputRef?: ElementRef<HTMLElement>;\n @ViewChildren('bubble') bubbleRefs!: QueryList<ElementRef<HTMLElement>>;\n\n // ── Private State ────────────────────────────────────────────────────────\n /** Mirror of the host's streaming target id (drives `isStreaming`). */\n private readonly _streamingId = signal<string | null>(null);\n /** Computed: is currently streaming */\n readonly isStreaming = computed(() => this._streamingId() !== null);\n\n /** rAF id used to coalesce rapid signal updates during streaming */\n private _syncRafId: number | null = null;\n\n /** The framework-agnostic chat-host orchestrator (created in ngAfterViewInit). */\n private _host?: AparteChatHost;\n private _unbindHost?: () => void;\n /** QueryList.changes subscription — released in ngOnDestroy so SPA route\n * churn doesn't leak a live subscription per mount. */\n private _bubbleRefsSub?: { unsubscribe(): void };\n\n ngAfterViewInit(): void {\n const host = this.elementRef.nativeElement as HTMLElement;\n\n // Ensure a stable id so aparte-composer can reference the host via `target`,\n // letting AparteClient find it without DOM traversal across re-renders.\n if (!host.id) host.id = `aparte-chat-${crypto.randomUUID()}`;\n const composerEl = this.inputRef?.nativeElement;\n if (composerEl) composerEl.setAttribute('target', host.id);\n\n const binding: AparteChatHostBinding = {\n hostId: host.id,\n host,\n viewport: this.viewportRef?.nativeElement ?? null,\n getMessages: () => this.messages(),\n setMessages: (msgs) => this.messages.set(msgs as AparteMessage[]),\n onMessagesChange: (msgs) => this.messagesChange.emit(msgs as AparteMessage[]),\n onMessageAppended: (msg) => this.messageAppended.emit(msg as AparteMessage),\n onTypingChange: (typing) => { this.isTyping.set(typing); this.typingChange.emit(typing); },\n onStreamingChange: (id) => this._streamingId.set(id),\n // Sibling-info / deferred work runs after Angular has re-rendered.\n afterRender: (cb) => { setTimeout(cb, 0); },\n resetComposer: () => {\n (this.inputRef?.nativeElement as unknown as { reset?: () => void })?.reset?.();\n },\n };\n\n this._host = new AparteChatHost(binding, {\n layoutTransitionMs: this.layoutTransitionMs,\n conversationId: this._conversationId,\n onConversationCreated: (id) => {\n this._conversationId = id;\n this.conversationCreated.emit(id);\n },\n config: this.config,\n });\n this._unbindHost = this._host.bind();\n\n // Custom bubble actions bubble to the host as `aparte-action`; surface them as\n // the typed `action` output. (addEventListener, not @HostListener: Angular\n // parses a colon in the event name as a `target:event` global target.)\n host.addEventListener('aparte-action', this._onAction);\n\n // Re-reconcile bubbles whenever Angular's @for materialises/destroys them.\n this._host.syncBubbles();\n this._bubbleRefsSub = this.bubbleRefs.changes.subscribe(() => this._host?.syncBubbles());\n }\n\n private readonly _onAction = (event: Event): void => {\n this.action.emit((event as CustomEvent<AparteActionEventDetail>).detail);\n };\n\n ngOnDestroy(): void {\n if (this._syncRafId !== null) {\n cancelAnimationFrame(this._syncRafId);\n this._syncRafId = null;\n }\n (this.elementRef.nativeElement as HTMLElement).removeEventListener('aparte-action', this._onAction);\n this._bubbleRefsSub?.unsubscribe();\n this._bubbleRefsSub = undefined;\n this._unbindHost?.();\n this._unbindHost = undefined;\n this._host = undefined;\n }\n\n // ── Public imperative API (delegates to the host) ──────────────────────────\n\n /** Append a message optimistically. */\n appendMessage(message: AparteMessage): void { this._host?.appendMessage(message); }\n /** Atomic update for a message. */\n updateMessage(messageId: string, updates: Partial<AparteMessage>): void {\n this._host?.updateMessage(messageId, updates);\n }\n /** Update the last message content (streaming text). */\n updateLastMessage(content: string, options?: { append?: boolean }): void {\n this._host?.updateLastMessage(content, options);\n }\n /** Add a segment to the last message. */\n addSegment(segment: AparteSegment): void { this._host?.addSegment(segment); }\n /** Update a segment in the last message. */\n updateSegment(segmentId: string, updates: Partial<AparteSegment>): void {\n this._host?.updateSegment(segmentId, updates);\n }\n /** Remove a transient segment. */\n removeSegment(segmentId: string): void { this._host?.removeSegment(segmentId); }\n /** Append content to a segment in the last message. */\n appendToSegment(segmentId: string, content: string): void {\n this._host?.appendToSegment(segmentId, content);\n }\n /** Read the current message list. */\n getMessages(): AparteMessage[] { return this._host?.getMessages() ?? this.messages(); }\n /** Clear all messages + reset state. */\n clearMessages(): void { this._host?.clearMessages(); }\n /** Scroll the viewport to the latest message. */\n scrollToBottom(): void {\n (this.viewportRef?.nativeElement as unknown as { scrollToBottom?: () => void })?.scrollToBottom?.();\n }\n /**\n * The `<aparte-chat-viewport>` element — for custom scroll handling, an\n * IntersectionObserver, etc. Same `getViewport()` accessor on all four\n * wrappers.\n */\n getViewport(): HTMLElement | null { return this.viewportRef?.nativeElement ?? null; }\n /** Focus the composer input. */\n focusInput(): void {\n (this.inputRef?.nativeElement as unknown as { focus?: () => void })?.focus?.();\n }\n /** Create a new branch from a message (returns the new sibling index). */\n addBranch(messageId: string): number { return this._host?.addBranch(messageId) ?? 0; }\n /** Add a sibling of an existing message (returns the new id). */\n addSiblingOf(existingId: string, newMessage: AparteMessage): string | null {\n return this._host?.addSiblingOf(existingId, newMessage) ?? null;\n }\n /** Remove a message and all descendants (edit flow). */\n truncateFrom(messageId: string): void { this._host?.truncateFrom(messageId); }\n /** Keep up to and including a user message, drop later responses (retry). */\n truncateResponsesAfter(userMessageId: string): void {\n this._host?.truncateResponsesAfter(userMessageId);\n }\n\n // ── Token streaming (cross-wrapper contract + Observable adapter) ──────────\n\n /**\n * Inject a token stream for LLM streaming. Takes the cross-wrapper\n * `AsyncIterable<string>` contract (the exact call that works on\n * React/Vue/Svelte) — or an Angular-idiomatic RxJS `Observable<string>`,\n * adapted into the host's agnostic `streamTokens(AsyncIterable)` so the\n * orphan-stream guard + id tracking stay in one place (the host).\n */\n async injectTokenStream(\n messageId: string,\n stream: Observable<string> | AsyncIterable<string>,\n ): Promise<void> {\n if (!this._host) return;\n const tokens = Symbol.asyncIterator in stream\n ? (stream as AsyncIterable<string>)\n : this._observableToAsyncIterable(stream as Observable<string>);\n await this._host.streamTokens(messageId, tokens);\n }\n\n /** Stop any active token stream. */\n stopTokenStream(): void { this._host?.stopTokenStream(); }\n\n /**\n * Set the active conversation id imperatively — parity with the other\n * wrappers' handles (the `conversationId` `@Input` remains the declarative\n * path). Delegates to the host, which loads/persists via the registered\n * `ConversationManager`.\n */\n setConversationId(id: string | null): Promise<void> {\n return this._host?.setConversationId(id) ?? Promise.resolve();\n }\n\n private _observableToAsyncIterable(stream: Observable<string>): AsyncIterable<string> {\n return {\n [Symbol.asyncIterator](): AsyncIterator<string> {\n const buffer: string[] = [];\n let finished = false;\n let failure: unknown = null;\n let pending: {\n resolve: (r: IteratorResult<string>) => void;\n reject: (e: unknown) => void;\n } | null = null;\n const settle = () => {\n if (!pending) return;\n if (failure !== null) { const p = pending; pending = null; p.reject(failure); return; }\n if (buffer.length) {\n const p = pending; pending = null;\n p.resolve({ value: buffer.shift() as string, done: false });\n return;\n }\n if (finished) {\n const p = pending; pending = null;\n p.resolve({ value: undefined as unknown as string, done: true });\n }\n };\n const sub = stream.subscribe({\n next: (v) => { buffer.push(v); settle(); },\n error: (e) => { failure = e; settle(); },\n complete: () => { finished = true; settle(); },\n });\n return {\n next(): Promise<IteratorResult<string>> {\n if (failure !== null) return Promise.reject(failure);\n if (buffer.length) {\n return Promise.resolve({ value: buffer.shift() as string, done: false });\n }\n if (finished) {\n return Promise.resolve({ value: undefined as unknown as string, done: true });\n }\n return new Promise((resolve, reject) => { pending = { resolve, reject }; });\n },\n return(): Promise<IteratorResult<string>> {\n sub.unsubscribe();\n // If a consumer is mid-`await next()` on an empty buffer (e.g. the\n // orphan-stream guard calling `return()` on stop/teardown), settle\n // that pending promise now with done:true — otherwise it hangs\n // forever, since unsubscribing means `next` and `complete` will\n // never fire again to resolve it.\n if (pending) {\n const p = pending;\n pending = null;\n p.resolve({ value: undefined as unknown as string, done: true });\n }\n finished = true;\n return Promise.resolve({ value: undefined as unknown as string, done: true });\n },\n };\n },\n };\n }\n\n /** Handle aparte-send event from the composer Web Component. */\n onAparteSend(event: Event): void {\n const detail = (event as CustomEvent<AparteSendEventDetail>).detail;\n // Smooth-scroll the next auto-scroll (when Angular adds the user bubble).\n (this.viewportRef?.nativeElement as unknown as { requestSmoothScroll?: () => void })\n ?.requestSmoothScroll?.();\n this.messageSent.emit(detail);\n }\n}\n","import {\n Component,\n CUSTOM_ELEMENTS_SCHEMA,\n ElementRef,\n OnChanges,\n OnDestroy,\n AfterViewInit,\n SimpleChanges,\n ChangeDetectionStrategy,\n Input,\n output,\n Renderer2,\n inject\n} from '@angular/core';\nimport { applyElementProps, DEFAULT_UI_EVENTS } from '@aparte/core';\n\n/**\n * The imperative surface of the `AparteUi` proxy — the same\n * `getElement`/`callMethod` contract on all four wrappers.\n */\nexport interface AparteUiHandle {\n getElement<T extends HTMLElement = HTMLElement>(): T | null;\n callMethod<T = unknown>(methodName: string, ...args: unknown[]): T | undefined;\n}\n\n/**\n * AparteUiComponent - Universal UI Proxy\n *\n * A pass-through proxy component that dynamically injects any aparté\n * Web Component, so you don't need a dedicated Angular wrapper per element.\n *\n * @example\n * ```html\n * <aparte-ui\n * name=\"aparte-model-selector\"\n * [props]=\"{\n * placeholder: 'Ask anything...',\n * '--glow-opacity': '1',\n * '--glow-speed': '4s'\n * }\"\n * (elementEvent)=\"onEvent($event)\"\n * />\n * ```\n *\n * @description\n * - Keys starting with `--` are applied as CSS Variables\n * - Other keys are set as DOM properties on the element\n * - The events in `events` (default: {@link DEFAULT_UI_EVENTS}) bubble up via `elementEvent`\n */\n@Component({\n selector: 'aparte-ui',\n standalone: true,\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `<ng-container></ng-container>`,\n styles: [`\n :host {\n display: contents;\n }\n `]\n})\nexport class AparteUiComponent implements AfterViewInit, OnChanges, OnDestroy, AparteUiHandle {\n private readonly renderer = inject(Renderer2);\n private readonly hostEl = inject(ElementRef);\n\n // ─────────────────────────────────────────────────────────────\n // Inputs\n // ─────────────────────────────────────────────────────────────\n\n /** The custom element tag name (e.g., 'aparte-model-selector') */\n @Input({ required: true }) name!: string;\n\n /** Properties to pass to the element. Keys starting with '--' are CSS vars */\n @Input() props: Record<string, unknown> = {};\n\n /**\n * Which custom events to forward through `elementEvent`. Defaults to the\n * interactive aparté surface ({@link DEFAULT_UI_EVENTS}); pass your own list to\n * listen to other events (e.g. `['aparte-composer-change']` for attachments).\n */\n @Input() events?: string[];\n\n // ─────────────────────────────────────────────────────────────\n // Outputs\n // ─────────────────────────────────────────────────────────────\n\n /** Emits a forwarded custom event from the underlying Web Component */\n readonly elementEvent = output<CustomEvent>();\n\n // ─────────────────────────────────────────────────────────────\n // Internal State\n // ─────────────────────────────────────────────────────────────\n\n /** The dynamically created Web Component element */\n private element: HTMLElement | null = null;\n\n /** Cleanup functions for event listeners */\n private eventCleanups: (() => void)[] = [];\n\n /** Joined key of the bound event set, so a fresh inline `[events]` array\n * doesn't thrash the element — only a real change rebinds. */\n private lastEventsKey = '';\n\n // ─────────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────────\n\n ngAfterViewInit(): void {\n this.createElement();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n // Recreate the element when `name` (or the forwarded event set) changes.\n const nameChanged = !!changes['name'] && !changes['name'].firstChange;\n const eventsChanged =\n !!changes['events'] &&\n !changes['events'].firstChange &&\n this.eventsKey() !== this.lastEventsKey;\n\n if (nameChanged || eventsChanged) {\n this.destroyElement();\n this.createElement();\n }\n\n // If props changed, update them\n if (changes['props'] && this.element) {\n this.applyProps();\n }\n }\n\n ngOnDestroy(): void {\n this.destroyElement();\n }\n\n // ─────────────────────────────────────────────────────────────\n // Element Management\n // ─────────────────────────────────────────────────────────────\n\n private eventsKey(): string {\n return (this.events ?? DEFAULT_UI_EVENTS).join('|');\n }\n\n private createElement(): void {\n if (!this.name) return;\n\n // Create the custom element\n this.element = this.renderer.createElement(this.name);\n\n // Apply initial props\n this.applyProps();\n\n // Setup event listeners\n this.setupEventListeners();\n\n // Append to host (not container, to avoid extra wrapper)\n this.renderer.appendChild(this.hostEl.nativeElement, this.element);\n }\n\n private destroyElement(): void {\n // Cleanup event listeners\n this.eventCleanups.forEach(cleanup => cleanup());\n this.eventCleanups = [];\n\n // Remove element\n if (this.element && this.element.parentNode) {\n this.renderer.removeChild(this.hostEl.nativeElement, this.element);\n }\n this.element = null;\n }\n\n /**\n * aparté elements are **attribute-driven** (`observedAttributes`): assigning a\n * property is either a silent no-op (nothing observes it) or throws outright on\n * a getter-only accessor — `<aparte-composer>`'s `placeholder`/`disabled` are\n * exactly that. So primitives go through `setAttribute`; only values an\n * attribute cannot carry (objects, functions) are handed over as properties.\n */\n private applyProps(): void {\n if (this.element) applyElementProps(this.element, this.props);\n }\n\n private setupEventListeners(): void {\n if (!this.element) return;\n\n this.lastEventsKey = this.eventsKey();\n (this.events ?? DEFAULT_UI_EVENTS).forEach(eventName => {\n const listener = (event: Event) => {\n this.elementEvent.emit(event as CustomEvent);\n };\n\n this.element!.addEventListener(eventName, listener);\n this.eventCleanups.push(() => {\n this.element?.removeEventListener(eventName, listener);\n });\n });\n }\n\n // ─────────────────────────────────────────────────────────────\n // Public API\n // ─────────────────────────────────────────────────────────────\n\n /** Get the underlying Web Component element */\n getElement<T extends HTMLElement = HTMLElement>(): T | null {\n return this.element as T | null;\n }\n\n /** Call a method on the underlying element */\n callMethod<T = unknown>(methodName: string, ...args: unknown[]): T | undefined {\n if (!this.element) return undefined;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const method = (this.element as any)[methodName];\n if (typeof method === 'function') {\n return method.apply(this.element, args) as T;\n }\n return undefined;\n }\n}\n","import { Injectable, OnDestroy, computed, signal } from '@angular/core';\nimport { AparteConfig, ConversationManager, type AparteConversation, type AparteStorageAdapter } from '@aparte/core';\nimport type { AparteMessage } from '@aparte/core';\n\n/**\n * Angular 19 Signal-based wrapper around ConversationManager.\n *\n * Register a storage adapter before calling init():\n * ```ts\n * // app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * {\n * provide: CONVERSATION_ADAPTER,\n * useValue: new IndexedDBAdapter('my-app-convs'),\n * },\n * ],\n * };\n * ```\n *\n * Then inject ConversationManagerService in any component or service.\n */\n@Injectable({ providedIn: 'root' })\nexport class ConversationManagerService implements OnDestroy {\n private _manager: ConversationManager | null = null;\n private _unsubscribe: (() => void) | null = null;\n\n // ─── Signals ─────────────────────────────────────────────────────────────\n\n /** All conversations (active + archived). */\n readonly conversations = signal<AparteConversation[]>([]);\n\n /** Active conversations only, newest first. */\n readonly activeConversations = computed(() =>\n this.conversations()\n .filter(c => !c.archivedAt)\n .sort((a, b) => b.updatedAt - a.updatedAt)\n );\n\n /** Archived conversations, newest first. */\n readonly archivedConversations = computed(() =>\n this.conversations()\n .filter(c => !!c.archivedAt)\n .sort((a, b) => b.updatedAt - a.updatedAt)\n );\n\n /** Currently active conversation id. */\n readonly activeId = signal<string | null>(null);\n\n /** The active conversation object (null when no conv is selected). */\n readonly activeConversation = computed(() => {\n const id = this.activeId();\n if (!id) return null;\n return this.conversations().find(c => c.id === id) ?? null;\n });\n\n // ─── Lifecycle ───────────────────────────────────────────────────────────\n\n /**\n * Initialise the service with a storage adapter.\n * Call once in your root component or app initialiser.\n */\n async init(adapter: AparteStorageAdapter): Promise<void> {\n this._manager = new ConversationManager(adapter);\n this._unsubscribe = this._manager.subscribe(convs => {\n this.conversations.set([...convs]);\n this.activeId.set(this._manager!.activeId);\n });\n await this._manager.init();\n // Sync activeId after load (manager may have no active conv yet)\n this.activeId.set(this._manager.activeId);\n // Register globally so AparteConversationController (used by aparte-chat)\n // can resolve it without explicit DI plumbing.\n AparteConfig.setConversationManager(this._manager);\n }\n\n ngOnDestroy(): void {\n this._unsubscribe?.();\n }\n\n // ─── Actions ─────────────────────────────────────────────────────────────\n\n /** Create a new empty conversation, make it active, return it. */\n async createNew(title?: string): Promise<AparteConversation> {\n this._assertInit();\n return this._manager!.createNew(title);\n }\n\n // Note: there is no `select()` / `clearActive()` here on purpose.\n // The active conversation is owned exclusively by AparteConversationController\n // (inside <aparte-chat>). To switch conversations, either bind\n // `[conversationId]` on <aparte-chat> or dispatch a window event:\n // window.dispatchEvent(new CustomEvent('aparte-select-conversation', {\n // detail: { id, targetId? },\n // }));\n // The `activeId` signal here is read-only and stays in sync via subscribe().\n\n /** Append a message to a conversation and persist. */\n async addMessage(convId: string, msg: AparteMessage): Promise<void> {\n this._assertInit();\n return this._manager!.addMessage(convId, msg);\n }\n\n /**\n * Replace all messages for a conversation.\n * Call after branch navigation or AI response completion.\n */\n async updateMessages(convId: string, messages: AparteMessage[]): Promise<void> {\n this._assertInit();\n return this._manager!.updateMessages(convId, messages);\n }\n\n /** Permanently delete a conversation. */\n async delete(id: string): Promise<void> {\n this._assertInit();\n return this._manager!.delete(id);\n }\n\n /** Archive a conversation. */\n async archive(id: string): Promise<void> {\n this._assertInit();\n return this._manager!.archive(id);\n }\n\n /** Restore an archived conversation. */\n async unarchive(id: string): Promise<void> {\n this._assertInit();\n return this._manager!.unarchive(id);\n }\n\n // ─── Private ─────────────────────────────────────────────────────────────\n\n private _assertInit(): void {\n if (!this._manager) {\n throw new Error(\n '[ConversationManagerService] Not initialised. Call init(adapter) before using the service.'\n );\n }\n }\n}\n","/**\n * aparté Angular wrapper\n * Angular 19 standalone components + services over the framework-agnostic web components.\n */\n\n// Configuration (a standalone provider function — no NgModule).\nexport { provideAparte, APARTE_CONFIG_TOKEN } from './lib/provide-aparte';\nexport type { ProvideAparteOptions, ApartePluginLoader } from './lib/provide-aparte';\n\n// Components (standalone — import them directly).\nexport { AparteChatComponent } from './lib/aparte-chat.component';\nexport { AparteUiComponent } from './lib/aparte-ui.component';\nexport type { AparteUiHandle } from './lib/aparte-ui.component';\n\n// Annex: client lifecycle + reactive conversation manager.\nexport { AparteAiService, APARTE_CLIENT_OPTIONS } from './lib/aparte-ai.service';\nexport { ConversationManagerService } from './lib/conversation-manager.service';\n\n// Public types — re-exported from `@aparte/core`, the single source of truth\n// (the component used to re-declare `AparteMessage`/`AparteSendEventDetail` locally).\nexport type {\n AparteMessage,\n AparteSendEventDetail,\n AparteActionEventDetail,\n AparteSegment,\n AparteTextSegment,\n AparteCodeSegment,\n AparteThinkingSegment,\n AparteTerminalSegment,\n} from '@aparte/core';\n\n// Re-export AparteConfig for direct access (config without `provideAparte`).\nexport { AparteConfig } from '@aparte/core';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"aparte-angular.mjs","sources":["../../src/lib/aparte-ai.service.ts","../../src/lib/provide-aparte.ts","../../src/lib/aparte-chat.component.ts","../../src/lib/aparte-ui.component.ts","../../src/lib/conversation-manager.service.ts","../../src/index.ts","../../src/aparte-angular.ts"],"sourcesContent":["import { Injectable, OnDestroy, inject, InjectionToken } from '@angular/core';\nimport { AparteClient, AparteClientOptions } from '@aparte/core';\n\n/**\n * Injection token for AparteClient configuration. Provided by `provideAparte()`;\n * omit it and the service falls back to `{}`.\n */\nexport const APARTE_CLIENT_OPTIONS = new InjectionToken<AparteClientOptions>('APARTE_CLIENT_OPTIONS');\n\n/**\n * AparteAiService\n *\n * Angular service to bridge the UI events with AI Providers.\n * Uses the agnostic `AparteClient` under the hood.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class AparteAiService implements OnDestroy {\n private readonly _clientOptions = inject(APARTE_CLIENT_OPTIONS, { optional: true });\n private _client: AparteClient = new AparteClient(this._clientOptions ?? {});\n\n /**\n * Start listening to `aparte-send` events globally.\n * This connects the <aparte-chat> components to the AI Providers.\n *\n * `provideAparte()` calls this for you on app init (its `autoConnect`,\n * on by default). Idempotent — a manual call on top of that is a no-op,\n * so it stays the escape hatch when configuring without `provideAparte`.\n */\n connect(): void {\n this._client.start();\n }\n\n /**\n * Stop listening.\n */\n disconnect(): void {\n this._client.stop();\n }\n\n /**\n * Abort the current AI response and all active tool calls.\n */\n abort(): void {\n this._client.abort();\n }\n\n ngOnDestroy(): void {\n this.disconnect();\n }\n}\n","import {\n DestroyRef,\n InjectionToken,\n inject,\n makeEnvironmentProviders,\n provideAppInitializer,\n type EnvironmentProviders,\n} from '@angular/core';\nimport {\n AparteConfig,\n type AparteAIProvider,\n type AparteClientOptions,\n type AparteIconProvider,\n type AparteLocale,\n type AparteMarkdownProvider,\n type AparteModelConfig,\n type AparteSkeletonProvider,\n} from '@aparte/core';\nimport { APARTE_CLIENT_OPTIONS, AparteAiService } from './aparte-ai.service';\n\n/**\n * Any function that initialises a plugin — sync or async, so it can wrap a\n * dynamic `import()` of a package YOU choose:\n * `() => import('@aparte/plugin-model-selector')`.\n */\nexport type ApartePluginLoader = () => void | Promise<void>;\n\n/**\n * Config for {@link provideAparte}. Deliberately **instance-agnostic**: every\n * plugin/locale slot takes a provider OBJECT or a LOADER function you supply —\n * this package never hardcodes (nor depends on) a catalog of `@aparte/*` package\n * names, so it stays a leaf with only `@aparte/core` + Angular as peers.\n */\nexport interface ProvideAparteOptions {\n /** AI providers to register (e.g. from `@aparte/provider-openai-compat`). */\n providers?: AparteAIProvider[];\n\n /** Optional plugin wiring — objects or loaders, never package-name strings. */\n plugins?: {\n /** Action plugins, as loaders: `[() => import('@aparte/plugin-model-selector')]`. */\n actions?: ApartePluginLoader[];\n /** An icon provider object, or a loader that registers one. */\n icons?: AparteIconProvider | ApartePluginLoader;\n /** A skeleton provider object, or a loader that registers one. */\n skeleton?: AparteSkeletonProvider | ApartePluginLoader;\n /** A loader that applies a theme. */\n theme?: ApartePluginLoader;\n /** A markdown provider `(raw: string) => string`, or a loader that registers one. */\n markdown?: AparteMarkdownProvider | ApartePluginLoader;\n };\n\n /** Model selection configuration. */\n modelConfig?: AparteModelConfig;\n\n /** A locale OBJECT (e.g. `fr` from `@aparte/locale-fr`) — not a package-name string. */\n locale?: AparteLocale;\n\n /** Theme mode; `'auto'` follows the system preference. */\n themeMode?: 'light' | 'dark' | 'auto';\n\n /** Options for the `AparteClient` mounted by {@link AparteAiService}. */\n clientOptions?: AparteClientOptions;\n\n /**\n * Start the {@link AparteAiService} client once the app initialises (after\n * providers/plugins are registered), so sends stream without a manual\n * `AparteAiService.connect()` — \"wire the config and it works\", same as the\n * React/Vue/Svelte wrappers. Default `true`; set `false` to control the\n * client lifecycle yourself.\n */\n autoConnect?: boolean;\n}\n\n/** Holds the resolved aparté config, for consumers that want to inject it. */\nexport const APARTE_CONFIG_TOKEN = new InjectionToken<ProvideAparteOptions>('APARTE_CONFIG');\n\nasync function loadIconPlugin(plugin: AparteIconProvider | ApartePluginLoader): Promise<void> {\n if (typeof plugin === 'object' && plugin !== null) {\n AparteConfig.setIconProvider(plugin);\n return;\n }\n try {\n await (plugin as ApartePluginLoader)();\n } catch (err) {\n console.warn('[aparte] Failed to load icon plugin', err);\n }\n}\n\nasync function loadSkeletonPlugin(plugin: AparteSkeletonProvider | ApartePluginLoader): Promise<void> {\n if (typeof plugin === 'object' && plugin !== null) {\n AparteConfig.setSkeletonProvider(plugin);\n return;\n }\n try {\n await (plugin as ApartePluginLoader)();\n } catch (err) {\n console.warn('[aparte] Failed to load skeleton plugin', err);\n }\n}\n\nasync function loadMarkdownPlugin(plugin: AparteMarkdownProvider | ApartePluginLoader): Promise<void> {\n // A markdown provider takes the raw string; a loader takes nothing.\n if (plugin.length >= 1) {\n AparteConfig.setMarkdownProvider(plugin as AparteMarkdownProvider);\n return;\n }\n try {\n await (plugin as ApartePluginLoader)();\n } catch (err) {\n console.warn('[aparte] Failed to load markdown plugin', err);\n }\n}\n\nasync function runLoader(loader: ApartePluginLoader, label: string): Promise<void> {\n try {\n await loader();\n } catch (err) {\n console.warn(`[aparte] Failed to load ${label} plugin`, err);\n }\n}\n\nasync function loadPlugins(options: ProvideAparteOptions): Promise<void> {\n const plugins = options.plugins;\n if (!plugins) return;\n const pending: Promise<void>[] = [];\n\n for (const action of plugins.actions ?? []) pending.push(runLoader(action, 'action'));\n if (plugins.icons) pending.push(loadIconPlugin(plugins.icons));\n if (plugins.skeleton) pending.push(loadSkeletonPlugin(plugins.skeleton));\n if (plugins.theme) pending.push(runLoader(plugins.theme, 'theme'));\n if (plugins.markdown) pending.push(loadMarkdownPlugin(plugins.markdown));\n\n await Promise.all(pending);\n}\n\n/** Reflect the theme mode on the document root. */\nfunction applyThemeMode(mode: 'light' | 'dark' | 'auto', destroyRef: DestroyRef): void {\n if (mode !== 'auto') {\n document.documentElement.setAttribute('data-aparte-theme', mode);\n return;\n }\n const query = window.matchMedia('(prefers-color-scheme: dark)');\n const onChange = (e: MediaQueryListEvent) => {\n document.documentElement.setAttribute('data-aparte-theme', e.matches ? 'dark' : 'light');\n };\n document.documentElement.setAttribute('data-aparte-theme', query.matches ? 'dark' : 'light');\n query.addEventListener('change', onChange);\n // Released with the environment injector, so repeated bootstraps (TestBed, a\n // multi-instance embed) don't stack listeners on the media query forever.\n destroyRef.onDestroy(() => query.removeEventListener('change', onChange));\n}\n\n/**\n * Configure aparté for a standalone Angular app. Registers your AI providers,\n * model config, locale and optional plugins on the global `AparteConfig`,\n * provides {@link APARTE_CLIENT_OPTIONS} for {@link AparteAiService}, and\n * starts the client (see `autoConnect`) — no manual\n * `AparteAiService.connect()` needed.\n *\n * The components (`AparteChatComponent`, `AparteUiComponent`) are standalone and\n * work WITHOUT this — it is config sugar. You can equally call `AparteConfig.*`\n * yourself, exactly like the React/Vue/Svelte wrappers do.\n *\n * @example\n * bootstrapApplication(App, {\n * providers: [\n * provideAparte({\n * providers: [createOpenAICompatProvider(presets.OPENROUTER)],\n * clientOptions: { keyResolver },\n * }),\n * ],\n * });\n */\nexport function provideAparte(options: ProvideAparteOptions = {}): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: APARTE_CONFIG_TOKEN, useValue: options },\n { provide: APARTE_CLIENT_OPTIONS, useValue: options.clientOptions ?? {} },\n provideAppInitializer(async () => {\n const destroyRef = inject(DestroyRef);\n // inject() only works before the first await — grab the service now,\n // connect at the end (after plugins) so the first send already sees\n // markdown/action providers. SSR-safe: no listener without a window.\n const ai = options.autoConnect !== false && typeof window !== 'undefined'\n ? inject(AparteAiService)\n : null;\n if (options.providers?.length) {\n AparteConfig.registerAIProvider(...options.providers);\n }\n if (options.modelConfig) {\n AparteConfig.setModelConfig(options.modelConfig);\n }\n if (options.locale) {\n AparteConfig.setLocale(options.locale);\n }\n await loadPlugins(options);\n if (options.themeMode) {\n applyThemeMode(options.themeMode, destroyRef);\n }\n ai?.connect();\n }),\n ]);\n}\n","import {\n Component,\n CUSTOM_ELEMENTS_SCHEMA,\n ElementRef,\n OnDestroy,\n ViewChild,\n QueryList,\n ViewChildren,\n output,\n signal,\n computed,\n ChangeDetectionStrategy,\n AfterViewInit,\n Input,\n TemplateRef,\n inject,\n effect,\n booleanAttribute,\n numberAttribute,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { Observable } from 'rxjs';\nimport type {\n AparteMessage,\n AparteSegment,\n AparteSendEventDetail,\n AparteChatHostBinding,\n AparteConfigClass,\n AparteActionEventDetail,\n AparteChatImperativeApi,\n} from '@aparte/core';\nimport { AparteChatHost, isAwaitingReply } from '@aparte/core';\n\n/**\n * AparteChatComponent — Angular 19 Wrapper\n *\n * Standalone component wrapping aparté Web Components with Angular Signals.\n * The streaming / branch-navigation / host-method orchestration (orphan-stream\n * guard, lifecycle tracking, conversation lifecycle, bubble reconciliation)\n * lives in the framework-agnostic `AparteChatHost` from `@aparte/core`; this\n * component only owns the Angular-idiomatic surface (signals, template, DI) and\n * binds the host over its `messages` signal.\n */\n@Component({\n selector: 'aparte-chat',\n standalone: true,\n imports: [NgTemplateOutlet],\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n changeDetection: ChangeDetectionStrategy.OnPush,\n // This selector is ALSO core's `<aparte-chat>` custom element, so the host gets\n // upgraded by core on insert. `framework-managed` tells that shell to keep its\n // hands off: THIS component renders the viewport + composer and drives them\n // through AparteChatHost. Without it, core injects its default composition\n // underneath ours (its own check can't see our children — they render later).\n host: { 'framework-managed': '' },\n template: `\n <div\n class=\"aparte-chat-container\"\n [class.aparte-chat-container--auto-center]=\"centerWhenEmpty()\"\n [attr.data-aparte-empty]=\"centerWhenEmpty() && messages().length === 0 ? '' : null\"\n >\n <aparte-chat-viewport #viewport framework-managed=\"\">\n @if (messages().length === 0) {\n <!-- Welcome / placeholder shown inside the viewport while empty. -->\n <ng-content select=\"[slot='empty-state']\"></ng-content>\n }\n @for (message of messages(); track message.id) {\n @if (bubbleTemplate) {\n <!-- Render your OWN element per message; driven by the reactive\n messages() signal so it streams live. -->\n <ng-container\n [ngTemplateOutlet]=\"bubbleTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: message }\"\n ></ng-container>\n } @else {\n <aparte-chat-bubble\n #bubble\n [attr.message-id]=\"message.id\"\n [attr.data-role]=\"message.role\"\n [attr.timestamp]=\"message.timestamp\"\n [attr.content]=\"message.content\"\n [attr.streaming]=\"awaitingReply(message) ? '' : null\"\n ></aparte-chat-bubble>\n }\n }\n <aparte-chat-status\n [attr.visible]=\"isTyping() ? '' : null\"\n [attr.text]=\"typingText()\"\n ></aparte-chat-status>\n </aparte-chat-viewport>\n\n <ng-content select=\"[slot='above-composer']\"></ng-content>\n\n <aparte-composer\n #input\n [attr.placeholder]=\"placeholder()\"\n [attr.disabled]=\"disabled() ? '' : null\"\n [attr.submit-on-enter]=\"submitOnEnter() ? null : 'false'\"\n (aparte-send)=\"onAparteSend($event)\"\n >\n <!-- Custom composer via [slot='composer']; falls back to the default\n shell (input · send + footer slots, plus the attachment primitives\n when the attachments input is set). Project your own\n aparte-composer-* layout for a skin-specific composer. -->\n <ng-content select=\"[slot='composer']\">\n <div class=\"aparte-composer-shell\">\n @if (attachments()) {\n <aparte-composer-attachments></aparte-composer-attachments>\n }\n <div class=\"aparte-composer-row\">\n @if (attachments()) {\n <aparte-composer-add-attachment></aparte-composer-add-attachment>\n }\n <aparte-composer-input></aparte-composer-input>\n <aparte-composer-send></aparte-composer-send>\n </div>\n <div class=\"aparte-composer-footer\">\n <ng-content select=\"[slot='footer-left']\"></ng-content>\n <ng-content select=\"[slot='footer-center']\"></ng-content>\n <ng-content select=\"[slot='footer-right']\"></ng-content>\n </div>\n </div>\n </ng-content>\n </aparte-composer>\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .aparte-chat-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n }\n\n aparte-chat-viewport {\n flex: 1;\n min-height: 0;\n }\n\n aparte-composer {\n flex-shrink: 0;\n }\n `]\n})\nexport class AparteChatComponent implements AfterViewInit, OnDestroy, AparteChatImperativeApi {\n constructor() {\n // Reactive effect to reconcile bubbles when the messages signal updates.\n // Debounced with requestAnimationFrame so rapid token bursts only trigger\n // one sync per paint frame instead of N syncs for N tokens.\n effect(() => {\n const msgs = this.messages();\n if (msgs.length > 0) {\n if (this._syncRafId !== null) return;\n this._syncRafId = requestAnimationFrame(() => {\n this._syncRafId = null;\n this._host?.syncBubbles();\n });\n }\n });\n }\n\n private elementRef = inject(ElementRef);\n\n /**\n * Template bridge to core's shared `isAwaitingReply` (an Angular template can't\n * call an imported function). One rule for the four wrappers and core itself,\n * so \"is this bubble in flight\" can't drift between them.\n */\n readonly awaitingReply = isAwaitingReply;\n\n // ── Input Signals ────────────────────────────────────────────────────────\n\n /** Messages to display */\n @Input('messages') set messagesInput(val: AparteMessage[]) {\n this.messages.set(val);\n // When messages are cleared (new conversation), reset the host's render cache\n // so the next conversation starts clean — same as React/Vue/Svelte do. (The\n // viewport's own clearMessages() is @deprecated in core and only clears its\n // repo; the host's clearAll() path already owns the real teardown.)\n if (val.length === 0) this._host?.clearRenderCache();\n }\n readonly messages = signal<AparteMessage[]>([]);\n\n /** Input placeholder text */\n @Input('placeholder') set placeholderInput(val: string) { this.placeholder.set(val); }\n readonly placeholder = signal<string>('Type a message...');\n\n /** Whether the input is disabled */\n @Input({ alias: 'disabled', transform: booleanAttribute }) set disabledInput(val: boolean) { this.disabled.set(val); }\n readonly disabled = signal<boolean>(false);\n\n /** When false, Shift+Enter submits and a bare Enter inserts a newline. */\n @Input({ alias: 'submitOnEnter', transform: booleanAttribute }) set submitOnEnterInput(val: boolean) { this.submitOnEnter.set(val); }\n readonly submitOnEnter = signal<boolean>(true);\n\n /**\n * Opt in to the \"centered composer when empty\" layout: the composer sits\n * vertically centered with the `[slot='empty-state']` content above it while\n * the list is empty, then slides to the bottom on the first message (~0.3s).\n * Off by default — additive (adds the `--auto-center` modifier + a\n * `data-aparte-empty` attribute the shipped `aparte.css` recipe keys off).\n */\n @Input({ alias: 'centerWhenEmpty', transform: booleanAttribute }) set centerWhenEmptyInput(val: boolean) { this.centerWhenEmpty.set(val); }\n readonly centerWhenEmpty = signal<boolean>(false);\n\n /**\n * Add the file picker + chips strip to the default composer shell. **Off by\n * default**, because the capability needs a host that consumes the files: an\n * `AparteClient` inlines them per its `rawFileInject` option, but if you drive\n * your own loop you must read `event.files` on `(messageSent)` — otherwise the\n * file the user deliberately attached is dropped in silence. No effect when you\n * project a `[slot='composer']` (drop `<aparte-composer-add-attachment>` and\n * `<aparte-composer-attachments>` in it yourself).\n */\n @Input({ alias: 'attachments', transform: booleanAttribute }) set attachmentsInput(val: boolean) { this.attachments.set(val); }\n readonly attachments = signal<boolean>(false);\n\n /** Whether the assistant is currently typing/streaming */\n @Input({ alias: 'isTyping', transform: booleanAttribute }) set isTypingInput(val: boolean) { this.isTyping.set(val); }\n readonly isTyping = signal<boolean>(false);\n\n /** Text to show in the typing status */\n @Input('typingText') set typingTextInput(val: string) { this.typingText.set(val); }\n readonly typingText = signal<string>('Assistant is thinking...');\n\n /** Duration in ms to freeze spacer recalculation after a conversation swap. */\n @Input({ alias: 'layoutTransitionMs', transform: numberAttribute }) layoutTransitionMs = 0;\n\n /**\n * Active conversation id. When provided, the host attaches an\n * `AparteConversationController` that loads/persists messages via the\n * `ConversationManager` registered in `AparteConfig`. Setting a different id\n * mid-stream aborts the previous request; `null` deselects.\n */\n @Input('conversationId') set conversationIdInput(val: string | null | undefined) {\n const next = val ?? null;\n if (next === this._conversationId) return;\n this._conversationId = next;\n if (this._host) void this._host.setConversationId(next);\n }\n private _conversationId: string | null = null;\n\n /**\n * Instance {@link AparteConfigClass} for this chat. When set, aparté components\n * inside resolve THIS config instead of the global `AparteConfig` singleton, so\n * several independently-configured chats can coexist on one page. Omit for the\n * global config. Read once in `ngAfterViewInit` when the host is created.\n */\n @Input() config?: AparteConfigClass;\n\n /**\n * Render your OWN element per message in place of `<aparte-chat-bubble>`.\n * Opt-in — provide a `<ng-template let-message>` and pass its ref. Driven by\n * the reactive `messages()` signal, so it updates live during streaming.\n * The built-in action bar (retry/edit/branch) belongs to the native bubble;\n * a custom bubble owns whatever it wires.\n * @example\n * <aparte-chat [bubbleTemplate]=\"tpl\" />\n * <ng-template #tpl let-message>{{ message.content }}</ng-template>\n */\n @Input() bubbleTemplate?: TemplateRef<{ $implicit: AparteMessage }>;\n\n // ── Outputs ────────────────────────────────────────────────────────────\n\n /**\n * User submitted a message from the composer. It is **appended to the thread\n * automatically** (optimistic UI) before this fires — do NOT add it again in\n * the handler (uncontrolled → duplicates; controlled → mirror it into your\n * own `[messages]`). For side-effects: scroll, analytics, send.\n */\n readonly messageSent = output<AparteSendEventDetail>();\n /**\n * Emitted when a custom bubble action (registered via\n * `AparteConfig.registerAction` with `zones: ['bubble']`) is clicked — a typed\n * wrapper over the bubbling `aparte-action` DOM event. Switch on `$event.actionId`.\n */\n readonly action = output<AparteActionEventDetail>();\n /** Emitted when messages are updated internally (e.g. by AparteClient) */\n readonly messagesChange = output<AparteMessage[]>();\n /** Emitted when a message is added internally (e.g. by appendMessage) */\n readonly messageAppended = output<AparteMessage>();\n /** The typing/\"thinking\" indicator toggled (the host flips it off on the first streamed token). */\n readonly typingChange = output<boolean>();\n /** Emitted when the controller lazily creates a conversation on first send. */\n readonly conversationCreated = output<string>();\n\n // ── View Children ────────────────────────────────────────────────────────\n @ViewChild('viewport') viewportRef?: ElementRef<HTMLElement>;\n @ViewChild('input') inputRef?: ElementRef<HTMLElement>;\n @ViewChildren('bubble') bubbleRefs!: QueryList<ElementRef<HTMLElement>>;\n\n // ── Private State ────────────────────────────────────────────────────────\n /** Mirror of the host's streaming target id (drives `isStreaming`). */\n private readonly _streamingId = signal<string | null>(null);\n /** Computed: is currently streaming */\n readonly isStreaming = computed(() => this._streamingId() !== null);\n\n /** rAF id used to coalesce rapid signal updates during streaming */\n private _syncRafId: number | null = null;\n\n /** The framework-agnostic chat-host orchestrator (created in ngAfterViewInit). */\n private _host?: AparteChatHost;\n private _unbindHost?: () => void;\n /** QueryList.changes subscription — released in ngOnDestroy so SPA route\n * churn doesn't leak a live subscription per mount. */\n private _bubbleRefsSub?: { unsubscribe(): void };\n\n ngAfterViewInit(): void {\n const host = this.elementRef.nativeElement as HTMLElement;\n\n // Ensure a stable id so aparte-composer can reference the host via `target`,\n // letting AparteClient find it without DOM traversal across re-renders.\n if (!host.id) host.id = `aparte-chat-${crypto.randomUUID()}`;\n const composerEl = this.inputRef?.nativeElement;\n if (composerEl) composerEl.setAttribute('target', host.id);\n\n const binding: AparteChatHostBinding = {\n hostId: host.id,\n host,\n viewport: this.viewportRef?.nativeElement ?? null,\n getMessages: () => this.messages(),\n setMessages: (msgs) => this.messages.set(msgs as AparteMessage[]),\n onMessagesChange: (msgs) => this.messagesChange.emit(msgs as AparteMessage[]),\n onMessageAppended: (msg) => this.messageAppended.emit(msg as AparteMessage),\n onTypingChange: (typing) => { this.isTyping.set(typing); this.typingChange.emit(typing); },\n onStreamingChange: (id) => this._streamingId.set(id),\n // Sibling-info / deferred work runs after Angular has re-rendered.\n afterRender: (cb) => { setTimeout(cb, 0); },\n resetComposer: () => {\n (this.inputRef?.nativeElement as unknown as { reset?: () => void })?.reset?.();\n },\n };\n\n this._host = new AparteChatHost(binding, {\n layoutTransitionMs: this.layoutTransitionMs,\n conversationId: this._conversationId,\n onConversationCreated: (id) => {\n this._conversationId = id;\n this.conversationCreated.emit(id);\n },\n config: this.config,\n });\n this._unbindHost = this._host.bind();\n\n // Custom bubble actions bubble to the host as `aparte-action`; surface them as\n // the typed `action` output. (addEventListener, not @HostListener: Angular\n // parses a colon in the event name as a `target:event` global target.)\n host.addEventListener('aparte-action', this._onAction);\n\n // Re-reconcile bubbles whenever Angular's @for materialises/destroys them.\n this._host.syncBubbles();\n this._bubbleRefsSub = this.bubbleRefs.changes.subscribe(() => this._host?.syncBubbles());\n }\n\n private readonly _onAction = (event: Event): void => {\n this.action.emit((event as CustomEvent<AparteActionEventDetail>).detail);\n };\n\n ngOnDestroy(): void {\n if (this._syncRafId !== null) {\n cancelAnimationFrame(this._syncRafId);\n this._syncRafId = null;\n }\n (this.elementRef.nativeElement as HTMLElement).removeEventListener('aparte-action', this._onAction);\n this._bubbleRefsSub?.unsubscribe();\n this._bubbleRefsSub = undefined;\n this._unbindHost?.();\n this._unbindHost = undefined;\n this._host = undefined;\n }\n\n // ── Public imperative API (delegates to the host) ──────────────────────────\n\n /** Append a message optimistically. */\n appendMessage(message: AparteMessage): void { this._host?.appendMessage(message); }\n /** Atomic update for a message. */\n updateMessage(messageId: string, updates: Partial<AparteMessage>): void {\n this._host?.updateMessage(messageId, updates);\n }\n /** Update the last message content (streaming text). */\n updateLastMessage(content: string, options?: { append?: boolean }): void {\n this._host?.updateLastMessage(content, options);\n }\n /** Add a segment to the last message. */\n addSegment(segment: AparteSegment): void { this._host?.addSegment(segment); }\n /** Update a segment in the last message. */\n updateSegment(segmentId: string, updates: Partial<AparteSegment>): void {\n this._host?.updateSegment(segmentId, updates);\n }\n /** Remove a transient segment. */\n removeSegment(segmentId: string): void { this._host?.removeSegment(segmentId); }\n /** Append content to a segment in the last message. */\n appendToSegment(segmentId: string, content: string): void {\n this._host?.appendToSegment(segmentId, content);\n }\n /** Read the current message list. */\n getMessages(): AparteMessage[] { return this._host?.getMessages() ?? this.messages(); }\n /** Clear all messages + reset state. */\n clearMessages(): void { this._host?.clearMessages(); }\n /** Scroll the viewport to the latest message. */\n scrollToBottom(): void {\n (this.viewportRef?.nativeElement as unknown as { scrollToBottom?: () => void })?.scrollToBottom?.();\n }\n /**\n * The `<aparte-chat-viewport>` element — for custom scroll handling, an\n * IntersectionObserver, etc. Same `getViewport()` accessor on all four\n * wrappers.\n */\n getViewport(): HTMLElement | null { return this.viewportRef?.nativeElement ?? null; }\n /** Focus the composer input. */\n focusInput(): void {\n (this.inputRef?.nativeElement as unknown as { focus?: () => void })?.focus?.();\n }\n /** Create a new branch from a message (returns the new sibling index). */\n addBranch(messageId: string): number { return this._host?.addBranch(messageId) ?? 0; }\n /** Add a sibling of an existing message (returns the new id). */\n addSiblingOf(existingId: string, newMessage: AparteMessage): string | null {\n return this._host?.addSiblingOf(existingId, newMessage) ?? null;\n }\n /** Remove a message and all descendants (edit flow). */\n truncateFrom(messageId: string): void { this._host?.truncateFrom(messageId); }\n /** Keep up to and including a user message, drop later responses (retry). */\n truncateResponsesAfter(userMessageId: string): void {\n this._host?.truncateResponsesAfter(userMessageId);\n }\n\n // ── Token streaming (cross-wrapper contract + Observable adapter) ──────────\n\n /**\n * Inject a token stream for LLM streaming. Takes the cross-wrapper\n * `AsyncIterable<string>` contract (the exact call that works on\n * React/Vue/Svelte) — or an Angular-idiomatic RxJS `Observable<string>`,\n * adapted into the host's agnostic `streamTokens(AsyncIterable)` so the\n * orphan-stream guard + id tracking stay in one place (the host).\n */\n async injectTokenStream(\n messageId: string,\n stream: Observable<string> | AsyncIterable<string>,\n ): Promise<void> {\n if (!this._host) return;\n const tokens = Symbol.asyncIterator in stream\n ? (stream as AsyncIterable<string>)\n : this._observableToAsyncIterable(stream as Observable<string>);\n await this._host.streamTokens(messageId, tokens);\n }\n\n /** Stop any active token stream. */\n stopTokenStream(): void { this._host?.stopTokenStream(); }\n\n /**\n * Set the active conversation id imperatively — parity with the other\n * wrappers' handles (the `conversationId` `@Input` remains the declarative\n * path). Delegates to the host, which loads/persists via the registered\n * `ConversationManager`.\n */\n setConversationId(id: string | null): Promise<void> {\n return this._host?.setConversationId(id) ?? Promise.resolve();\n }\n\n private _observableToAsyncIterable(stream: Observable<string>): AsyncIterable<string> {\n return {\n [Symbol.asyncIterator](): AsyncIterator<string> {\n const buffer: string[] = [];\n let finished = false;\n let failure: unknown = null;\n let pending: {\n resolve: (r: IteratorResult<string>) => void;\n reject: (e: unknown) => void;\n } | null = null;\n const settle = () => {\n if (!pending) return;\n if (failure !== null) { const p = pending; pending = null; p.reject(failure); return; }\n if (buffer.length) {\n const p = pending; pending = null;\n p.resolve({ value: buffer.shift() as string, done: false });\n return;\n }\n if (finished) {\n const p = pending; pending = null;\n p.resolve({ value: undefined as unknown as string, done: true });\n }\n };\n const sub = stream.subscribe({\n next: (v) => { buffer.push(v); settle(); },\n error: (e) => { failure = e; settle(); },\n complete: () => { finished = true; settle(); },\n });\n return {\n next(): Promise<IteratorResult<string>> {\n if (failure !== null) return Promise.reject(failure);\n if (buffer.length) {\n return Promise.resolve({ value: buffer.shift() as string, done: false });\n }\n if (finished) {\n return Promise.resolve({ value: undefined as unknown as string, done: true });\n }\n return new Promise((resolve, reject) => { pending = { resolve, reject }; });\n },\n return(): Promise<IteratorResult<string>> {\n sub.unsubscribe();\n // If a consumer is mid-`await next()` on an empty buffer (e.g. the\n // orphan-stream guard calling `return()` on stop/teardown), settle\n // that pending promise now with done:true — otherwise it hangs\n // forever, since unsubscribing means `next` and `complete` will\n // never fire again to resolve it.\n if (pending) {\n const p = pending;\n pending = null;\n p.resolve({ value: undefined as unknown as string, done: true });\n }\n finished = true;\n return Promise.resolve({ value: undefined as unknown as string, done: true });\n },\n };\n },\n };\n }\n\n /** Handle aparte-send event from the composer Web Component. */\n onAparteSend(event: Event): void {\n const detail = (event as CustomEvent<AparteSendEventDetail>).detail;\n // Smooth-scroll the next auto-scroll (when Angular adds the user bubble).\n (this.viewportRef?.nativeElement as unknown as { requestSmoothScroll?: () => void })\n ?.requestSmoothScroll?.();\n this.messageSent.emit(detail);\n }\n}\n","import {\n Component,\n CUSTOM_ELEMENTS_SCHEMA,\n ElementRef,\n OnChanges,\n OnDestroy,\n AfterViewInit,\n SimpleChanges,\n ChangeDetectionStrategy,\n Input,\n output,\n Renderer2,\n inject\n} from '@angular/core';\nimport { applyElementProps, DEFAULT_UI_EVENTS } from '@aparte/core';\n\n/**\n * The imperative surface of the `AparteUi` proxy — the same\n * `getElement`/`callMethod` contract on all four wrappers.\n */\nexport interface AparteUiHandle {\n getElement<T extends HTMLElement = HTMLElement>(): T | null;\n callMethod<T = unknown>(methodName: string, ...args: unknown[]): T | undefined;\n}\n\n/**\n * AparteUiComponent - Universal UI Proxy\n *\n * A pass-through proxy component that dynamically injects any aparté\n * Web Component, so you don't need a dedicated Angular wrapper per element.\n *\n * @example\n * ```html\n * <aparte-ui\n * name=\"aparte-model-selector\"\n * [props]=\"{\n * placeholder: 'Ask anything...',\n * '--glow-opacity': '1',\n * '--glow-speed': '4s'\n * }\"\n * (elementEvent)=\"onEvent($event)\"\n * />\n * ```\n *\n * @description\n * - Keys starting with `--` are applied as CSS Variables\n * - Other keys are set as DOM properties on the element\n * - The events in `events` (default: {@link DEFAULT_UI_EVENTS}) bubble up via `elementEvent`\n */\n@Component({\n selector: 'aparte-ui',\n standalone: true,\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `<ng-container></ng-container>`,\n styles: [`\n :host {\n display: contents;\n }\n `]\n})\nexport class AparteUiComponent implements AfterViewInit, OnChanges, OnDestroy, AparteUiHandle {\n private readonly renderer = inject(Renderer2);\n private readonly hostEl = inject(ElementRef);\n\n // ─────────────────────────────────────────────────────────────\n // Inputs\n // ─────────────────────────────────────────────────────────────\n\n /** The custom element tag name (e.g., 'aparte-model-selector') */\n @Input({ required: true }) name!: string;\n\n /** Properties to pass to the element. Keys starting with '--' are CSS vars */\n @Input() props: Record<string, unknown> = {};\n\n /**\n * Which custom events to forward through `elementEvent`. Defaults to the\n * interactive aparté surface ({@link DEFAULT_UI_EVENTS}); pass your own list to\n * listen to other events (e.g. `['aparte-composer-change']` for attachments).\n */\n @Input() events?: string[];\n\n // ─────────────────────────────────────────────────────────────\n // Outputs\n // ─────────────────────────────────────────────────────────────\n\n /** Emits a forwarded custom event from the underlying Web Component */\n readonly elementEvent = output<CustomEvent>();\n\n // ─────────────────────────────────────────────────────────────\n // Internal State\n // ─────────────────────────────────────────────────────────────\n\n /** The dynamically created Web Component element */\n private element: HTMLElement | null = null;\n\n /** Cleanup functions for event listeners */\n private eventCleanups: (() => void)[] = [];\n\n /** Joined key of the bound event set, so a fresh inline `[events]` array\n * doesn't thrash the element — only a real change rebinds. */\n private lastEventsKey = '';\n\n // ─────────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────────\n\n ngAfterViewInit(): void {\n this.createElement();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n // Recreate the element when `name` (or the forwarded event set) changes.\n const nameChanged = !!changes['name'] && !changes['name'].firstChange;\n const eventsChanged =\n !!changes['events'] &&\n !changes['events'].firstChange &&\n this.eventsKey() !== this.lastEventsKey;\n\n if (nameChanged || eventsChanged) {\n this.destroyElement();\n this.createElement();\n }\n\n // If props changed, update them\n if (changes['props'] && this.element) {\n this.applyProps();\n }\n }\n\n ngOnDestroy(): void {\n this.destroyElement();\n }\n\n // ─────────────────────────────────────────────────────────────\n // Element Management\n // ─────────────────────────────────────────────────────────────\n\n private eventsKey(): string {\n return (this.events ?? DEFAULT_UI_EVENTS).join('|');\n }\n\n private createElement(): void {\n if (!this.name) return;\n\n // Create the custom element\n this.element = this.renderer.createElement(this.name);\n\n // Apply initial props\n this.applyProps();\n\n // Setup event listeners\n this.setupEventListeners();\n\n // Append to host (not container, to avoid extra wrapper)\n this.renderer.appendChild(this.hostEl.nativeElement, this.element);\n }\n\n private destroyElement(): void {\n // Cleanup event listeners\n this.eventCleanups.forEach(cleanup => cleanup());\n this.eventCleanups = [];\n\n // Remove element\n if (this.element && this.element.parentNode) {\n this.renderer.removeChild(this.hostEl.nativeElement, this.element);\n }\n this.element = null;\n }\n\n /**\n * aparté elements are **attribute-driven** (`observedAttributes`): assigning a\n * property is either a silent no-op (nothing observes it) or throws outright on\n * a getter-only accessor — `<aparte-composer>`'s `placeholder`/`disabled` are\n * exactly that. So primitives go through `setAttribute`; only values an\n * attribute cannot carry (objects, functions) are handed over as properties.\n */\n private applyProps(): void {\n if (this.element) applyElementProps(this.element, this.props);\n }\n\n private setupEventListeners(): void {\n if (!this.element) return;\n\n this.lastEventsKey = this.eventsKey();\n (this.events ?? DEFAULT_UI_EVENTS).forEach(eventName => {\n const listener = (event: Event) => {\n this.elementEvent.emit(event as CustomEvent);\n };\n\n this.element!.addEventListener(eventName, listener);\n this.eventCleanups.push(() => {\n this.element?.removeEventListener(eventName, listener);\n });\n });\n }\n\n // ─────────────────────────────────────────────────────────────\n // Public API\n // ─────────────────────────────────────────────────────────────\n\n /** Get the underlying Web Component element */\n getElement<T extends HTMLElement = HTMLElement>(): T | null {\n return this.element as T | null;\n }\n\n /** Call a method on the underlying element */\n callMethod<T = unknown>(methodName: string, ...args: unknown[]): T | undefined {\n if (!this.element) return undefined;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const method = (this.element as any)[methodName];\n if (typeof method === 'function') {\n return method.apply(this.element, args) as T;\n }\n return undefined;\n }\n}\n","import { Injectable, OnDestroy, computed, signal } from '@angular/core';\nimport { AparteConfig, ConversationManager, type AparteConversation, type AparteStorageAdapter } from '@aparte/core';\nimport type { AparteMessage } from '@aparte/core';\n\n/**\n * Angular 19 Signal-based wrapper around ConversationManager.\n *\n * Register a storage adapter before calling init():\n * ```ts\n * // app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * {\n * provide: CONVERSATION_ADAPTER,\n * useValue: new IndexedDBAdapter('my-app-convs'),\n * },\n * ],\n * };\n * ```\n *\n * Then inject ConversationManagerService in any component or service.\n */\n@Injectable({ providedIn: 'root' })\nexport class ConversationManagerService implements OnDestroy {\n private _manager: ConversationManager | null = null;\n private _unsubscribe: (() => void) | null = null;\n\n // ─── Signals ─────────────────────────────────────────────────────────────\n\n /** All conversations (active + archived). */\n readonly conversations = signal<AparteConversation[]>([]);\n\n /** Active conversations only, newest first. */\n readonly activeConversations = computed(() =>\n this.conversations()\n .filter(c => !c.archivedAt)\n .sort((a, b) => b.updatedAt - a.updatedAt)\n );\n\n /** Archived conversations, newest first. */\n readonly archivedConversations = computed(() =>\n this.conversations()\n .filter(c => !!c.archivedAt)\n .sort((a, b) => b.updatedAt - a.updatedAt)\n );\n\n /** Currently active conversation id. */\n readonly activeId = signal<string | null>(null);\n\n /** The active conversation object (null when no conv is selected). */\n readonly activeConversation = computed(() => {\n const id = this.activeId();\n if (!id) return null;\n return this.conversations().find(c => c.id === id) ?? null;\n });\n\n // ─── Lifecycle ───────────────────────────────────────────────────────────\n\n /**\n * Initialise the service with a storage adapter.\n * Call once in your root component or app initialiser.\n */\n async init(adapter: AparteStorageAdapter): Promise<void> {\n this._manager = new ConversationManager(adapter);\n this._unsubscribe = this._manager.subscribe(convs => {\n this.conversations.set([...convs]);\n this.activeId.set(this._manager!.activeId);\n });\n await this._manager.init();\n // Sync activeId after load (manager may have no active conv yet)\n this.activeId.set(this._manager.activeId);\n // Register globally so AparteConversationController (used by aparte-chat)\n // can resolve it without explicit DI plumbing.\n AparteConfig.setConversationManager(this._manager);\n }\n\n ngOnDestroy(): void {\n this._unsubscribe?.();\n }\n\n // ─── Actions ─────────────────────────────────────────────────────────────\n\n /** Create a new empty conversation, make it active, return it. */\n async createNew(title?: string): Promise<AparteConversation> {\n this._assertInit();\n return this._manager!.createNew(title);\n }\n\n // Note: there is no `select()` / `clearActive()` here on purpose.\n // The active conversation is owned exclusively by AparteConversationController\n // (inside <aparte-chat>). To switch conversations, either bind\n // `[conversationId]` on <aparte-chat> or dispatch a window event:\n // window.dispatchEvent(new CustomEvent('aparte-select-conversation', {\n // detail: { id, targetId? },\n // }));\n // The `activeId` signal here is read-only and stays in sync via subscribe().\n\n /** Append a message to a conversation and persist. */\n async addMessage(convId: string, msg: AparteMessage): Promise<void> {\n this._assertInit();\n return this._manager!.addMessage(convId, msg);\n }\n\n /**\n * Replace all messages for a conversation.\n * Call after branch navigation or AI response completion.\n */\n async updateMessages(convId: string, messages: AparteMessage[]): Promise<void> {\n this._assertInit();\n return this._manager!.updateMessages(convId, messages);\n }\n\n /** Permanently delete a conversation. */\n async delete(id: string): Promise<void> {\n this._assertInit();\n return this._manager!.delete(id);\n }\n\n /** Archive a conversation. */\n async archive(id: string): Promise<void> {\n this._assertInit();\n return this._manager!.archive(id);\n }\n\n /** Restore an archived conversation. */\n async unarchive(id: string): Promise<void> {\n this._assertInit();\n return this._manager!.unarchive(id);\n }\n\n // ─── Private ─────────────────────────────────────────────────────────────\n\n private _assertInit(): void {\n if (!this._manager) {\n throw new Error(\n '[ConversationManagerService] Not initialised. Call init(adapter) before using the service.'\n );\n }\n }\n}\n","/**\n * aparté Angular wrapper\n * Angular 19 standalone components + services over the framework-agnostic web components.\n */\n\n// Configuration (a standalone provider function — no NgModule).\nexport { provideAparte, APARTE_CONFIG_TOKEN } from './lib/provide-aparte';\nexport type { ProvideAparteOptions, ApartePluginLoader } from './lib/provide-aparte';\n\n// Components (standalone — import them directly).\nexport { AparteChatComponent } from './lib/aparte-chat.component';\nexport { AparteUiComponent } from './lib/aparte-ui.component';\nexport type { AparteUiHandle } from './lib/aparte-ui.component';\n\n// Annex: client lifecycle + reactive conversation manager.\nexport { AparteAiService, APARTE_CLIENT_OPTIONS } from './lib/aparte-ai.service';\nexport { ConversationManagerService } from './lib/conversation-manager.service';\n\n// Public types — re-exported from `@aparte/core`, the single source of truth\n// (the component used to re-declare `AparteMessage`/`AparteSendEventDetail` locally).\nexport type {\n AparteMessage,\n AparteSendEventDetail,\n AparteActionEventDetail,\n AparteSegment,\n AparteTextSegment,\n AparteCodeSegment,\n AparteThinkingSegment,\n AparteTerminalSegment,\n} from '@aparte/core';\n\n// Re-export AparteConfig for direct access (config without `provideAparte`).\nexport { AparteConfig } from '@aparte/core';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ElementRef, OnDestroy, QueryList, AfterViewInit, TemplateRef } from '@angular/core';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
import type { AparteMessage, AparteSegment, AparteSendEventDetail, AparteConfigClass, AparteActionEventDetail, AparteChatImperativeApi } from '@aparte/core';
|
|
4
|
+
import { isAwaitingReply } from '@aparte/core';
|
|
4
5
|
import * as i0 from "@angular/core";
|
|
5
6
|
/**
|
|
6
7
|
* AparteChatComponent — Angular 19 Wrapper
|
|
@@ -15,6 +16,12 @@ import * as i0 from "@angular/core";
|
|
|
15
16
|
export declare class AparteChatComponent implements AfterViewInit, OnDestroy, AparteChatImperativeApi {
|
|
16
17
|
constructor();
|
|
17
18
|
private elementRef;
|
|
19
|
+
/**
|
|
20
|
+
* Template bridge to core's shared `isAwaitingReply` (an Angular template can't
|
|
21
|
+
* call an imported function). One rule for the four wrappers and core itself,
|
|
22
|
+
* so "is this bubble in flight" can't drift between them.
|
|
23
|
+
*/
|
|
24
|
+
readonly awaitingReply: typeof isAwaitingReply;
|
|
18
25
|
/** Messages to display */
|
|
19
26
|
set messagesInput(val: AparteMessage[]);
|
|
20
27
|
readonly messages: import("@angular/core").WritableSignal<AparteMessage[]>;
|
|
@@ -36,6 +43,17 @@ export declare class AparteChatComponent implements AfterViewInit, OnDestroy, Ap
|
|
|
36
43
|
*/
|
|
37
44
|
set centerWhenEmptyInput(val: boolean);
|
|
38
45
|
readonly centerWhenEmpty: import("@angular/core").WritableSignal<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Add the file picker + chips strip to the default composer shell. **Off by
|
|
48
|
+
* default**, because the capability needs a host that consumes the files: an
|
|
49
|
+
* `AparteClient` inlines them per its `rawFileInject` option, but if you drive
|
|
50
|
+
* your own loop you must read `event.files` on `(messageSent)` — otherwise the
|
|
51
|
+
* file the user deliberately attached is dropped in silence. No effect when you
|
|
52
|
+
* project a `[slot='composer']` (drop `<aparte-composer-add-attachment>` and
|
|
53
|
+
* `<aparte-composer-attachments>` in it yourself).
|
|
54
|
+
*/
|
|
55
|
+
set attachmentsInput(val: boolean);
|
|
56
|
+
readonly attachments: import("@angular/core").WritableSignal<boolean>;
|
|
39
57
|
/** Whether the assistant is currently typing/streaming */
|
|
40
58
|
set isTypingInput(val: boolean);
|
|
41
59
|
readonly isTyping: import("@angular/core").WritableSignal<boolean>;
|
|
@@ -170,10 +188,11 @@ export declare class AparteChatComponent implements AfterViewInit, OnDestroy, Ap
|
|
|
170
188
|
/** Handle aparte-send event from the composer Web Component. */
|
|
171
189
|
onAparteSend(event: Event): void;
|
|
172
190
|
static ɵfac: i0.ɵɵFactoryDeclaration<AparteChatComponent, never>;
|
|
173
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<AparteChatComponent, "aparte-chat", never, { "messagesInput": { "alias": "messages"; "required": false; }; "placeholderInput": { "alias": "placeholder"; "required": false; }; "disabledInput": { "alias": "disabled"; "required": false; }; "submitOnEnterInput": { "alias": "submitOnEnter"; "required": false; }; "centerWhenEmptyInput": { "alias": "centerWhenEmpty"; "required": false; }; "isTypingInput": { "alias": "isTyping"; "required": false; }; "typingTextInput": { "alias": "typingText"; "required": false; }; "layoutTransitionMs": { "alias": "layoutTransitionMs"; "required": false; }; "conversationIdInput": { "alias": "conversationId"; "required": false; }; "config": { "alias": "config"; "required": false; }; "bubbleTemplate": { "alias": "bubbleTemplate"; "required": false; }; }, { "messageSent": "messageSent"; "action": "action"; "messagesChange": "messagesChange"; "messageAppended": "messageAppended"; "typingChange": "typingChange"; "conversationCreated": "conversationCreated"; }, never, ["[slot='empty-state']", "[slot='above-composer']", "[slot='footer-left']", "[slot='footer-center']", "[slot='footer-right']", "[slot='composer']"], true, never>;
|
|
191
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<AparteChatComponent, "aparte-chat", never, { "messagesInput": { "alias": "messages"; "required": false; }; "placeholderInput": { "alias": "placeholder"; "required": false; }; "disabledInput": { "alias": "disabled"; "required": false; }; "submitOnEnterInput": { "alias": "submitOnEnter"; "required": false; }; "centerWhenEmptyInput": { "alias": "centerWhenEmpty"; "required": false; }; "attachmentsInput": { "alias": "attachments"; "required": false; }; "isTypingInput": { "alias": "isTyping"; "required": false; }; "typingTextInput": { "alias": "typingText"; "required": false; }; "layoutTransitionMs": { "alias": "layoutTransitionMs"; "required": false; }; "conversationIdInput": { "alias": "conversationId"; "required": false; }; "config": { "alias": "config"; "required": false; }; "bubbleTemplate": { "alias": "bubbleTemplate"; "required": false; }; }, { "messageSent": "messageSent"; "action": "action"; "messagesChange": "messagesChange"; "messageAppended": "messageAppended"; "typingChange": "typingChange"; "conversationCreated": "conversationCreated"; }, never, ["[slot='empty-state']", "[slot='above-composer']", "[slot='footer-left']", "[slot='footer-center']", "[slot='footer-right']", "[slot='composer']"], true, never>;
|
|
174
192
|
static ngAcceptInputType_disabledInput: unknown;
|
|
175
193
|
static ngAcceptInputType_submitOnEnterInput: unknown;
|
|
176
194
|
static ngAcceptInputType_centerWhenEmptyInput: unknown;
|
|
195
|
+
static ngAcceptInputType_attachmentsInput: unknown;
|
|
177
196
|
static ngAcceptInputType_isTypingInput: unknown;
|
|
178
197
|
static ngAcceptInputType_layoutTransitionMs: unknown;
|
|
179
198
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aparte/angular",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-alpha.0",
|
|
4
4
|
"description": "Angular 19 wrapper for aparté — an ergonomic <aparte-chat> component plus services over the framework-agnostic web components.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@angular/common": "^19.2.0",
|
|
31
31
|
"@angular/core": "^19.2.0",
|
|
32
32
|
"rxjs": "^7.8.0",
|
|
33
|
-
"@aparte/core": "0.
|
|
33
|
+
"@aparte/core": "0.4.0-alpha.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@analogjs/vitest-angular": "^2.2.2",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"typescript": "^5.4.0",
|
|
46
46
|
"vite": "^6.0.0",
|
|
47
47
|
"zone.js": "~0.15.0",
|
|
48
|
-
"@aparte/core": "0.
|
|
48
|
+
"@aparte/core": "0.4.0-alpha.0"
|
|
49
49
|
},
|
|
50
50
|
"keywords": [
|
|
51
51
|
"angular",
|
|
@@ -65,6 +65,8 @@
|
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"build": "ng-packagr -p ng-package.json",
|
|
68
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
69
|
+
"typecheck:tests": "tsc -p tsconfig.spec.json --noEmit",
|
|
68
70
|
"test": "vitest",
|
|
69
71
|
"test:run": "vitest run",
|
|
70
72
|
"test:coverage": "vitest run --coverage"
|