@kodaris/krubble-app-components 1.0.146 → 1.0.148
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/chatbot.d.ts +17 -0
- package/dist/chatbot.d.ts.map +1 -1
- package/dist/chatbot.js +73 -1
- package/dist/chatbot.js.map +1 -1
- package/dist/krubble-app.bundled.js +85 -3
- package/dist/krubble-app.bundled.js.map +1 -1
- package/dist/krubble-app.bundled.min.js +13 -5
- package/dist/krubble-app.bundled.min.js.map +1 -1
- package/dist/krubble-app.umd.js +85 -3
- package/dist/krubble-app.umd.js.map +1 -1
- package/dist/krubble-app.umd.min.js +14 -6
- package/dist/krubble-app.umd.min.js.map +1 -1
- package/dist/screen-nav.d.ts +13 -2
- package/dist/screen-nav.d.ts.map +1 -1
- package/dist/screen-nav.js +12 -2
- package/dist/screen-nav.js.map +1 -1
- package/package.json +1 -1
package/dist/krubble-app.umd.js
CHANGED
|
@@ -2900,6 +2900,13 @@
|
|
|
2900
2900
|
*/
|
|
2901
2901
|
this._reconnectAttempts = 0;
|
|
2902
2902
|
this._userHasScrolledUp = false;
|
|
2903
|
+
/**
|
|
2904
|
+
* Keep the end of the streaming response in view. Set at the start of every
|
|
2905
|
+
* turn (send, confirmation decision, reconnect); cleared when the user scrolls
|
|
2906
|
+
* up on their own (wheel, touch drag, scrollbar drag) and restored when they
|
|
2907
|
+
* scroll back to the bottom. Checked in updated() after every streamed chunk.
|
|
2908
|
+
*/
|
|
2909
|
+
this._followStream = false;
|
|
2903
2910
|
this._isDragging = false;
|
|
2904
2911
|
this._isResizing = false;
|
|
2905
2912
|
this._overlay = null;
|
|
@@ -3555,6 +3562,35 @@
|
|
|
3555
3562
|
});
|
|
3556
3563
|
}
|
|
3557
3564
|
}
|
|
3565
|
+
// Streamed chunks mutate the message in place and call requestUpdate(), so
|
|
3566
|
+
// `changed` never has 'messages' mid-turn — run the follow on every update
|
|
3567
|
+
// instead. The user message stays pinned at the top (Gemini-style) until the
|
|
3568
|
+
// response grows past the bottom of the view; from then on the end stays in
|
|
3569
|
+
// view. Never scrolls to the empty runway below the content.
|
|
3570
|
+
if (this._isStreaming && this._followStream && this._messagesEl) {
|
|
3571
|
+
requestAnimationFrame(() => {
|
|
3572
|
+
const container = this._messagesEl;
|
|
3573
|
+
if (!container || !this._isStreaming || !this._followStream) {
|
|
3574
|
+
return;
|
|
3575
|
+
}
|
|
3576
|
+
const turnEls = container.querySelectorAll('.agent-turn');
|
|
3577
|
+
const turnEl = turnEls[turnEls.length - 1];
|
|
3578
|
+
const lastEl = turnEl?.lastElementChild;
|
|
3579
|
+
if (!lastEl) {
|
|
3580
|
+
return;
|
|
3581
|
+
}
|
|
3582
|
+
// Bottom edge of the turn's last rendered child, in the container's
|
|
3583
|
+
// scroll coordinates — the runway (min-height on the turn) sits below it.
|
|
3584
|
+
const contentBottom = lastEl.getBoundingClientRect().bottom
|
|
3585
|
+
- container.getBoundingClientRect().top
|
|
3586
|
+
+ container.scrollTop
|
|
3587
|
+
+ 24;
|
|
3588
|
+
const visibleBottom = container.scrollTop + container.clientHeight;
|
|
3589
|
+
if (contentBottom > visibleBottom) {
|
|
3590
|
+
container.scrollTop = Math.min(contentBottom - container.clientHeight, container.scrollHeight - container.clientHeight);
|
|
3591
|
+
}
|
|
3592
|
+
});
|
|
3593
|
+
}
|
|
3558
3594
|
if (changed.has('opened') && this.opened && this._inputEl) {
|
|
3559
3595
|
setTimeout(() => {
|
|
3560
3596
|
if (this._inputEl) {
|
|
@@ -4623,6 +4659,7 @@
|
|
|
4623
4659
|
this._saveState();
|
|
4624
4660
|
this._error = '';
|
|
4625
4661
|
this._userHasScrolledUp = false;
|
|
4662
|
+
this._followStream = true;
|
|
4626
4663
|
// Clear the composer, but DON'T revoke the preview object URLs — the sent
|
|
4627
4664
|
// message now renders them until the upload's real files replace them.
|
|
4628
4665
|
this._pendingConversationFiles = [];
|
|
@@ -4857,6 +4894,7 @@
|
|
|
4857
4894
|
this._turnFinishedCleanly = false;
|
|
4858
4895
|
this._reconnectAttempts = 0;
|
|
4859
4896
|
this._userHasScrolledUp = false;
|
|
4897
|
+
this._followStream = true;
|
|
4860
4898
|
this.send({
|
|
4861
4899
|
message: '',
|
|
4862
4900
|
messages: this.messages,
|
|
@@ -4957,6 +4995,33 @@
|
|
|
4957
4995
|
}
|
|
4958
4996
|
else {
|
|
4959
4997
|
this._userHasScrolledUp = false;
|
|
4998
|
+
// Back at the bottom mid-turn: resume following the stream end.
|
|
4999
|
+
if (this._isStreaming) {
|
|
5000
|
+
this._followStream = true;
|
|
5001
|
+
}
|
|
5002
|
+
}
|
|
5003
|
+
}
|
|
5004
|
+
/**
|
|
5005
|
+
* User-driven scroll intent while a response streams. Scroll events alone can't
|
|
5006
|
+
* tell the user apart from our own follow-scroll (and from scrollTop clamping
|
|
5007
|
+
* when the runway clears), so listen for the gestures instead: a wheel/trackpad
|
|
5008
|
+
* move up, any touch drag, or a pointer down on the scrollbar track. Any of
|
|
5009
|
+
* these stops the follow; scrolling back to the bottom restores it.
|
|
5010
|
+
*/
|
|
5011
|
+
_handleMessagesWheel(e) {
|
|
5012
|
+
if (this._isStreaming && e.deltaY < 0) {
|
|
5013
|
+
this._followStream = false;
|
|
5014
|
+
}
|
|
5015
|
+
}
|
|
5016
|
+
_handleMessagesTouchMove() {
|
|
5017
|
+
if (this._isStreaming) {
|
|
5018
|
+
this._followStream = false;
|
|
5019
|
+
}
|
|
5020
|
+
}
|
|
5021
|
+
_handleMessagesPointerDown(e) {
|
|
5022
|
+
const container = e.currentTarget;
|
|
5023
|
+
if (this._isStreaming && e.offsetX >= container.clientWidth) {
|
|
5024
|
+
this._followStream = false;
|
|
4960
5025
|
}
|
|
4961
5026
|
}
|
|
4962
5027
|
_handleErrorDismiss() {
|
|
@@ -5529,6 +5594,7 @@
|
|
|
5529
5594
|
// (a no-op).
|
|
5530
5595
|
this._reconnectAttempts = 0;
|
|
5531
5596
|
this._isStreaming = true;
|
|
5597
|
+
this._followStream = true;
|
|
5532
5598
|
this._reader = response.body.getReader();
|
|
5533
5599
|
this._decoder = new TextDecoder();
|
|
5534
5600
|
this._buffer = '';
|
|
@@ -6647,7 +6713,13 @@
|
|
|
6647
6713
|
</div>
|
|
6648
6714
|
</div>
|
|
6649
6715
|
|
|
6650
|
-
<div
|
|
6716
|
+
<div
|
|
6717
|
+
class="messages"
|
|
6718
|
+
@scroll=${this._handleMessagesScroll}
|
|
6719
|
+
@wheel=${this._handleMessagesWheel}
|
|
6720
|
+
@touchmove=${this._handleMessagesTouchMove}
|
|
6721
|
+
@pointerdown=${this._handleMessagesPointerDown}
|
|
6722
|
+
>
|
|
6651
6723
|
<div class="messages-inner">
|
|
6652
6724
|
${this.messages.length === 0 ? b `
|
|
6653
6725
|
<div class="empty">
|
|
@@ -11547,6 +11619,7 @@
|
|
|
11547
11619
|
* activeId="overview"
|
|
11548
11620
|
* .actions=${[
|
|
11549
11621
|
* { id: 'edit', label: 'Edit', variant: 'flat' },
|
|
11622
|
+
* { id: 'preview', label: 'Preview', href: '/s/companies/123', target: '_blank' },
|
|
11550
11623
|
* { id: 'archive', label: 'Archive' },
|
|
11551
11624
|
* { id: 'delete', label: 'Delete' },
|
|
11552
11625
|
* { id: 'export', label: 'Export' },
|
|
@@ -11558,7 +11631,8 @@
|
|
|
11558
11631
|
*
|
|
11559
11632
|
* Actions render in a footer at the bottom of the nav column. With more than
|
|
11560
11633
|
* `maxVisibleActions` (default 5), the overflow collapses into a "More" dropdown.
|
|
11561
|
-
* Listen for `action-click` to handle a click: `e.detail.action` is the action id.
|
|
11634
|
+
* Listen for `action-click` to handle a click: `e.detail.action` is the action id. An action with
|
|
11635
|
+
* an `href` renders as a link and navigates on its own; it does not fire `action-click`.
|
|
11562
11636
|
*
|
|
11563
11637
|
* @slot - The main screen content
|
|
11564
11638
|
*
|
|
@@ -11569,7 +11643,7 @@
|
|
|
11569
11643
|
* @property {KRScreenNavAction[]} actions - Action buttons rendered in the nav footer
|
|
11570
11644
|
* @property {number} maxVisibleActions - Max inline actions before collapsing into a "More" dropdown (default 5)
|
|
11571
11645
|
*
|
|
11572
|
-
* @fires action-click - When an action button (inline or overflow) is clicked; detail is `{ action: id }`
|
|
11646
|
+
* @fires action-click - When an action button (inline or overflow) without an `href` is clicked; detail is `{ action: id }`
|
|
11573
11647
|
*/
|
|
11574
11648
|
class KRScreenNav extends i$3 {
|
|
11575
11649
|
constructor() {
|
|
@@ -11663,6 +11737,10 @@
|
|
|
11663
11737
|
}
|
|
11664
11738
|
}
|
|
11665
11739
|
handleActionClick(e, action) {
|
|
11740
|
+
// A link action navigates on its own through the kr-button's anchor; it doesn't fire action-click.
|
|
11741
|
+
if (action.href) {
|
|
11742
|
+
return;
|
|
11743
|
+
}
|
|
11666
11744
|
this.dispatchEvent(new CustomEvent('action-click', {
|
|
11667
11745
|
detail: { action: action.id },
|
|
11668
11746
|
bubbles: true,
|
|
@@ -11689,6 +11767,8 @@
|
|
|
11689
11767
|
overflowOptions = this.actions.slice(this.maxVisibleActions - 1).map((action) => ({
|
|
11690
11768
|
id: action.id,
|
|
11691
11769
|
label: action.label,
|
|
11770
|
+
href: action.href,
|
|
11771
|
+
hrefTarget: action.target,
|
|
11692
11772
|
}));
|
|
11693
11773
|
}
|
|
11694
11774
|
return b `
|
|
@@ -11724,6 +11804,8 @@
|
|
|
11724
11804
|
class="nav-actions__button"
|
|
11725
11805
|
variant=${action.variant || 'outline'}
|
|
11726
11806
|
size="small"
|
|
11807
|
+
href=${action.href || A}
|
|
11808
|
+
target=${action.target || A}
|
|
11727
11809
|
@click=${(e) => this.handleActionClick(e, action)}
|
|
11728
11810
|
>
|
|
11729
11811
|
${action.label}
|