@aparte/svelte 0.16.10 → 0.17.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,5 +1,5 @@
1
1
  <script>import { onMount, onDestroy, tick, createEventDispatcher } from "svelte";
2
- import { AparteChatHost, isAwaitingReply, uuid } from "@aparte/core";
2
+ import { AparteChatHost, aparteGlobalConfig, isAwaitingReply, uuid } from "@aparte/core";
3
3
  export let id = void 0;
4
4
  export let messages = [];
5
5
  export let placeholder = "Type a message...";
@@ -9,6 +9,10 @@ export let typingText = "Assistant is thinking...";
9
9
  export let submitOnEnter = true;
10
10
  export let layoutTransitionMs = 0;
11
11
  export let centerWhenEmpty = false;
12
+ export let loading = false;
13
+ let hostLoading = false;
14
+ $: waiting = loading || hostLoading;
15
+ $: loadingText = (config ?? aparteGlobalConfig).t("loadingConversation");
12
16
  export let overlayComposer = false;
13
17
  export let attachments = false;
14
18
  export let elicitation = true;
@@ -55,10 +59,11 @@ function toggleAttr(el, name, on, value) {
55
59
  if (on) el.setAttribute(name, value);
56
60
  else el.removeAttribute(name);
57
61
  }
62
+ $: if (viewportRef) toggleAttr(viewportRef, "loading", waiting, "");
58
63
  $: if (composerRef) {
59
64
  composerRef.setAttribute("target", hostId);
60
65
  composerRef.setAttribute("placeholder", placeholder);
61
- toggleAttr(composerRef, "disabled", disabled, "");
66
+ toggleAttr(composerRef, "disabled", disabled || waiting, "");
62
67
  toggleAttr(composerRef, "submit-on-enter", !submitOnEnter, "false");
63
68
  }
