@aparte/core 0.9.0 → 0.10.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.
- package/dist/components/bubble/aparte-chat-bubble.d.ts +24 -3
- package/dist/components/bubble/aparte-chat-bubble.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-action.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-add-attachment.d.ts +11 -0
- package/dist/components/composer/aparte-composer-add-attachment.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-cancel.d.ts +8 -0
- package/dist/components/composer/aparte-composer-cancel.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-input.d.ts.map +1 -1
- package/dist/components/composer/aparte-composer-send.d.ts +32 -0
- package/dist/components/composer/aparte-composer-send.d.ts.map +1 -1
- package/dist/components/elicitation/aparte-elicitation.d.ts +10 -0
- package/dist/components/elicitation/aparte-elicitation.d.ts.map +1 -1
- package/dist/components/viewport/aparte-chat-viewport.d.ts +3 -1
- package/dist/components/viewport/aparte-chat-viewport.d.ts.map +1 -1
- package/dist/config/aparte-config.d.ts +34 -1
- package/dist/config/aparte-config.d.ts.map +1 -1
- package/dist/config/config-subscribe.d.ts +4 -0
- package/dist/config/config-subscribe.d.ts.map +1 -0
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/locale.d.ts +98 -0
- package/dist/config/locale.d.ts.map +1 -1
- package/dist/config/sanitize.d.ts.map +1 -1
- package/dist/custom-elements.json +4588 -4293
- package/dist/elicitation/panel.d.ts +13 -0
- package/dist/elicitation/panel.d.ts.map +1 -1
- package/dist/host/aparte-chat-host.d.ts +3 -1
- package/dist/host/aparte-chat-host.d.ts.map +1 -1
- package/dist/{index-hQQljwfX.js → index-BnKBciDG.js} +515 -232
- package/dist/index-BnKBciDG.js.map +1 -0
- package/dist/index.css +147 -310
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +248 -87
- package/dist/index.js.map +1 -1
- package/dist/index.node.d.ts +3 -2
- package/dist/index.node.d.ts.map +1 -1
- package/dist/index.node.js +60 -57
- package/dist/index.node.js.map +1 -1
- package/dist/parsers/aparte-stream-parser.d.ts.map +1 -1
- package/dist/renderers/highlight-stream.d.ts +17 -0
- package/dist/renderers/highlight-stream.d.ts.map +1 -0
- package/dist/renderers/segment-renderers.d.ts.map +1 -1
- package/dist/renderers/segments/artifact/binary-file.d.ts.map +1 -1
- package/dist/renderers/segments/artifact/card.d.ts.map +1 -1
- package/dist/renderers/segments/artifact/shared.d.ts +19 -2
- package/dist/renderers/segments/artifact/shared.d.ts.map +1 -1
- package/dist/renderers/segments/code.d.ts.map +1 -1
- package/dist/renderers/segments/error.d.ts.map +1 -1
- package/dist/renderers/segments/pipeline-waiting.d.ts.map +1 -1
- package/dist/renderers/segments/thinking.d.ts.map +1 -1
- package/dist/renderers/segments/tool-call.d.ts.map +1 -1
- package/dist/types/event-map.d.ts +1 -2
- package/dist/types/event-map.d.ts.map +1 -1
- package/dist/types/events.d.ts +0 -22
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/models.d.ts +1 -6
- package/dist/types/models.d.ts.map +1 -1
- package/dist/types/segments.d.ts +87 -67
- package/dist/types/segments.d.ts.map +1 -1
- package/dist/utils/segments.d.ts +75 -5
- package/dist/utils/segments.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/index-hQQljwfX.js.map +0 -1
- package/dist/renderers/segments/file-tree.d.ts +0 -3
- package/dist/renderers/segments/file-tree.d.ts.map +0 -1
- package/dist/renderers/segments/terminal.d.ts +0 -3
- package/dist/renderers/segments/terminal.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { A, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p,
|
|
1
|
+
import { I as escapeAttr, D as cssEscape, $ as runWithConfig, Z as resolveConfig, a5 as mergeSegmentUpdate, J as escapeHtml, M as getSegmentRenderer, N as installDefaultRenderersOnce, r as AparteMessageRepository, a6 as stampSegmentActivity, a7 as stampSegmentOnInsert, a8 as stampSegmentOnUpdate, a9 as renumberSegments, aa as openSegmentIds, ab as isTerminalStatus, ac as adoptMessageSegments, O as isAwaitingReply, U as populateBubbleFromMessage, a4 as uuid, _ as revokeAttachmentUrls, a2 as subscribeConfigChange, w as buildElicitationPanel } from "./index-BnKBciDG.js";
|
|
2
|
+
import { A, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, s, t, u, v, x, y, z, B, C, E, F, G, H, K, L, P, Q, R, S, T, V, W, X, Y, a0, a1, a3 } from "./index-BnKBciDG.js";
|
|
3
3
|
class AparteOption extends HTMLElement {
|
|
4
4
|
static get observedAttributes() {
|
|
5
5
|
return ["value", "disabled", "selected", "data-status"];
|
|
@@ -804,7 +804,38 @@ class AparteChatBubble extends HTMLElement {
|
|
|
804
804
|
this._updateName();
|
|
805
805
|
this._updateLocalizedLabels();
|
|
806
806
|
this._updateWaiting();
|
|
807
|
+
this._renderAvatar();
|
|
808
|
+
this._relabelSegments();
|
|
809
|
+
this._updateTimestamp(this.getAttribute("timestamp"));
|
|
807
810
|
};
|
|
811
|
+
/**
|
|
812
|
+
* Ask every rendered segment to re-read its config-derived text.
|
|
813
|
+
*
|
|
814
|
+
* Not `_renderSegments()`, which wipes the container and rebuilds: that destroys a
|
|
815
|
+
* mounted artifact preview, reverts a reasoning block the reader expanded by
|
|
816
|
+
* clicking `<summary>` (the DOM's real state is never written back to `collapsed`),
|
|
817
|
+
* resets scroll inside long terminal panes, drops focus from an Approve/Reject
|
|
818
|
+
* gate, and throws away the incremental Markdown parser's buffered lookahead
|
|
819
|
+
* mid-stream — for a change that added no content. It also fires container-wide
|
|
820
|
+
* childList mutations, which is what the viewport's observer reads as "scroll to
|
|
821
|
+
* the bottom".
|
|
822
|
+
*
|
|
823
|
+
* `relabel` is the narrow alternative, bound by the same no-child-node rule as
|
|
824
|
+
* `update()`. A renderer that has no config-derived text does not implement it,
|
|
825
|
+
* and this loop simply skips it.
|
|
826
|
+
*/
|
|
827
|
+
_relabelSegments() {
|
|
828
|
+
if (!this._segmentsEl) return;
|
|
829
|
+
for (const segment of this._segments) {
|
|
830
|
+
const renderer = resolveSegmentRenderer(segment.type, this._cfg);
|
|
831
|
+
if (!renderer?.relabel) continue;
|
|
832
|
+
const el = this._segmentsEl.querySelector(
|
|
833
|
+
`:scope > [data-segment-id="${cssEscape(segment.id)}"]`
|
|
834
|
+
);
|
|
835
|
+
if (!el) continue;
|
|
836
|
+
runWithConfig(this._cfg, () => renderer.relabel(el, segment));
|
|
837
|
+
}
|
|
838
|
+
}
|
|
808
839
|
/**
|
|
809
840
|
* Re-apply the locale strings written straight into the markup by `_render()` —
|
|
810
841
|
* the accessible names a screen reader reads, which nothing else refreshes.
|
|
@@ -892,7 +923,7 @@ class AparteChatBubble extends HTMLElement {
|
|
|
892
923
|
}
|
|
893
924
|
/** Set segments for rich content */
|
|
894
925
|
setSegments(segments) {
|
|
895
|
-
this._segments = segments;
|
|
926
|
+
this._segments = [...segments];
|
|
896
927
|
this._renderSegments();
|
|
897
928
|
this._updateWaiting();
|
|
898
929
|
}
|
|
@@ -906,7 +937,7 @@ class AparteChatBubble extends HTMLElement {
|
|
|
906
937
|
updateSegment(segmentId, updates) {
|
|
907
938
|
const index = this._segments.findIndex((s2) => s2.id === segmentId);
|
|
908
939
|
if (index !== -1) {
|
|
909
|
-
const updated =
|
|
940
|
+
const updated = mergeSegmentUpdate(this._segments[index], updates);
|
|
910
941
|
this._segments[index] = updated;
|
|
911
942
|
this._applySegmentUpdate(segmentId, updated, updates);
|
|
912
943
|
}
|
|
@@ -1135,9 +1166,12 @@ class AparteChatBubble extends HTMLElement {
|
|
|
1135
1166
|
* (same null-guarded degradation as the other region hooks).
|
|
1136
1167
|
*/
|
|
1137
1168
|
_updateWaiting() {
|
|
1169
|
+
const empty = this._segments.length === 0 && !this._content.trim();
|
|
1170
|
+
const waiting = this._streaming && this._role !== "user" && empty;
|
|
1171
|
+
const box = this.querySelector(".aparte-message-content");
|
|
1172
|
+
if (box) box.hidden = empty && !waiting;
|
|
1138
1173
|
const el = this.querySelector(".aparte-waiting");
|
|
1139
1174
|
if (!el) return;
|
|
1140
|
-
const waiting = this._streaming && this._role !== "user" && this._segments.length === 0 && !this._content.trim();
|
|
1141
1175
|
el.hidden = !waiting;
|
|
1142
1176
|
if (!waiting) return;
|
|
1143
1177
|
const label = this._cfg.getLocale().typing;
|
|
@@ -1145,9 +1179,13 @@ class AparteChatBubble extends HTMLElement {
|
|
|
1145
1179
|
if (sr && sr.textContent !== label) sr.textContent = label;
|
|
1146
1180
|
}
|
|
1147
1181
|
/**
|
|
1148
|
-
* Hand the avatar host element off to the registered AvatarProvider, if
|
|
1149
|
-
*
|
|
1150
|
-
*
|
|
1182
|
+
* Hand the avatar host element off to the registered AvatarProvider, if any.
|
|
1183
|
+
*
|
|
1184
|
+
* With no provider the slot is left exactly as the shell rendered it — which for
|
|
1185
|
+
* the default shell means EMPTY, and hidden by `.aparte-avatar:empty`. This used
|
|
1186
|
+
* to claim it "falls back to the default initial rendered by `_render()`"; there
|
|
1187
|
+
* is no such initial, and believing there was is what made `_updateRole` write
|
|
1188
|
+
* one.
|
|
1151
1189
|
*/
|
|
1152
1190
|
_renderAvatar() {
|
|
1153
1191
|
const avatar = this.querySelector(".aparte-avatar");
|
|
@@ -1175,7 +1213,7 @@ class AparteChatBubble extends HTMLElement {
|
|
|
1175
1213
|
}
|
|
1176
1214
|
if (avatar) {
|
|
1177
1215
|
avatar.setAttribute("data-role", this._role);
|
|
1178
|
-
avatar.textContent = this._getAvatarInitial();
|
|
1216
|
+
if (avatar.textContent) avatar.textContent = this._getAvatarInitial();
|
|
1179
1217
|
}
|
|
1180
1218
|
if (nameEl) {
|
|
1181
1219
|
nameEl.textContent = this._getDisplayName();
|
|
@@ -1186,7 +1224,9 @@ class AparteChatBubble extends HTMLElement {
|
|
|
1186
1224
|
_updateName() {
|
|
1187
1225
|
const avatar = this.querySelector(".aparte-avatar");
|
|
1188
1226
|
const nameEl = this.querySelector(".aparte-name");
|
|
1189
|
-
if (avatar && !this._cfg.getAvatarProvider())
|
|
1227
|
+
if (avatar && avatar.textContent && !this._cfg.getAvatarProvider()) {
|
|
1228
|
+
avatar.textContent = this._getAvatarInitial();
|
|
1229
|
+
}
|
|
1190
1230
|
if (nameEl) nameEl.textContent = this._getDisplayName();
|
|
1191
1231
|
}
|
|
1192
1232
|
_updateContent() {
|
|
@@ -1271,7 +1311,7 @@ class AparteChatBubble extends HTMLElement {
|
|
|
1271
1311
|
if (!timestampEl || !value) return;
|
|
1272
1312
|
try {
|
|
1273
1313
|
const date = new Date(isNaN(Number(value)) ? value : Number(value));
|
|
1274
|
-
timestampEl.textContent = date.toLocaleTimeString(void 0, {
|
|
1314
|
+
timestampEl.textContent = date.toLocaleTimeString(this._cfg.getLocale().tag || void 0, {
|
|
1275
1315
|
hour: "2-digit",
|
|
1276
1316
|
minute: "2-digit"
|
|
1277
1317
|
});
|
|
@@ -2023,7 +2063,14 @@ class AparteChatViewport extends HTMLElement {
|
|
|
2023
2063
|
if (!message.segments) {
|
|
2024
2064
|
message.segments = [];
|
|
2025
2065
|
}
|
|
2026
|
-
const stamped = stampSegmentOnInsert(
|
|
2066
|
+
const stamped = stampSegmentOnInsert(
|
|
2067
|
+
message.segments,
|
|
2068
|
+
segment,
|
|
2069
|
+
messageId,
|
|
2070
|
+
// THIS chat's defaults, not the page's: two chats on one page can be
|
|
2071
|
+
// configured differently, and the config seam is per instance.
|
|
2072
|
+
resolveConfig(this).getSegmentDefaults(segment.type)
|
|
2073
|
+
);
|
|
2027
2074
|
message.segments.push(stamped);
|
|
2028
2075
|
this._notifyBubble(messageId, "addSegment", stamped);
|
|
2029
2076
|
this._autoScroll();
|
|
@@ -2040,10 +2087,7 @@ class AparteChatViewport extends HTMLElement {
|
|
|
2040
2087
|
if (segmentIndex !== -1) {
|
|
2041
2088
|
const current = message.segments[segmentIndex];
|
|
2042
2089
|
const stamped = stampSegmentOnUpdate(current, updates);
|
|
2043
|
-
message.segments[segmentIndex] =
|
|
2044
|
-
...current,
|
|
2045
|
-
...stamped
|
|
2046
|
-
};
|
|
2090
|
+
message.segments[segmentIndex] = mergeSegmentUpdate(current, stamped);
|
|
2047
2091
|
this._notifyBubble(messageId, "updateSegment", { segmentId, updates: stamped });
|
|
2048
2092
|
}
|
|
2049
2093
|
}
|
|
@@ -2143,7 +2187,7 @@ class AparteChatViewport extends HTMLElement {
|
|
|
2143
2187
|
* which both records the message and creates its bubble element.
|
|
2144
2188
|
*/
|
|
2145
2189
|
addMessage(message) {
|
|
2146
|
-
this._repo.addOrUpdateMessage(this._repo.headId, { ...message });
|
|
2190
|
+
this._repo.addOrUpdateMessage(this._repo.headId, adoptMessageSegments({ ...message }));
|
|
2147
2191
|
this._pruneRenderedBubbles();
|
|
2148
2192
|
this._autoScroll();
|
|
2149
2193
|
}
|
|
@@ -2154,8 +2198,20 @@ class AparteChatViewport extends HTMLElement {
|
|
|
2154
2198
|
* When `_frameworkManagedDOM` is true, only the internal repo is updated —
|
|
2155
2199
|
* the framework owns the DOM and will create the bubble element itself.
|
|
2156
2200
|
*/
|
|
2157
|
-
appendMessage(message) {
|
|
2158
|
-
|
|
2201
|
+
appendMessage(message, options) {
|
|
2202
|
+
const stored = options?.historical ? adoptMessageSegments(message) : message.segments?.length ? { ...message, segments: message.segments.reduce(
|
|
2203
|
+
(acc, segment) => {
|
|
2204
|
+
acc.push(stampSegmentOnInsert(
|
|
2205
|
+
acc,
|
|
2206
|
+
segment,
|
|
2207
|
+
message.id,
|
|
2208
|
+
resolveConfig(this).getSegmentDefaults(segment.type)
|
|
2209
|
+
));
|
|
2210
|
+
return acc;
|
|
2211
|
+
},
|
|
2212
|
+
[]
|
|
2213
|
+
) } : { ...message };
|
|
2214
|
+
this._repo.addOrUpdateMessage(this._repo.headId, stored);
|
|
2159
2215
|
if (!this._frameworkManagedDOM) {
|
|
2160
2216
|
const wrapper = this.querySelector(".aparte-messages-wrapper");
|
|
2161
2217
|
if (wrapper) {
|
|
@@ -2172,7 +2228,7 @@ class AparteChatViewport extends HTMLElement {
|
|
|
2172
2228
|
} else {
|
|
2173
2229
|
wrapper.appendChild(bubble);
|
|
2174
2230
|
}
|
|
2175
|
-
populateBubbleFromMessage(bubble,
|
|
2231
|
+
populateBubbleFromMessage(bubble, stored);
|
|
2176
2232
|
}
|
|
2177
2233
|
}
|
|
2178
2234
|
this._pruneRenderedBubbles();
|
|
@@ -2322,7 +2378,13 @@ class AparteChatViewport extends HTMLElement {
|
|
|
2322
2378
|
*/
|
|
2323
2379
|
importTree(tree) {
|
|
2324
2380
|
this.clearAll({ revokeAttachments: false });
|
|
2325
|
-
this._repo.import(
|
|
2381
|
+
this._repo.import({
|
|
2382
|
+
...tree,
|
|
2383
|
+
messages: tree.messages.map((entry) => ({
|
|
2384
|
+
...entry,
|
|
2385
|
+
message: adoptMessageSegments(entry.message)
|
|
2386
|
+
}))
|
|
2387
|
+
});
|
|
2326
2388
|
this._reRenderActivePath();
|
|
2327
2389
|
}
|
|
2328
2390
|
/**
|
|
@@ -2370,7 +2432,7 @@ class AparteChatViewport extends HTMLElement {
|
|
|
2370
2432
|
setMessages(messages) {
|
|
2371
2433
|
this.clearAll({ revokeAttachments: false });
|
|
2372
2434
|
for (const m2 of messages) {
|
|
2373
|
-
this.appendMessage(m2);
|
|
2435
|
+
this.appendMessage(m2, { historical: true });
|
|
2374
2436
|
}
|
|
2375
2437
|
}
|
|
2376
2438
|
/**
|
|
@@ -3231,6 +3293,7 @@ class AparteComposerInput extends HTMLElement {
|
|
|
3231
3293
|
this._render();
|
|
3232
3294
|
this._connectToRoot();
|
|
3233
3295
|
this._scheduleInitialReflow();
|
|
3296
|
+
this._unsubscribes.push(subscribeConfigChange(this, () => this._updatePlaceholder()));
|
|
3234
3297
|
}
|
|
3235
3298
|
disconnectedCallback() {
|
|
3236
3299
|
this._editor?.removeEventListener("input", this._onInput);
|
|
@@ -3434,6 +3497,16 @@ if (!customElements.get("aparte-composer-input")) {
|
|
|
3434
3497
|
class AparteComposerSend extends HTMLElement {
|
|
3435
3498
|
_button = null;
|
|
3436
3499
|
_unsubscribes = [];
|
|
3500
|
+
/**
|
|
3501
|
+
* The last `panel-change` payload.
|
|
3502
|
+
*
|
|
3503
|
+
* This button has four meanings — send, stop, submit an answer, advance to the
|
|
3504
|
+
* next question — and three of them are decided by state it does not own: the
|
|
3505
|
+
* root's `streaming`, and this payload. It was read straight out of the event's
|
|
3506
|
+
* arguments and thrown away, so nothing could recompute the button's chrome
|
|
3507
|
+
* afterwards; a config change had no way to know which of the four to write.
|
|
3508
|
+
*/
|
|
3509
|
+
_panel = null;
|
|
3437
3510
|
// Bound handler
|
|
3438
3511
|
_onClick = this._handleClick.bind(this);
|
|
3439
3512
|
connectedCallback() {
|
|
@@ -3483,27 +3556,56 @@ class AparteComposerSend extends HTMLElement {
|
|
|
3483
3556
|
root._on("attachments-change", () => this._syncState())
|
|
3484
3557
|
);
|
|
3485
3558
|
this._unsubscribes.push(
|
|
3486
|
-
root._on("panel-change", (
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
this._button.disabled = !submitEnabled;
|
|
3490
|
-
const cfg = resolveConfig(this);
|
|
3491
|
-
const advancing = mode === "advance";
|
|
3492
|
-
this._button.innerHTML = advancing ? cfg.getIcon("nextBranch") : this._getSubmitIcon();
|
|
3493
|
-
const label = advancing ? cfg.t("elicitationNext") || "Next" : cfg.t("submitButton") || "Submit";
|
|
3494
|
-
this._button.setAttribute("aria-label", label);
|
|
3495
|
-
this._button.setAttribute("title", label);
|
|
3496
|
-
this._button.classList.remove("is-streaming");
|
|
3497
|
-
} else {
|
|
3498
|
-
const root2 = this._getRoot();
|
|
3499
|
-
if (root2?.streaming) {
|
|
3500
|
-
this._syncStreamingState(true);
|
|
3501
|
-
} else {
|
|
3502
|
-
this._syncState();
|
|
3503
|
-
}
|
|
3504
|
-
}
|
|
3559
|
+
root._on("panel-change", (payload) => {
|
|
3560
|
+
this._panel = payload;
|
|
3561
|
+
this._refreshChrome();
|
|
3505
3562
|
})
|
|
3506
3563
|
);
|
|
3564
|
+
this._unsubscribes.push(subscribeConfigChange(this, () => this._refreshChrome()));
|
|
3565
|
+
}
|
|
3566
|
+
/**
|
|
3567
|
+
* Write the chrome for the mode the button is IN, deciding before writing.
|
|
3568
|
+
*
|
|
3569
|
+
* Never `_render()`: it returns early once the button exists, and its own
|
|
3570
|
+
* disabled/icon computation consults neither `root.streaming` nor the panel — so
|
|
3571
|
+
* rebuilding mid-turn would put a paper plane back while a reply was still
|
|
3572
|
+
* streaming, and rebuilding with the question panel open would silently drop out
|
|
3573
|
+
* of answer mode. It would also take the focus off the one control in this
|
|
3574
|
+
* composer most likely to be holding it.
|
|
3575
|
+
*/
|
|
3576
|
+
_refreshChrome() {
|
|
3577
|
+
if (!this._button) return;
|
|
3578
|
+
if (this._panel?.active) {
|
|
3579
|
+
this._syncPanelState();
|
|
3580
|
+
return;
|
|
3581
|
+
}
|
|
3582
|
+
if (this._getRoot()?.streaming) {
|
|
3583
|
+
this._syncStreamingState(true);
|
|
3584
|
+
return;
|
|
3585
|
+
}
|
|
3586
|
+
this._syncState();
|
|
3587
|
+
}
|
|
3588
|
+
/**
|
|
3589
|
+
* Panel open: this one button now means "answer", and WHICH answer depends on
|
|
3590
|
+
* where you are in the form.
|
|
3591
|
+
*
|
|
3592
|
+
* The icon has to move with the meaning: it drew a paper plane while the label
|
|
3593
|
+
* already said "Submit", so it read as "send a message" while it meant "answer
|
|
3594
|
+
* this question". And a check on a form with three questions left was just as
|
|
3595
|
+
* wrong — hence a chevron while there is more ahead. The visual is what a user
|
|
3596
|
+
* reads.
|
|
3597
|
+
*/
|
|
3598
|
+
_syncPanelState() {
|
|
3599
|
+
const panel = this._panel;
|
|
3600
|
+
if (!this._button || !panel?.active) return;
|
|
3601
|
+
const cfg = resolveConfig(this);
|
|
3602
|
+
const advancing = panel.mode === "advance";
|
|
3603
|
+
this._button.disabled = !panel.submitEnabled;
|
|
3604
|
+
this._button.innerHTML = advancing ? cfg.getIcon("nextBranch") : this._getSubmitIcon();
|
|
3605
|
+
const label = advancing ? cfg.t("elicitationNext") || "Next" : cfg.t("submitButton") || "Submit";
|
|
3606
|
+
this._button.setAttribute("aria-label", label);
|
|
3607
|
+
this._button.setAttribute("title", label);
|
|
3608
|
+
this._button.classList.remove("is-streaming");
|
|
3507
3609
|
}
|
|
3508
3610
|
_handleClick(e2) {
|
|
3509
3611
|
e2.preventDefault();
|
|
@@ -3526,8 +3628,9 @@ class AparteComposerSend extends HTMLElement {
|
|
|
3526
3628
|
if (streaming) {
|
|
3527
3629
|
this._button.disabled = false;
|
|
3528
3630
|
this._button.innerHTML = this._getStopIcon();
|
|
3529
|
-
this.
|
|
3530
|
-
this._button.setAttribute("
|
|
3631
|
+
const label = resolveConfig(this).t("stopButton") || "Stop";
|
|
3632
|
+
this._button.setAttribute("aria-label", label);
|
|
3633
|
+
this._button.setAttribute("title", label);
|
|
3531
3634
|
this._button.classList.add("is-streaming");
|
|
3532
3635
|
} else {
|
|
3533
3636
|
this._syncState();
|
|
@@ -3558,6 +3661,7 @@ class AparteComposerCancel extends HTMLElement {
|
|
|
3558
3661
|
connectedCallback() {
|
|
3559
3662
|
this._render();
|
|
3560
3663
|
this._connectToRoot();
|
|
3664
|
+
this._unsubscribes.push(subscribeConfigChange(this, () => this._refreshChrome()));
|
|
3561
3665
|
}
|
|
3562
3666
|
disconnectedCallback() {
|
|
3563
3667
|
this._button?.removeEventListener("click", this._onClick);
|
|
@@ -3595,6 +3699,20 @@ class AparteComposerCancel extends HTMLElement {
|
|
|
3595
3699
|
e2.preventDefault();
|
|
3596
3700
|
this._getRoot()?.cancel();
|
|
3597
3701
|
}
|
|
3702
|
+
/**
|
|
3703
|
+
* Re-read the accessible name and the icon in place.
|
|
3704
|
+
*
|
|
3705
|
+
* `hidden` is NOT touched: `_render()` always renders this button hidden and only
|
|
3706
|
+
* the root's `streaming-change` listener ever un-hides it, so a rebuild would make
|
|
3707
|
+
* the stop button vanish in the middle of a turn.
|
|
3708
|
+
*/
|
|
3709
|
+
_refreshChrome() {
|
|
3710
|
+
if (!this._button) return;
|
|
3711
|
+
const label = resolveConfig(this).t("stopButton") || "Stop";
|
|
3712
|
+
this._button.setAttribute("aria-label", label);
|
|
3713
|
+
this._button.setAttribute("title", label);
|
|
3714
|
+
this._button.innerHTML = this._getStopIcon();
|
|
3715
|
+
}
|
|
3598
3716
|
_getStopIcon() {
|
|
3599
3717
|
return resolveConfig(this).getIcon("stop");
|
|
3600
3718
|
}
|
|
@@ -3700,6 +3818,7 @@ class AparteComposerAddAttachment extends HTMLElement {
|
|
|
3700
3818
|
this._render();
|
|
3701
3819
|
this._connectToRoot();
|
|
3702
3820
|
this._setupDragDrop();
|
|
3821
|
+
this._unsubscribes.push(subscribeConfigChange(this, () => this._refreshChrome()));
|
|
3703
3822
|
}
|
|
3704
3823
|
disconnectedCallback() {
|
|
3705
3824
|
this._button?.removeEventListener("click", this._onClick);
|
|
@@ -3716,6 +3835,24 @@ class AparteComposerAddAttachment extends HTMLElement {
|
|
|
3716
3835
|
_getRoot() {
|
|
3717
3836
|
return this.closest("aparte-composer");
|
|
3718
3837
|
}
|
|
3838
|
+
/**
|
|
3839
|
+
* Re-read the label and the icon on the button that already exists.
|
|
3840
|
+
*
|
|
3841
|
+
* Deliberately not a re-render: `_render()` returns early once the button is
|
|
3842
|
+
* there, and its `disabled` computation ignores `root.streaming` while the
|
|
3843
|
+
* streaming listener sets `disabled` directly — so rebuilding would silently
|
|
3844
|
+
* re-enable the attach button mid-turn, and drop focus if the user were on it.
|
|
3845
|
+
* The native file input and the drag listeners live outside this element
|
|
3846
|
+
* (on `document.body` and on the composer root), so they are untouched either way.
|
|
3847
|
+
*/
|
|
3848
|
+
_refreshChrome() {
|
|
3849
|
+
if (!this._button) return;
|
|
3850
|
+
const cfg = resolveConfig(this);
|
|
3851
|
+
const label = cfg.t("actionUpload") || "Attach file";
|
|
3852
|
+
this._button.setAttribute("aria-label", label);
|
|
3853
|
+
this._button.setAttribute("title", label);
|
|
3854
|
+
this._button.innerHTML = cfg.getIcon("paperclip") || this._defaultIcon();
|
|
3855
|
+
}
|
|
3719
3856
|
_render() {
|
|
3720
3857
|
if (this.querySelector(".aparte-caa-button")) return;
|
|
3721
3858
|
const label = resolveConfig(this).t("actionUpload") || "Attach file";
|
|
@@ -3809,6 +3946,9 @@ class AparteComposerAction extends HTMLElement {
|
|
|
3809
3946
|
connectedCallback() {
|
|
3810
3947
|
this._render();
|
|
3811
3948
|
this._connectToRoot();
|
|
3949
|
+
this._unsubscribes.push(subscribeConfigChange(this, () => {
|
|
3950
|
+
if (this._button) this._button.innerHTML = this._resolveIcon(this.getAttribute("icon") ?? "");
|
|
3951
|
+
}));
|
|
3812
3952
|
}
|
|
3813
3953
|
disconnectedCallback() {
|
|
3814
3954
|
this._button?.removeEventListener("click", this._onClick);
|
|
@@ -4090,8 +4230,10 @@ class AparteElicitation extends HTMLElement {
|
|
|
4090
4230
|
if (evtTargetId && own && evtTargetId !== own) return;
|
|
4091
4231
|
this._cancelPending();
|
|
4092
4232
|
};
|
|
4233
|
+
_unsubscribeConfig = null;
|
|
4093
4234
|
connectedCallback() {
|
|
4094
4235
|
this.style.display = "none";
|
|
4236
|
+
this._unsubscribeConfig = subscribeConfigChange(this, () => this._relabelPending());
|
|
4095
4237
|
resolveConfig(this).setElicitationPresenter(this._present);
|
|
4096
4238
|
window.addEventListener("aparte-message-aborted", this._onTurnEnd);
|
|
4097
4239
|
window.addEventListener("aparte-message-error", this._onTurnEnd);
|
|
@@ -4117,8 +4259,24 @@ class AparteElicitation extends HTMLElement {
|
|
|
4117
4259
|
if (cfg.getElicitationPresenter() === this._present) cfg.setElicitationPresenter(null);
|
|
4118
4260
|
window.removeEventListener("aparte-message-aborted", this._onTurnEnd);
|
|
4119
4261
|
window.removeEventListener("aparte-message-error", this._onTurnEnd);
|
|
4262
|
+
this._unsubscribeConfig?.();
|
|
4263
|
+
this._unsubscribeConfig = null;
|
|
4120
4264
|
this._cancelPending();
|
|
4121
4265
|
}
|
|
4266
|
+
/**
|
|
4267
|
+
* Re-apply the open question's strings, in place.
|
|
4268
|
+
*
|
|
4269
|
+
* Two owners, and both have to move or the panel goes bilingual: the panel's own
|
|
4270
|
+
* defaults (`relabel`), and the Skip button, which this file builds and this file
|
|
4271
|
+
* therefore has to re-text. The composer's one button is a third, and it already
|
|
4272
|
+
* follows — `aparte-composer-send` remembers the panel state it was given.
|
|
4273
|
+
*/
|
|
4274
|
+
_relabelPending() {
|
|
4275
|
+
if (!this._pending) return;
|
|
4276
|
+
const cfg = resolveConfig(this);
|
|
4277
|
+
runWithConfig(cfg, () => this._pending.panel.relabel());
|
|
4278
|
+
this._pending.skip.textContent = cfg.t("elicitationSkip");
|
|
4279
|
+
}
|
|
4122
4280
|
_present = (request) => {
|
|
4123
4281
|
if (this._pending) return Promise.resolve({ action: "cancel" });
|
|
4124
4282
|
const composer = this._getComposer();
|
|
@@ -4149,7 +4307,7 @@ class AparteElicitation extends HTMLElement {
|
|
|
4149
4307
|
skip.textContent = cfg.t("elicitationSkip");
|
|
4150
4308
|
skip.addEventListener("click", () => settle({ action: "decline" }));
|
|
4151
4309
|
panel.dismiss.appendChild(skip);
|
|
4152
|
-
this._pending = { settle, composer };
|
|
4310
|
+
this._pending = { settle, composer, panel, skip };
|
|
4153
4311
|
composer.showPanel(panel.el, {
|
|
4154
4312
|
submitEnabled: panel.canProceed(),
|
|
4155
4313
|
mode: panel.mode(),
|
|
@@ -4233,21 +4391,22 @@ function registerAllComponents() {
|
|
|
4233
4391
|
}
|
|
4234
4392
|
}
|
|
4235
4393
|
export {
|
|
4236
|
-
A as
|
|
4237
|
-
a as
|
|
4238
|
-
b as
|
|
4239
|
-
c as
|
|
4240
|
-
d as
|
|
4241
|
-
e as
|
|
4242
|
-
f as
|
|
4243
|
-
g as
|
|
4244
|
-
h as
|
|
4394
|
+
A as APARTE_CONFIG_CHANGE,
|
|
4395
|
+
a as APARTE_CONVERSATION_SCHEMA_VERSION,
|
|
4396
|
+
b as APARTE_DEFAULT_BUBBLE_ACTIONS,
|
|
4397
|
+
c as APARTE_DEFAULT_HOST_HANDLERS,
|
|
4398
|
+
d as APARTE_DEFAULT_ICON_FALLBACKS,
|
|
4399
|
+
e as APARTE_DEFAULT_LOCALE,
|
|
4400
|
+
f as APARTE_DEFAULT_SKELETON_FALLBACKS,
|
|
4401
|
+
g as APARTE_DEFAULT_UI_EVENTS,
|
|
4402
|
+
h as APARTE_HOST_ATTR,
|
|
4403
|
+
i as AparteBackendTransport,
|
|
4245
4404
|
AparteChat,
|
|
4246
4405
|
AparteChatBubble,
|
|
4247
|
-
|
|
4406
|
+
j as AparteChatHost,
|
|
4248
4407
|
AparteChatStatus,
|
|
4249
4408
|
AparteChatViewport,
|
|
4250
|
-
|
|
4409
|
+
k as AparteClient,
|
|
4251
4410
|
AparteComposer,
|
|
4252
4411
|
AparteComposerAction,
|
|
4253
4412
|
AparteComposerAddAttachment,
|
|
@@ -4256,57 +4415,59 @@ export {
|
|
|
4256
4415
|
AparteComposerInput,
|
|
4257
4416
|
AparteComposerSend,
|
|
4258
4417
|
AparteComposerToolbar,
|
|
4259
|
-
|
|
4260
|
-
|
|
4418
|
+
l as AparteConfig,
|
|
4419
|
+
m as AparteConversationController,
|
|
4261
4420
|
AparteConversationList,
|
|
4262
|
-
|
|
4263
|
-
|
|
4421
|
+
n as AparteConversationManager,
|
|
4422
|
+
o as AparteDirectTransport,
|
|
4264
4423
|
AparteElicitation,
|
|
4265
|
-
|
|
4266
|
-
|
|
4424
|
+
p as AparteError,
|
|
4425
|
+
q as AparteErrorCode,
|
|
4267
4426
|
AparteMessageRepository,
|
|
4268
4427
|
AparteOptgroup,
|
|
4269
4428
|
AparteOption,
|
|
4270
4429
|
AparteProgressSpinner,
|
|
4271
4430
|
AparteSelect,
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4431
|
+
s as AparteStreamParser,
|
|
4432
|
+
t as aparteGlobalConfig,
|
|
4433
|
+
u as applyElementProps,
|
|
4434
|
+
v as attachConfig,
|
|
4276
4435
|
buildElicitationPanel,
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4436
|
+
x as collectRendererStyles,
|
|
4437
|
+
y as contentToText,
|
|
4438
|
+
z as contextConfig,
|
|
4439
|
+
B as createAparteChatHandler,
|
|
4440
|
+
C as createStreamAdapter,
|
|
4282
4441
|
cssEscape,
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4442
|
+
E as declineDefaultRenderers,
|
|
4443
|
+
F as defaultSanitizer,
|
|
4444
|
+
G as deriveArtifactKind,
|
|
4445
|
+
H as detachConfig,
|
|
4287
4446
|
escapeAttr,
|
|
4288
4447
|
escapeHtml,
|
|
4289
|
-
|
|
4290
|
-
|
|
4448
|
+
K as filesToAttachments,
|
|
4449
|
+
L as getAllRenderers,
|
|
4291
4450
|
getSegmentRenderer,
|
|
4292
4451
|
installDefaultRenderersOnce,
|
|
4293
4452
|
isAwaitingReply,
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4453
|
+
P as isFormatAdapter,
|
|
4454
|
+
Q as isSafeUrl,
|
|
4455
|
+
R as isSegmentSettled,
|
|
4456
|
+
S as parseAparteEventStream,
|
|
4457
|
+
T as parseMarkdownToSegments,
|
|
4299
4458
|
populateBubbleFromMessage,
|
|
4300
|
-
|
|
4459
|
+
V as readableToAsyncIterable,
|
|
4301
4460
|
registerAllComponents,
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4461
|
+
W as registerDefaultRenderers,
|
|
4462
|
+
X as registerSegmentRenderer,
|
|
4463
|
+
Y as requestUserInput,
|
|
4305
4464
|
resolveConfig,
|
|
4306
4465
|
revokeAttachmentUrls,
|
|
4307
4466
|
runWithConfig,
|
|
4308
|
-
|
|
4309
|
-
|
|
4467
|
+
a0 as segmentDuration,
|
|
4468
|
+
a1 as segmentTiming,
|
|
4469
|
+
subscribeConfigChange,
|
|
4470
|
+
a3 as unregisterSegmentRenderer,
|
|
4310
4471
|
uuid
|
|
4311
4472
|
};
|
|
4312
4473
|
//# sourceMappingURL=index.js.map
|