@aparte/core 0.2.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.
Files changed (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -0
  3. package/dist/client/aparte-client.d.ts +326 -0
  4. package/dist/client/aparte-client.d.ts.map +1 -0
  5. package/dist/client/stream-adapter.d.ts +197 -0
  6. package/dist/client/stream-adapter.d.ts.map +1 -0
  7. package/dist/components/bubble/aparte-chat-bubble.d.ts +153 -0
  8. package/dist/components/bubble/aparte-chat-bubble.d.ts.map +1 -0
  9. package/dist/components/bubble/bubble-sync.d.ts +44 -0
  10. package/dist/components/bubble/bubble-sync.d.ts.map +1 -0
  11. package/dist/components/bubble/index.d.ts +4 -0
  12. package/dist/components/bubble/index.d.ts.map +1 -0
  13. package/dist/components/chat/aparte-chat.d.ts +49 -0
  14. package/dist/components/chat/aparte-chat.d.ts.map +1 -0
  15. package/dist/components/chat/index.d.ts +2 -0
  16. package/dist/components/chat/index.d.ts.map +1 -0
  17. package/dist/components/composer/aparte-composer-action.d.ts +37 -0
  18. package/dist/components/composer/aparte-composer-action.d.ts.map +1 -0
  19. package/dist/components/composer/aparte-composer-add-attachment.d.ts +27 -0
  20. package/dist/components/composer/aparte-composer-add-attachment.d.ts.map +1 -0
  21. package/dist/components/composer/aparte-composer-attachments.d.ts +26 -0
  22. package/dist/components/composer/aparte-composer-attachments.d.ts.map +1 -0
  23. package/dist/components/composer/aparte-composer-cancel.d.ts +21 -0
  24. package/dist/components/composer/aparte-composer-cancel.d.ts.map +1 -0
  25. package/dist/components/composer/aparte-composer-input.d.ts +63 -0
  26. package/dist/components/composer/aparte-composer-input.d.ts.map +1 -0
  27. package/dist/components/composer/aparte-composer-send.d.ts +25 -0
  28. package/dist/components/composer/aparte-composer-send.d.ts.map +1 -0
  29. package/dist/components/composer/aparte-composer.d.ts +150 -0
  30. package/dist/components/composer/aparte-composer.d.ts.map +1 -0
  31. package/dist/components/composer/index.d.ts +9 -0
  32. package/dist/components/composer/index.d.ts.map +1 -0
  33. package/dist/components/conversation-list/aparte-conversation-list.d.ts +50 -0
  34. package/dist/components/conversation-list/aparte-conversation-list.d.ts.map +1 -0
  35. package/dist/components/conversation-list/index.d.ts +2 -0
  36. package/dist/components/conversation-list/index.d.ts.map +1 -0
  37. package/dist/components/elicitation/aparte-elicitation.d.ts +29 -0
  38. package/dist/components/elicitation/aparte-elicitation.d.ts.map +1 -0
  39. package/dist/components/index.d.ts +10 -0
  40. package/dist/components/index.d.ts.map +1 -0
  41. package/dist/components/status/aparte-chat-status.d.ts +34 -0
  42. package/dist/components/status/aparte-chat-status.d.ts.map +1 -0
  43. package/dist/components/status/index.d.ts +2 -0
  44. package/dist/components/status/index.d.ts.map +1 -0
  45. package/dist/components/viewport/aparte-chat-viewport.d.ts +358 -0
  46. package/dist/components/viewport/aparte-chat-viewport.d.ts.map +1 -0
  47. package/dist/components/viewport/index.d.ts +2 -0
  48. package/dist/components/viewport/index.d.ts.map +1 -0
  49. package/dist/config/action-provider.d.ts +59 -0
  50. package/dist/config/action-provider.d.ts.map +1 -0
  51. package/dist/config/aparte-config.d.ts +490 -0
  52. package/dist/config/aparte-config.d.ts.map +1 -0
  53. package/dist/config/attachment-renderer.d.ts +28 -0
  54. package/dist/config/attachment-renderer.d.ts.map +1 -0
  55. package/dist/config/avatar-provider.d.ts +35 -0
  56. package/dist/config/avatar-provider.d.ts.map +1 -0
  57. package/dist/config/bubble-shell-renderer.d.ts +41 -0
  58. package/dist/config/bubble-shell-renderer.d.ts.map +1 -0
  59. package/dist/config/config-context.d.ts +47 -0
  60. package/dist/config/config-context.d.ts.map +1 -0
  61. package/dist/config/error-renderer.d.ts +26 -0
  62. package/dist/config/error-renderer.d.ts.map +1 -0
  63. package/dist/config/icon-provider.d.ts +63 -0
  64. package/dist/config/icon-provider.d.ts.map +1 -0
  65. package/dist/config/index.d.ts +19 -0
  66. package/dist/config/index.d.ts.map +1 -0
  67. package/dist/config/locale.d.ts +60 -0
  68. package/dist/config/locale.d.ts.map +1 -0
  69. package/dist/config/sanitize.d.ts +31 -0
  70. package/dist/config/sanitize.d.ts.map +1 -0
  71. package/dist/config/sibling-nav-renderer.d.ts +27 -0
  72. package/dist/config/sibling-nav-renderer.d.ts.map +1 -0
  73. package/dist/config/skeleton-provider.d.ts +26 -0
  74. package/dist/config/skeleton-provider.d.ts.map +1 -0
  75. package/dist/config/status-renderer.d.ts +23 -0
  76. package/dist/config/status-renderer.d.ts.map +1 -0
  77. package/dist/conversations/conversation-controller.d.ts +126 -0
  78. package/dist/conversations/conversation-controller.d.ts.map +1 -0
  79. package/dist/conversations/conversation-manager.d.ts +98 -0
  80. package/dist/conversations/conversation-manager.d.ts.map +1 -0
  81. package/dist/conversations/index.d.ts +5 -0
  82. package/dist/conversations/index.d.ts.map +1 -0
  83. package/dist/conversations/types.d.ts +172 -0
  84. package/dist/conversations/types.d.ts.map +1 -0
  85. package/dist/custom-elements.json +15833 -0
  86. package/dist/elicitation/index.d.ts +20 -0
  87. package/dist/elicitation/index.d.ts.map +1 -0
  88. package/dist/elicitation/panel.d.ts +18 -0
  89. package/dist/elicitation/panel.d.ts.map +1 -0
  90. package/dist/elicitation/types.d.ts +98 -0
  91. package/dist/elicitation/types.d.ts.map +1 -0
  92. package/dist/host/aparte-chat-host.d.ts +176 -0
  93. package/dist/host/aparte-chat-host.d.ts.map +1 -0
  94. package/dist/host/index.d.ts +2 -0
  95. package/dist/host/index.d.ts.map +1 -0
  96. package/dist/index-D89k-n2Q.js +6294 -0
  97. package/dist/index-D89k-n2Q.js.map +1 -0
  98. package/dist/index.css +2554 -0
  99. package/dist/index.d.ts +62 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +3763 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/index.node.d.ts +53 -0
  104. package/dist/index.node.d.ts.map +1 -0
  105. package/dist/index.node.js +49 -0
  106. package/dist/index.node.js.map +1 -0
  107. package/dist/interop/element-props.d.ts +23 -0
  108. package/dist/interop/element-props.d.ts.map +1 -0
  109. package/dist/parsers/aparte-event-stream.d.ts +13 -0
  110. package/dist/parsers/aparte-event-stream.d.ts.map +1 -0
  111. package/dist/parsers/aparte-stream-parser.d.ts +137 -0
  112. package/dist/parsers/aparte-stream-parser.d.ts.map +1 -0
  113. package/dist/parsers/index.d.ts +4 -0
  114. package/dist/parsers/index.d.ts.map +1 -0
  115. package/dist/primitives/index.d.ts +8 -0
  116. package/dist/primitives/index.d.ts.map +1 -0
  117. package/dist/primitives/progress-spinner/aparte-progress-spinner.d.ts +25 -0
  118. package/dist/primitives/progress-spinner/aparte-progress-spinner.d.ts.map +1 -0
  119. package/dist/primitives/progress-spinner/index.d.ts +2 -0
  120. package/dist/primitives/progress-spinner/index.d.ts.map +1 -0
  121. package/dist/primitives/select/aparte-optgroup.d.ts +32 -0
  122. package/dist/primitives/select/aparte-optgroup.d.ts.map +1 -0
  123. package/dist/primitives/select/aparte-option.d.ts +30 -0
  124. package/dist/primitives/select/aparte-option.d.ts.map +1 -0
  125. package/dist/primitives/select/aparte-select.d.ts +74 -0
  126. package/dist/primitives/select/aparte-select.d.ts.map +1 -0
  127. package/dist/primitives/select/index.d.ts +9 -0
  128. package/dist/primitives/select/index.d.ts.map +1 -0
  129. package/dist/renderers/index.d.ts +5 -0
  130. package/dist/renderers/index.d.ts.map +1 -0
  131. package/dist/renderers/segment-renderers.d.ts +31 -0
  132. package/dist/renderers/segment-renderers.d.ts.map +1 -0
  133. package/dist/runtime/message-repository.d.ts +111 -0
  134. package/dist/runtime/message-repository.d.ts.map +1 -0
  135. package/dist/transport/backend-handler.d.ts +50 -0
  136. package/dist/transport/backend-handler.d.ts.map +1 -0
  137. package/dist/transport/backend-transport.d.ts +39 -0
  138. package/dist/transport/backend-transport.d.ts.map +1 -0
  139. package/dist/transport/direct-transport.d.ts +36 -0
  140. package/dist/transport/direct-transport.d.ts.map +1 -0
  141. package/dist/transport/index.d.ts +6 -0
  142. package/dist/transport/index.d.ts.map +1 -0
  143. package/dist/transport/types.d.ts +73 -0
  144. package/dist/transport/types.d.ts.map +1 -0
  145. package/dist/types/chat.d.ts +223 -0
  146. package/dist/types/chat.d.ts.map +1 -0
  147. package/dist/types/errors.d.ts +25 -0
  148. package/dist/types/errors.d.ts.map +1 -0
  149. package/dist/types/event-map.d.ts +41 -0
  150. package/dist/types/event-map.d.ts.map +1 -0
  151. package/dist/types/events.d.ts +290 -0
  152. package/dist/types/events.d.ts.map +1 -0
  153. package/dist/types/imperative-api.d.ts +38 -0
  154. package/dist/types/imperative-api.d.ts.map +1 -0
  155. package/dist/types/index.d.ts +22 -0
  156. package/dist/types/index.d.ts.map +1 -0
  157. package/dist/types/model-provider.d.ts +229 -0
  158. package/dist/types/model-provider.d.ts.map +1 -0
  159. package/dist/types/models.d.ts +173 -0
  160. package/dist/types/models.d.ts.map +1 -0
  161. package/dist/types/parsers.d.ts +42 -0
  162. package/dist/types/parsers.d.ts.map +1 -0
  163. package/dist/types/providers.d.ts +93 -0
  164. package/dist/types/providers.d.ts.map +1 -0
  165. package/dist/types/segments.d.ts +221 -0
  166. package/dist/types/segments.d.ts.map +1 -0
  167. package/dist/types/theming.d.ts +44 -0
  168. package/dist/types/theming.d.ts.map +1 -0
  169. package/dist/types/tools.d.ts +98 -0
  170. package/dist/types/tools.d.ts.map +1 -0
  171. package/dist/utils/assert-never.d.ts +9 -0
  172. package/dist/utils/assert-never.d.ts.map +1 -0
  173. package/dist/utils/css-escape.d.ts +15 -0
  174. package/dist/utils/css-escape.d.ts.map +1 -0
  175. package/package.json +68 -0
@@ -0,0 +1,358 @@
1
+ import type { AparteMessage, AparteViewportConfig, AparteSegment, AparteUsage } from '../../types/index.js';
2
+ import type { ExportedMessageRepository } from '../../runtime/message-repository.js';
3
+ /**
4
+ * AparteChatViewport - The Core
5
+ *
6
+ * Container component with smart scroll, streaming, and segment support.
7
+ * Uses Light DOM for global CSS styling.
8
+ *
9
+ * @element aparte-chat-viewport
10
+ *
11
+ * Features:
12
+ * - Smart Scroll: Sticks to bottom when user is at bottom, stops on manual scroll up
13
+ * - appendToken(): For simple content streaming
14
+ * - appendToSegment(): For segment-aware streaming (thinking, code, etc.)
15
+ * - Internal message registry for memory management
16
+ */
17
+ export declare class AparteChatViewport extends HTMLElement {
18
+ private _container;
19
+ private _scrollBtn;
20
+ private _bottomSpacer;
21
+ /**
22
+ * In framework-managed mode there is no spacer ELEMENT (an extra child would
23
+ * collide with the framework's own DOM reconciliation). The spacer is an
24
+ * additive `padding-bottom` on the host, tracked here so `_recalculateSpacer`
25
+ * can read the current value without measuring an element.
26
+ */
27
+ private _fwSpacerHeight;
28
+ private _spacerRafId;
29
+ private _spacerFrozenUntil;
30
+ private _layoutTransitionMs;
31
+ private _repo;
32
+ private _isAutoScrollEnabled;
33
+ private _scrollThreshold;
34
+ /** When true, the next _autoScroll() call uses smooth instead of instant, then resets. */
35
+ private _smoothScrollOnce;
36
+ /**
37
+ * DOM render cap: the max number of `<aparte-chat-bubble>` elements kept in the
38
+ * DOM at once (a perf ceiling for very long conversations). This NEVER evicts
39
+ * messages from the repository — the full conversation tree and its persistence
40
+ * snapshot stay intact; only the oldest rendered bubbles are dropped from view.
41
+ */
42
+ private _maxRenderedBubbles;
43
+ /** One-time guard for the deprecated `maxMessages` warning. */
44
+ private _warnedMaxMessagesDeprecation;
45
+ private _resizeObserver;
46
+ private _mutationObserver;
47
+ private _boundResetHandler;
48
+ /**
49
+ * When true, _reRenderActivePath() only dispatches aparte-path-changed without
50
+ * touching the DOM. Set via setFrameworkManagedDOM(true) when a framework
51
+ * (e.g. Angular) owns the bubble elements.
52
+ */
53
+ private _frameworkManagedDOM;
54
+ static get observedAttributes(): string[];
55
+ constructor();
56
+ connectedCallback(): void;
57
+ disconnectedCallback(): void;
58
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
59
+ /**
60
+ * Configure viewport with options
61
+ */
62
+ configure(config: AparteViewportConfig): void;
63
+ /**
64
+ * Append a token chunk to a message's content (simple text streaming)
65
+ * @param messageId - Unique identifier for the message
66
+ * @param chunk - Token chunk to append
67
+ */
68
+ appendToken(messageId: string, chunk: string): void;
69
+ /**
70
+ * Append content to a specific segment within a message
71
+ * @param messageId - Message containing the segment
72
+ * @param segmentId - Target segment ID
73
+ * @param chunk - Content to append
74
+ */
75
+ appendToSegment(messageId: string, segmentId: string, chunk: string): void;
76
+ /**
77
+ * The active (head) message id — the target of `AparteClient`'s 1-argument
78
+ * streaming convention (`addSegment(segment)`, `updateSegment(segmentId,
79
+ * updates)`, …) which operates on "the current message". Lets a bare
80
+ * `<aparte-chat-viewport>` be a valid `AparteClient` target, exactly like a
81
+ * framework wrapper's host element.
82
+ */
83
+ private _activeMessageId;
84
+ /**
85
+ * Add a new segment. Two calling conventions are accepted:
86
+ * - `addSegment(segment)` — AparteClient's 1-arg "operate on the current
87
+ * (head) message" convention (also what a wrapper host installs);
88
+ * - `addSegment(messageId, segment)` — explicit standalone form.
89
+ * The first argument's type disambiguates (string = messageId, object =
90
+ * segment), so a raw viewport driven by `AparteClient` no longer drops text
91
+ * (the args used to bind one position short, creating a phantom message).
92
+ */
93
+ addSegment(segment: AparteSegment): void;
94
+ addSegment(messageId: string, segment: AparteSegment): void;
95
+ /**
96
+ * Update a segment. `updateSegment(segmentId, updates)` (1-arg client
97
+ * convention → current message) or `updateSegment(messageId, segmentId,
98
+ * updates)` (explicit). Disambiguated by arity: the 3rd arg is absent and
99
+ * the 2nd is the `updates` object in the 1-arg form.
100
+ */
101
+ updateSegment(segmentId: string, updates: Partial<AparteSegment>): void;
102
+ updateSegment(messageId: string, segmentId: string, updates: Partial<AparteSegment>): void;
103
+ /**
104
+ * Remove a segment. `removeSegment(segmentId)` (1-arg client convention →
105
+ * current message) or `removeSegment(messageId, segmentId)` (explicit).
106
+ */
107
+ removeSegment(segmentId: string): void;
108
+ removeSegment(messageId: string, segmentId: string): void;
109
+ /**
110
+ * Start a new streaming segment (e.g., thinking or code block)
111
+ * Creates the segment and marks it as streaming
112
+ */
113
+ startSegment(messageId: string, segment: AparteSegment): void;
114
+ /**
115
+ * Complete a streaming segment
116
+ */
117
+ completeSegment(messageId: string, segmentId: string): void;
118
+ /**
119
+ * Persist token usage on a message and propagate to the live bubble so the
120
+ * perf chip (tokens/sec) renders in the action bar.
121
+ */
122
+ setUsage(messageId: string, usage: AparteUsage): void;
123
+ /**
124
+ * Mark a message as finished streaming
125
+ */
126
+ completeMessage(messageId: string): void;
127
+ /**
128
+ * Atomic update for a message by ID
129
+ * Supports updating content, status, segments, and other metadata
130
+ */
131
+ updateMessage(messageId: string, updates: Partial<AparteMessage>): void;
132
+ /**
133
+ * Add a complete message to the message registry.
134
+ *
135
+ * @remarks
136
+ * **Framework-managed DOM only.** Records the message in the tree but does NOT
137
+ * paint a bubble on its own (a framework wrapper reconciles the DOM from the
138
+ * list). For standalone / vanilla usage call {@link appendMessage} instead,
139
+ * which both records the message and creates its bubble element.
140
+ */
141
+ addMessage(message: AparteMessage): void;
142
+ /**
143
+ * Append a new message and create its bubble in the DOM.
144
+ * Implements the same contract as the Angular wrapper's appendMessage(),
145
+ * making aparte-chat-viewport a fully standalone target for aparte-client.
146
+ * When `_frameworkManagedDOM` is true, only the internal repo is updated —
147
+ * the framework owns the DOM and will create the bubble element itself.
148
+ */
149
+ appendMessage(message: AparteMessage): void;
150
+ /**
151
+ * Update the last message content, optionally appending.
152
+ * Implements the same contract as the Angular wrapper's updateLastMessage(),'
153
+ * making aparte-chat-viewport a fully standalone streaming target for aparte-client.
154
+ */
155
+ updateLastMessage(content: string, options?: {
156
+ append?: boolean;
157
+ }): void;
158
+ /**
159
+ * Add a new sibling branch to an assistant message (retry flow).
160
+ * Creates a new empty assistant message as a sibling of `messageId`
161
+ * under the same parent, switches the active branch to it, and
162
+ * re-renders the active path.
163
+ * @returns The index of the new branch in the siblings array, or 0 on failure.
164
+ */
165
+ addBranch(messageId: string): number;
166
+ /**
167
+ * Add a new message relative to `existingId`, switch to it, and re-render.
168
+ *
169
+ * Role-aware semantics:
170
+ * - existingId is an **assistant** message → create a sibling (same parent),
171
+ * so the active path replaces the old response with the new one.
172
+ * - existingId is a **user** message → create a child of that message,
173
+ * so the user message stays on the active path and the new response follows it.
174
+ *
175
+ * Returns the new message's ID, or null if `existingId` is not found.
176
+ */
177
+ addSiblingOf(existingId: string, newMessage: AparteMessage): string | null;
178
+ /**
179
+ * Navigate to the previous or next sibling branch of a message.
180
+ * Triggers a full re-render of the active path.
181
+ */
182
+ navigateBranch(messageId: string, direction: 'prev' | 'next'): void;
183
+ /**
184
+ * Remove ALL responses to a user message (every child branch) and set head
185
+ * back to `userMessageId`. Cleaner than `truncateFrom` for edit flows: it
186
+ * discards stale sibling branches so the regenerated response starts alone.
187
+ */
188
+ truncateResponsesAfter(userMessageId: string): void;
189
+ /**
190
+ * Remove all messages from `messageId` onwards (inclusive) from state and DOM.
191
+ * Used by edit to truncate history before re-generating.
192
+ */
193
+ truncateFrom(messageId: string): void;
194
+ /**
195
+ * Get a message by ID
196
+ */
197
+ getMessage(messageId: string): AparteMessage | undefined;
198
+ getMessages(): AparteMessage[];
199
+ /**
200
+ * Export the full conversation tree (all branches, not just the active path).
201
+ * The returned snapshot can be persisted and restored via `importTree()`.
202
+ */
203
+ exportTree(): ExportedMessageRepository;
204
+ /**
205
+ * Import a previously-exported tree snapshot, restoring the full branch
206
+ * topology and the active head. Replaces any existing repo content.
207
+ *
208
+ * Always calls `_reRenderActivePath()`:
209
+ * - In native DOM mode: rebuilds bubble elements.
210
+ * - In framework-managed mode: skips DOM manipulation but dispatches
211
+ * `aparte-path-changed` with sibling metadata so the wrapper can update
212
+ * branch arrows on already-rendered bubbles.
213
+ */
214
+ importTree(tree: ExportedMessageRepository): void;
215
+ /**
216
+ * Clear all messages and remove all bubble elements from the DOM.
217
+ * Also dispatches a aparte-reset-done event.
218
+ *
219
+ * In framework-managed mode the DOM is owned by the host framework
220
+ * (Angular @for, React, etc.) and we must not clear `innerHTML` — doing
221
+ * so desynchronises the framework's view tree from the live DOM and the
222
+ * next change-detection pass throws `NotFoundError` on insertBefore.
223
+ */
224
+ clearAll(): void;
225
+ /**
226
+ * Clear all messages
227
+ * @deprecated Use clearAll() to also remove DOM bubbles
228
+ */
229
+ clearMessages(): void;
230
+ /**
231
+ * Replace the entire message list in one shot. Used when switching
232
+ * conversations: clears existing repo + DOM, then appends each message.
233
+ *
234
+ * In framework-managed mode the framework re-renders the bubble DOM
235
+ * itself; we only update the internal repo (used by aparte-client to
236
+ * build chat history).
237
+ */
238
+ setMessages(messages: AparteMessage[]): void;
239
+ /**
240
+ * Scroll to bottom of viewport
241
+ */
242
+ scrollToBottom(): void;
243
+ /**
244
+ * Reset the bottom spacer to 0 height immediately and freeze it for
245
+ * 350 ms so the host-app layout transition (e.g. flex: 0→1 animation)
246
+ * does not trigger a premature recalculation with mid-animation geometry.
247
+ * Call before a full messages swap.
248
+ */
249
+ resetSpacer(): void;
250
+ /**
251
+ * Enable or disable auto-scroll
252
+ */
253
+ setAutoScroll(enabled: boolean): void;
254
+ /**
255
+ * Signal that a framework (e.g. Angular) manages the bubble DOM.
256
+ * When true, branch navigation dispatches `aparte-path-changed` without
257
+ * clearing/rebuilding the messages wrapper — the framework re-renders instead.
258
+ */
259
+ setFrameworkManagedDOM(managed: boolean): void;
260
+ private _getOrCreateMessage;
261
+ private _notifyBubble;
262
+ /**
263
+ * Re-render the active path: clears the messages wrapper and rebuilds bubbles
264
+ * for every message on the current active branch path (root → head).
265
+ * Calls `setSiblings(count, index)` on each bubble that has siblings, and
266
+ * dispatches `aparte-path-changed` so Angular wrapper can sync its signal.
267
+ *
268
+ * When `_frameworkManagedDOM` is true (set via setFrameworkManagedDOM), the DOM
269
+ * manipulation is skipped — only `aparte-path-changed` is dispatched so the
270
+ * framework can re-render from updated signal state.
271
+ */
272
+ private _reRenderActivePath;
273
+ private _dispatchPathChanged;
274
+ private _autoScroll;
275
+ /**
276
+ * Request that the next auto-scroll triggered by a DOM mutation uses
277
+ * smooth behaviour instead of instant. Call this just before adding a
278
+ * user message bubble so the viewport animates down rather than jumping.
279
+ * Resets automatically after the first auto-scroll fires.
280
+ */
281
+ requestSmoothScroll(): void;
282
+ private _render;
283
+ /**
284
+ * DOM setup for framework-managed mode. The framework (React/Vue/Svelte/
285
+ * Angular) renders the bubble elements as DIRECT children of the host, so we
286
+ * must NOT relocate them into an internal wrapper — that desyncs the
287
+ * framework's virtual DOM from the real DOM and throws NotFoundError on the
288
+ * next append. Instead the HOST itself is the scroll surface, the spacer is
289
+ * additive `padding-bottom` (no element), and the scroll button is a
290
+ * `position: sticky` TRAILING foreign child (kept last by the framework
291
+ * MutationObserver). A present foreign node is still a valid `insertBefore`
292
+ * reference for the framework — the crash came from a RELOCATED node, not a
293
+ * foreign one.
294
+ */
295
+ private _setupFrameworkDOM;
296
+ /**
297
+ * Keep the sticky scroll button as the last child in framework-managed mode.
298
+ * The framework usually inserts bubbles before its own trailing nodes (so the
299
+ * button stays last), but a plain `appendChild` at the very end (e.g. some
300
+ * Angular @for paths) can land a bubble after it — move it back. Idempotent:
301
+ * a no-op when already last, so it never loops the MutationObserver.
302
+ */
303
+ private _keepScrollButtonLast;
304
+ /** Current spacer height — a padding value (framework) or the element's height (core). */
305
+ private _getSpacerHeight;
306
+ /** Set the spacer — host padding (framework, additive to base padding) or element height (core). */
307
+ private _setSpacerHeight;
308
+ private _setupEventListeners;
309
+ private _setupObservers;
310
+ private _handleScroll;
311
+ private _scrollToBottom;
312
+ private _smoothScrollToBottom;
313
+ private _prefersReducedMotion;
314
+ /**
315
+ * Show/hide the scroll-to-bottom button based on the current auto-scroll state.
316
+ * Hidden when already at bottom (_isAutoScrollEnabled = true).
317
+ */
318
+ private _updateScrollButton;
319
+ /**
320
+ * Recalculate the bottom spacer height so the last user message is always
321
+ * pinned to the top of the scroll area when a response is being generated.
322
+ *
323
+ * spacer = max(0, viewportHeight - lastUserBubble.offsetHeight - lastAssistantBubble.offsetHeight)
324
+ *
325
+ * The spacer shrinks progressively as the assistant streams content, eventually
326
+ * reaching 0 when the combined height fills the viewport.
327
+ */
328
+ private _recalculateSpacer;
329
+ /**
330
+ * Schedule a spacer recalculation on the next animation frame.
331
+ * Batches multiple rapid calls (e.g. during token streaming) into one.
332
+ *
333
+ * Single-RAF intentional: both the scroll-to-bottom queued by MutationObserver
334
+ * and this spacer recalculation must land in the *same* frame so the browser
335
+ * paints exactly once — with the correct scroll position *and* the correct
336
+ * spacer height. A double-RAF would put the spacer shrink one frame after the
337
+ * scroll, causing a 1-frame layout jump during streaming.
338
+ */
339
+ private _scheduleSpacerUpdate;
340
+ /**
341
+ * Cap the number of rendered bubbles in the DOM (perf ceiling only).
342
+ *
343
+ * Drops the oldest `<aparte-chat-bubble>` elements beyond `_maxRenderedBubbles`
344
+ * from the DOM. It **never** touches the MessageRepository — the conversation
345
+ * model and its persistence snapshot stay complete (retention/eviction is a
346
+ * consumer/persistence concern, not the viewport's). No-op when a framework
347
+ * owns the DOM.
348
+ */
349
+ private _pruneRenderedBubbles;
350
+ private _warnMaxMessagesDeprecated;
351
+ private _cleanup;
352
+ }
353
+ declare global {
354
+ interface HTMLElementTagNameMap {
355
+ 'aparte-chat-viewport': AparteChatViewport;
356
+ }
357
+ }
358
+ //# sourceMappingURL=aparte-chat-viewport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aparte-chat-viewport.d.ts","sourceRoot":"","sources":["../../../src/components/viewport/aparte-chat-viewport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { AparteChatViewport } from './aparte-chat-viewport.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/viewport/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,59 @@
1
+ /** Zones where a custom action can appear. */
2
+ export type AparteActionZone = 'composer' | 'bubble';
3
+ /**
4
+ * A custom action button, registered once via `AparteConfig.registerAction(...)`
5
+ * and placed in one or more zones — the composer toolbar and/or the message
6
+ * (bubble) toolbar — via `zones`.
7
+ *
8
+ * Declarative and framework-agnostic: clicking it emits an `aparte-action`
9
+ * CustomEvent (bubbles, composed) carrying `{ actionId, zone, … }`, exactly like
10
+ * the built-in retry/feedback buttons — so you wire it the same way in
11
+ * React/Vue/Svelte/Angular and in vanilla. An optional `onClick` callback fires
12
+ * alongside the event for imperative convenience.
13
+ *
14
+ * @example
15
+ * AparteConfig.registerAction({
16
+ * id: 'share', icon: '<svg>…</svg>', label: 'Share',
17
+ * zones: ['bubble'], bubble: { roles: ['assistant'] },
18
+ * });
19
+ * chatEl.addEventListener('aparte-action', (e) => {
20
+ * if (e.detail.actionId === 'share') share(e.detail.messageId);
21
+ * });
22
+ */
23
+ export interface AparteAction {
24
+ /** Stable id — echoed as `actionId` in the `aparte-action` event. */
25
+ id: string;
26
+ /**
27
+ * Icon for the button:
28
+ * - If it starts with `<`, it is treated as raw HTML/SVG and used directly.
29
+ * - Otherwise it is treated as a key for `AparteConfig.getIcon()`. If the
30
+ * provider doesn't have the key, falls back to `iconFallback` or `id`.
31
+ */
32
+ icon: string;
33
+ /** Inline SVG/HTML fallback used when the icon provider doesn't have the key. */
34
+ iconFallback?: string;
35
+ /** Accessible label (sets `aria-label` + `title`) — a locale key or a raw string. */
36
+ label: string;
37
+ /** Lower renders first among custom actions (they follow the built-ins). */
38
+ order?: number;
39
+ /** Which zones this action appears in. */
40
+ zones: AparteActionZone[];
41
+ /** Composer-toolbar placement (used when `zones` includes `'composer'`). */
42
+ composer?: {
43
+ /** Toolbar side. Default: `'left'`. */
44
+ position?: 'left' | 'right';
45
+ /**
46
+ * When `true`, the button is hidden from the composer toolbar.
47
+ * Toggle at runtime with `AparteConfig.setActionHidden(id, hidden)`.
48
+ */
49
+ hidden?: boolean;
50
+ };
51
+ /** Bubble-toolbar placement (used when `zones` includes `'bubble'`). */
52
+ bubble?: {
53
+ /** Bubble roles this action shows on. Default: both user and assistant. */
54
+ roles?: ('user' | 'assistant')[];
55
+ };
56
+ /** Optional imperative callback, fired alongside the `aparte-action` event. */
57
+ onClick?: (event: Event, context?: unknown) => void;
58
+ }
59
+ //# sourceMappingURL=action-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-provider.d.ts","sourceRoot":"","sources":["../../src/config/action-provider.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,QAAQ,CAAC;AAErD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,YAAY;IACzB,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAC;IACX;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,4EAA4E;IAC5E,QAAQ,CAAC,EAAE;QACP,uCAAuC;QACvC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAC5B;;;WAGG;QACH,MAAM,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC;IACF,wEAAwE;IACxE,MAAM,CAAC,EAAE;QACL,2EAA2E;QAC3E,KAAK,CAAC,EAAE,CAAC,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC;KACpC,CAAC;IACF,+EAA+E;IAC/E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACvD"}