64
69
  function handleSend(event) {
@@ -101,7 +106,10 @@ onMount(() => {
101
106
  afterRender: (cb) => {
102
107
  void tick().then(cb);
103
108
  },
104
- resetComposer: () => composerRef?.reset?.()
109
+ resetComposer: () => composerRef?.reset?.(),
110
+ onLoadingChange: (on) => {
111
+ hostLoading = on;
112
+ }
105
113
  };
106
114
  host = new AparteChatHost(binding, {
107
115
  layoutTransitionMs,
@@ -146,8 +154,8 @@ export function appendToSegment(segmentId, content) {
146
154
  export function getMessages() {
147
155
  return host?.getMessages() ?? internalMessages;
148
156
  }
149
- export function clearMessages() {
150
- host?.clearMessages();
157
+ export function clearMessages(options) {
158
+ host?.clearMessages(options);
151
159
  }
152
160
  export function addBranch(messageId) {
153
161
  return host?.addBranch(messageId) ?? 0;
@@ -214,13 +222,25 @@ function _assertImperativeParity() {
214
222
  {style}
215
223
  data-aparte-chat
216
224
  {...(overlayComposer ? { 'overlay-composer': '' } : {})}
217
- data-aparte-empty={centerWhenEmpty && internalMessages.length === 0 ? '' : null}
225
+ data-aparte-empty={centerWhenEmpty && internalMessages.length === 0 && !waiting ? '' : null}
218
226
  id={hostId}
219
227
  bind:this={rootRef}
220
228
  >
221
229
  <aparte-chat-viewport bind:this={viewportRef} framework-managed="">
230
+ <!-- The wait, drawn here because this DOM is Svelte's: the kit's skeleton recipe,
231
+ and a line for a screen reader. -->
232
+ {#if waiting}
233
+ <div class="aparte-viewport-loading" aria-hidden="true">
234
+ <span class="aparte-skeleton aparte-skeleton--rect aparte-viewport-loading__user"></span>
235
+ <span class="aparte-skeleton aparte-skeleton--text"></span>
236
+ <span class="aparte-skeleton aparte-skeleton--text"></span>
237
+ <span class="aparte-skeleton aparte-skeleton--text"></span>
238
+ <span class="aparte-skeleton aparte-skeleton--text aparte-viewport-loading__last"></span>
239
+ </div>
240
+ <span class="aparte-viewport-loading-status aparte-sr-only" role="status">{loadingText}</span>
241
+ {/if}
222
242
  <!-- Welcome / placeholder shown inside the viewport while empty. -->
223
- {#if internalMessages.length === 0}
243
+ {#if internalMessages.length === 0 && !waiting}
224
244
  <slot name="empty-state" />
225
245
  {/if}
226
246
  <!-- `bubble` slot renders your OWN element per message in place of
@@ -0,0 +1,143 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import { type AparteConfig } from '@aparte/core';
3
+ import type { AparteMessage, AparteSegment, AparteSendEventDetail, AparteActionEventDetail } from './types.js';
4
+ declare const __propDef: {
5
+ props: {
6
+ /**
7
+ * The host element's `id`, and therefore the `targetId` every event this chat
8
+ * dispatches carries. Generated when omitted — but it used to be generated and
9
+ * neither accepted nor exposed, which made `scopeToTargetId` unreachable from
10
+ * this component.
11
+ */ id?: string | undefined;
12
+ messages?: AparteMessage[];
13
+ placeholder?: string;
14
+ disabled?: boolean;
15
+ isTyping?: boolean;
16
+ typingText?: string;
17
+ /** When false, Shift+Enter submits and a bare Enter inserts a newline. */ submitOnEnter?: boolean;
18
+ /** Freeze viewport spacer recalculation for this many ms after a conv swap. */ layoutTransitionMs?: number;
19
+ /**
20
+ * Opt in to the "centered composer when empty" layout: the composer sits
21
+ * vertically centered with the `empty-state` slot above it while the list is
22
+ * empty, then slides to the bottom on the first message (~0.3s). Off by
23
+ * default — additive.
24
+ */ centerWhenEmpty?: boolean;
25
+ /**
26
+ * The conversation is on its way: the viewport draws two skeleton turns, the empty
27
+ * state stays off and the composer is disabled until it lands. The conversation
28
+ * controller sets this itself while it fetches through your adapter's `loadFull()`;
29
+ * the prop is for a wait of your own. Off by default.
30
+ */ loading?: boolean;
31
+ /** Overlay the composer on the transcript: full-column scroll surface, edge-to-edge scrollbar, floating composer. Read when the viewport mounts. */ overlayComposer?: boolean;
32
+ /**
33
+ * Add the file picker + chips strip to the default composer shell. **Off by
34
+ * default**, because the capability needs a host that consumes the files: an
35
+ * `AparteClient` inlines them per its `rawFileInject` option, but if you drive
36
+ * your own loop you must read `event.files` on `messageSent` — otherwise the file
37
+ * the user deliberately attached is dropped in silence. No effect when you fill
38
+ * the `composer` slot (drop `<aparte-composer-add-attachment>` and
39
+ * `<aparte-composer-attachments>` in it yourself).
40
+ */ attachments?: boolean;
41
+ /**
42
+ * Render the `<aparte-elicitation>` presenter inside the host — on by default, as it
43
+ * is in `<aparte-chat>`: the built-in approval gate and `requestUserInput()` ask
44
+ * through it, and it renders nothing until something asks. Pass `false` when you
45
+ * mount a presenter of your own (`setElicitationPresenter`) or place the element
46
+ * yourself.
47
+ */ elicitation?: boolean;
48
+ /** Extra class names for the root element (`[data-aparte-chat]`), merged after core's own. */ class?: string;
49
+ /** Inline style for the root element (`[data-aparte-chat]`). */ style?: string | undefined;
50
+ /** Active conversation id (loads/persists via the registered AparteConversationManager). */ conversationId?: string | null;
51
+ /**
52
+ * Instance {@link AparteConfig} for this chat. When set, aparté components
53
+ * inside resolve THIS config instead of `aparteGlobalConfig`, so
54
+ * several independently-configured chats can coexist on one page. Omit for the
55
+ * global config. Read once when the host mounts.
56
+ */ config?: AparteConfig | undefined;
57
+ /** User submitted a message from the composer — see `messageSent` below for the append rule. */ onmessageSent?: ((detail: AparteSendEventDetail) => void) | undefined;
58
+ /** A custom bubble action (registerBubbleAction) was clicked. */ onaction?: ((detail: AparteActionEventDetail) => void) | undefined;
59
+ /** Active path changed — the list to bind back to `messages`. */ onmessagesChange?: ((messages: AparteMessage[]) => void) | undefined;
60
+ /** One message was appended. */ onmessageAppended?: ((message: AparteMessage) => void) | undefined;
61
+ /** The typing/"thinking" indicator toggled. */ ontypingChange?: ((typing: boolean) => void) | undefined;
62
+ /** The host created a conversation id (persistence). */ onconversationCreated?: ((id: string) => void) | undefined;
63
+ appendMessage?: (m: AparteMessage, options?: {
64
+ historical?: boolean;
65
+ }) => void;
66
+ updateMessage?: (id: string, u: Partial<AparteMessage>) => void;
67
+ updateLastMessage?: (content: string, options?: {
68
+ append?: boolean;
69
+ }) => void;
70
+ addSegment?: (segment: AparteSegment) => void;
71
+ updateSegment?: (segmentId: string, updates: Partial<AparteSegment>) => void;
72
+ removeSegment?: (segmentId: string) => void;
73
+ appendToSegment?: (segmentId: string, content: string) => void;
74
+ getMessages?: () => AparteMessage[];
75
+ clearMessages?: (options?: {
76
+ revokeAttachments?: boolean;
77
+ }) => void;
78
+ addBranch?: (messageId: string) => number;
79
+ addSiblingOf?: (existingId: string, message: AparteMessage) => string | null;
80
+ truncateFrom?: (messageId: string) => void;
81
+ truncateResponsesAfter?: (userMessageId: string) => void;
82
+ injectTokenStream?: (messageId: string, tokens: AsyncIterable<string>) => Promise<void>;
83
+ stopTokenStream?: () => void;
84
+ setConversationId?: (id: string | null) => Promise<void>;
85
+ scrollToBottom?: () => void;
86
+ getViewport?: () => HTMLElement | null;
87
+ focusInput?: () => void;
88
+ isStreaming?: () => boolean;
89
+ };
90
+ events: {
91
+ messageSent: CustomEvent<AparteSendEventDetail>;
92
+ action: CustomEvent<AparteActionEventDetail>;
93
+ messagesChange: CustomEvent<AparteMessage[]>;
94
+ messageAppended: CustomEvent<AparteMessage>;
95
+ typingChange: CustomEvent<boolean>;
96
+ conversationCreated: CustomEvent<string>;
97
+ } & {
98
+ [evt: string]: CustomEvent<any>;
99
+ };
100
+ slots: {
101
+ 'empty-state': {};
102
+ bubble: {
103
+ message: AparteMessage;
104
+ };
105
+ 'above-composer': {};
106
+ composer: {};
107
+ toolbar: {};
108
+ };
109
+ exports?: {} | undefined;
110
+ bindings?: string | undefined;
111
+ };
112
+ export type AparteChatProps = typeof __propDef.props;
113
+ export type AparteChatEvents = typeof __propDef.events;
114
+ export type AparteChatSlots = typeof __propDef.slots;
115
+ export default class AparteChat extends SvelteComponent<AparteChatProps, AparteChatEvents, AparteChatSlots> {
116
+ get appendMessage(): (m: AparteMessage, options?: {
117
+ historical?: boolean;
118
+ }) => void;
119
+ get updateMessage(): (id: string, u: Partial<AparteMessage>) => void;
120
+ get updateLastMessage(): (content: string, options?: {
121
+ append?: boolean;
122
+ }) => void;
123
+ get addSegment(): (segment: AparteSegment) => void;
124
+ get updateSegment(): (segmentId: string, updates: Partial<AparteSegment>) => void;
125
+ get removeSegment(): (segmentId: string) => void;
126
+ get appendToSegment(): (segmentId: string, content: string) => void;
127
+ get getMessages(): () => AparteMessage[];
128
+ get clearMessages(): (options?: {
129
+ revokeAttachments?: boolean;
130
+ }) => void;
131
+ get addBranch(): (messageId: string) => number;
132
+ get addSiblingOf(): (existingId: string, message: AparteMessage) => string | null;
133
+ get truncateFrom(): (messageId: string) => void;
134
+ get truncateResponsesAfter(): (userMessageId: string) => void;
135
+ get injectTokenStream(): (messageId: string, tokens: AsyncIterable<string>) => Promise<void>;
136
+ get stopTokenStream(): () => void;
137
+ get setConversationId(): (id: string | null) => Promise<void>;
138
+ get scrollToBottom(): () => void;
139
+ get getViewport(): () => HTMLElement | null;
140
+ get focusInput(): () => void;
141
+ get isStreaming(): () => boolean;
142
+ }
143
+ export {};
@@ -0,0 +1,35 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ /** The custom element tag name (e.g. 'aparte-model-selector'). */ name: string;
5
+ /** Props to apply. Keys starting with `--` become CSS variables. */ props?: Record<string, unknown>;
6
+ /**
7
+ * Which custom events to forward through `elementEvent`. Defaults to the
8
+ * interactive aparté surface (APARTE_DEFAULT_UI_EVENTS); pass your own list to listen to
9
+ * other events (e.g. ['aparte-composer-change'] for attachments).
10
+ */ events?: string[] | undefined;
11
+ /**
12
+ * Callback prop for the same forwarding as the `elementEvent` component event (#47):
13
+ * called with the element's own CustomEvent, then the event is dispatched. The path
14
+ * Svelte 5 recommends over `createEventDispatcher`; Svelte 4 keeps `on:elementEvent`.
15
+ */ onelementEvent?: ((event: CustomEvent) => void) | undefined;
16
+ getElement?: <T extends HTMLElement = HTMLElement>() => T | null;
17
+ callMethod?: <T = unknown>(methodName: string, ...args: unknown[]) => T | undefined;
18
+ };
19
+ events: {
20
+ elementEvent: CustomEvent<CustomEvent<any>>;
21
+ } & {
22
+ [evt: string]: CustomEvent<any>;
23
+ };
24
+ slots: {};
25
+ exports?: {} | undefined;
26
+ bindings?: string | undefined;
27
+ };
28
+ export type AparteUiProps = typeof __propDef.props;
29
+ export type AparteUiEvents = typeof __propDef.events;
30
+ export type AparteUiSlots = typeof __propDef.slots;
31
+ export default class AparteUi extends SvelteComponent<AparteUiProps, AparteUiEvents, AparteUiSlots> {
32
+ get getElement(): <T extends HTMLElement = HTMLElement>() => T | null;
33
+ get callMethod(): <T = unknown>(methodName: string, ...args: unknown[]) => T | undefined;
34
+ }
35
+ export {};
@@ -19,7 +19,14 @@ export interface AparteChatStore {
19
19
  updateSegment(segmentId: string, updates: Partial<AparteSegment>): void;
20
20
  removeSegment(segmentId: string): void;
21
21
  appendToSegment(segmentId: string, content: string): void;
22
- clearMessages(): void;
22
+ /**
23
+ * The host's list — the authority, and mid-stream a frame ahead of the
24
+ * `messages` store, which is synced once per paint rather than per token.
25
+ */
26
+ getMessages(): AparteMessage[];
27
+ clearMessages(options?: {
28
+ revokeAttachments?: boolean;
29
+ }): void;
23
30
  addBranch(messageId: string): number;
24
31
  addSiblingOf(existingId: string, message: AparteMessage): string | null;
25
32
  truncateFrom(messageId: string): void;
@@ -28,6 +35,10 @@ export interface AparteChatStore {
28
35
  stopTokenStream(): void;
29
36
  setConversationId(id: string | null): Promise<void>;
30
37
  isStreaming(): boolean;
38
+ scrollToBottom(): void;
39
+ focusInput(): void;
40
+ /** The `<aparte-chat-viewport>` element — same accessor on all four wrappers. */
41
+ getViewport(): HTMLElement | null;
31
42
  }
32
43
  /**
33
44
  * Idiomatic Svelte ergonomics for `<AparteChat>`. Owns the `messages` store so the
@@ -1 +1 @@
1
- {"version":3,"file":"aparteChat.d.ts","sourceRoot":"","sources":["../../src/lib/stores/aparteChat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC5B,kFAAkF;IAClF,QAAQ,EAAE,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IACpC,uDAAuD;IACvD,OAAO,CAAC,SAAS,EAAE,uBAAuB,GAAG,IAAI,GAAG,IAAI,CAAC;IACzD,4EAA4E;IAC5E,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAClD,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAChF,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IACxE,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACzE,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IACzC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IACxE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,aAAa,IAAI,IAAI,CAAC;IACtB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IACrC,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAAC;IACxE,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACpD,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnF,eAAe,IAAI,IAAI,CAAC;IACxB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,WAAW,IAAI,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,aAAa,EAAO,GAAG,eAAe,CAwB/E"}
1
+ {"version":3,"file":"aparteChat.d.ts","sourceRoot":"","sources":["../../src/lib/stores/aparteChat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC5B,kFAAkF;IAClF,QAAQ,EAAE,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IACpC,uDAAuD;IACvD,OAAO,CAAC,SAAS,EAAE,uBAAuB,GAAG,IAAI,GAAG,IAAI,CAAC;IACzD,4EAA4E;IAC5E,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAClD,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAChF,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IACxE,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACzE,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IACzC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IACxE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D;;;OAGG;IACH,WAAW,IAAI,aAAa,EAAE,CAAC;IAC/B,aAAa,CAAC,OAAO,CAAC,EAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/D,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IACrC,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAAC;IACxE,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACpD,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnF,eAAe,IAAI,IAAI,CAAC;IACxB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,WAAW,IAAI,OAAO,CAAC;IACvB,cAAc,IAAI,IAAI,CAAC;IACvB,UAAU,IAAI,IAAI,CAAC;IACnB,iFAAiF;IACjF,WAAW,IAAI,WAAW,GAAG,IAAI,CAAC;CACrC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,aAAa,EAAO,GAAG,eAAe,CA4B/E"}
@@ -1,4 +1,4 @@
1
- import { writable } from 'svelte/store';
1
+ import { get, writable } from 'svelte/store';
2
2
  /**
3
3
  * Idiomatic Svelte ergonomics for `<AparteChat>`. Owns the `messages` store so the
4
4
  * consumer skips the manual `on:messagesChange` → `messages` round-trip.
@@ -25,7 +25,8 @@ export function createAparteChat(initial = []) {
25
25
  updateSegment: (id, u) => comp?.updateSegment(id, u),
26
26
  removeSegment: (id) => comp?.removeSegment(id),
27
27
  appendToSegment: (id, c) => comp?.appendToSegment(id, c),
28
- clearMessages: () => comp?.clearMessages(),
28
+ getMessages: () => comp?.getMessages() ?? get(messages),
29
+ clearMessages: (o) => comp?.clearMessages(o),
29
30
  addBranch: (id) => comp?.addBranch(id) ?? 0,
30
31
  addSiblingOf: (id, m) => comp?.addSiblingOf(id, m) ?? null,
31
32
  truncateFrom: (id) => comp?.truncateFrom(id),
@@ -34,5 +35,8 @@ export function createAparteChat(initial = []) {
34
35
  stopTokenStream: () => comp?.stopTokenStream(),
35
36
  setConversationId: (id) => comp?.setConversationId(id) ?? Promise.resolve(),
36
37
  isStreaming: () => comp?.isStreaming() ?? false,
38
+ scrollToBottom: () => comp?.scrollToBottom(),
39
+ focusInput: () => comp?.focusInput(),
40
+ getViewport: () => comp?.getViewport() ?? null,
37
41
  };
38
42
  }
package/dist/types.d.ts CHANGED
@@ -23,11 +23,9 @@ export interface AparteUiProps {
23
23
  onelementEvent?: (event: CustomEvent) => void;
24
24
  }
25
25
  /**
26
- * The imperative surface `<AparteUi>` exposes (`bind:this`) — the same
27
- * `getElement`/`callMethod` contract on all four wrappers.
26
+ * The imperative surface `<AparteUi>` exposes (`bind:this`) — one declaration in
27
+ * `@aparte/core`, re-exported by all four wrappers. It used to be four hand-written
28
+ * copies, each promising "the same contract on all four", and it had already drifted.
28
29
  */
29
- export interface AparteUiHandle {
30
- getElement<T extends HTMLElement = HTMLElement>(): T | null;
31
- callMethod<T = unknown>(methodName: string, ...args: unknown[]): T | undefined;
32
- }
30
+ export type { AparteUiHandle } from '@aparte/core';
33
31
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/lib/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,YAAY,EACR,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,GAC1B,MAAM,cAAc,CAAC;AAEtB,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC1B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CACjD;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC3B,UAAU,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,KAAK,CAAC,GAAG,IAAI,CAAC;IAC5D,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC;CAClF"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/lib/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,YAAY,EACR,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,GAC1B,MAAM,cAAc,CAAC;AAEtB,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC1B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CACjD;AAED;;;;GAIG;AACH,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aparte/svelte",
3
- "version": "0.16.10",
3
+ "version": "0.17.0",
4
4
  "homepage": "https://apartejs.dev/frameworks/svelte/",
5
5
  "description": "Svelte wrapper for aparté — an ergonomic <AparteChat> component plus stores over the framework-agnostic web components. Works on Svelte 4 and 5.",
6
6
  "type": "module",
@@ -32,14 +32,22 @@
32
32
  "svelte-package copies the .svelte components and compiles the .ts to .js; tsc emits index.d.ts.",
33
33
  "Both are needed: a Svelte library must ship its components (the `svelte` condition) AND a real",
34
34
  "JS entry (a bundler that does not add that condition still resolves `default`).",
35
- "KNOWN GAP, pre-existing and not introduced here: no per-component `.svelte.d.ts` is emitted, so a",
36
- "consumer's svelte-check does not see AparteChat's props (it does not analyse .svelte inside",
37
- "node_modules). svelte-package's own type emission produces nothing under pnpm's isolation and fails",
38
- "silently, even with -t and an explicit --tsconfig. Fixing it needs svelte2tsx resolvable from",
39
- "@sveltejs/package itself. Until then the props are documented, not compiler-enforced, for consumers."
35
+ "FIXED: dist/AparteChat.svelte.d.ts and dist/AparteUi.svelte.d.ts are now emitted, so a consumer's",
36
+ "tsc/svelte-check DOES see the components' real prop/event/slot types. The earlier note here was",
37
+ "wrong about the cause: svelte2tsx WAS resolvable from @sveltejs/package (it is a direct, non-peer",
38
+ "dependency of @sveltejs/package itself). The real cause, found by toggling each candidate setting",
39
+ "alone against a real `svelte-package --tsconfig <probe>` invocation: this package's real",
40
+ "tsconfig.json inherits `noEmitOnError: true` from the repo base, which silently blocks",
41
+ "svelte2tsx's `emitDts` step on diagnostics that are EXPECTED noise in its `dts` transform mode",
42
+ "(svelte2tsx's own diagnostic filter already excludes those exact codes as non-fatal). `composite`",
43
+ "is NOT a cause in either direction (verified the same way) and is left untouched.",
44
+ "`tsconfig.dts.json` relaxes `noEmitOnError` (plus `declarationMap`, for an unrelated broken-path",
45
+ "reason documented there) and is passed via `--tsconfig` in the build script below; the real",
46
+ "`tsc -b` pass is untouched by it. Verified against a consumer `tsc --noEmit` importing the built",
47
+ "package: a wrong AparteChat prop now errors."
40
48
  ],
41
49
  "peerDependencies": {
42
- "@aparte/core": ">=0.16.10 <1.0.0",
50
+ "@aparte/core": ">=0.17.0 <1.0.0",
43
51
  "svelte": "^4.0.0 || ^5.0.0"
44
52
  },
45
53
  "devDependencies": {
@@ -52,7 +60,7 @@
52
60
  "svelte2tsx": "^0.7.61",
53
61
  "typescript": "^5.4.0",
54
62
  "vite": "^6.0.0",
55
- "@aparte/core": "0.16.10"
63
+ "@aparte/core": "0.17.0"
56
64
  },
57
65
  "keywords": [
58
66
  "svelte",
@@ -76,7 +84,7 @@
76
84
  "scripts": {
77
85
  "typecheck:tests": "svelte-check --tsconfig ./tsconfig.check.json --threshold error --output human",
78
86
  "dev": "vite",
79
- "build": "svelte-package -i src/lib -o dist && tsc -b --emitDeclarationOnly --force && node scripts/strip-dist-tests.mjs",
87
+ "build": "svelte-package -i src/lib -o dist --tsconfig ./tsconfig.dts.json && tsc -b --emitDeclarationOnly --force && node scripts/strip-dist-tests.mjs",
80
88
  "preview": "vite preview",
81
89
  "test": "vitest",
82
90
  "test:run": "vitest run",