@kodaris/krubble-app-components 1.0.87 → 1.0.89
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.map +1 -1
- package/dist/chatbot.js +66 -39
- package/dist/chatbot.js.map +1 -1
- package/dist/krubble-app.bundled.js +66 -39
- package/dist/krubble-app.bundled.js.map +1 -1
- package/dist/krubble-app.bundled.min.js +39 -31
- package/dist/krubble-app.bundled.min.js.map +1 -1
- package/dist/krubble-app.umd.js +66 -39
- package/dist/krubble-app.umd.js.map +1 -1
- package/dist/krubble-app.umd.min.js +36 -28
- package/dist/krubble-app.umd.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -5859,31 +5859,42 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
5859
5859
|
// --- Lifecycle ---
|
|
5860
5860
|
connectedCallback() {
|
|
5861
5861
|
super.connectedCallback();
|
|
5862
|
-
// Default to loading a
|
|
5863
|
-
//
|
|
5864
|
-
// conversation
|
|
5865
|
-
//
|
|
5866
|
-
// ({ type, content }); we only parse each row's
|
|
5867
|
-
// array string of ids) into
|
|
5862
|
+
// Default to loading a conversation's messages when the consumer hasn't
|
|
5863
|
+
// provided their own `load`. With `conversationId` set we rebuild that
|
|
5864
|
+
// conversation; with none set the user wants a NEW conversation, so we start
|
|
5865
|
+
// blank (no resume — the first message creates one via `send`). Rows already
|
|
5866
|
+
// match KRChatbotMessage ({ type, content }); we only parse each row's
|
|
5867
|
+
// `conversationFileIDs` (a JSON array string of ids) into `conversationFiles`.
|
|
5868
5868
|
if (!this.load) {
|
|
5869
5869
|
this.load = () => {
|
|
5870
5870
|
if (this.conversationId == null) {
|
|
5871
5871
|
return Promise.resolve([]);
|
|
5872
5872
|
}
|
|
5873
|
-
return KRHttp.fetch({
|
|
5874
|
-
url: `/api/system/conversation/${this.conversationId}/messages`,
|
|
5875
|
-
})
|
|
5873
|
+
return KRHttp.fetch({ url: `/api/system/conversation/${this.conversationId}/messages` })
|
|
5876
5874
|
.then((r) => r.json())
|
|
5877
|
-
.then((res) => (res?.data || []).map((msg) => {
|
|
5875
|
+
.then((res) => Promise.all((res?.data || []).map((msg) => {
|
|
5876
|
+
// Resolve this message's `conversationFileIDs` (a JSON array string of
|
|
5877
|
+
// ids) into full file objects — each fetch response IS the
|
|
5878
|
+
// KRChatbotConversationFile (id + niceName + mimeType), and niceName
|
|
5879
|
+
// drives the previewer's file-type detection. A failed fetch drops
|
|
5880
|
+
// that file rather than rendering a broken thumbnail.
|
|
5881
|
+
let ids = [];
|
|
5878
5882
|
try {
|
|
5879
|
-
|
|
5880
|
-
if (ids.length) {
|
|
5881
|
-
msg.conversationFiles = ids.map((id) => ({ conversationFileID: id }));
|
|
5882
|
-
}
|
|
5883
|
+
ids = JSON.parse(msg.conversationFileIDs || '[]');
|
|
5883
5884
|
}
|
|
5884
5885
|
catch { /* no/invalid attachments — leave empty */ }
|
|
5885
|
-
|
|
5886
|
-
|
|
5886
|
+
if (!ids.length) {
|
|
5887
|
+
return Promise.resolve(msg);
|
|
5888
|
+
}
|
|
5889
|
+
return Promise.all(ids.map((id) => KRHttp.fetch({ url: `/api/system/conversationFile/${id}` })
|
|
5890
|
+
.then((r) => r.json())
|
|
5891
|
+
.then((meta) => meta?.data)
|
|
5892
|
+
.catch(() => null)))
|
|
5893
|
+
.then((files) => {
|
|
5894
|
+
msg.conversationFiles = files.filter((f) => f != null);
|
|
5895
|
+
return msg;
|
|
5896
|
+
});
|
|
5897
|
+
})));
|
|
5887
5898
|
};
|
|
5888
5899
|
}
|
|
5889
5900
|
this.load().then((messages) => {
|
|
@@ -6678,10 +6689,18 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6678
6689
|
}
|
|
6679
6690
|
/** Open the shared full-screen previewer for a message image. */
|
|
6680
6691
|
_openImage(img) {
|
|
6681
|
-
|
|
6682
|
-
|
|
6692
|
+
// Prefix the configured backend base URL — a raw fetch of a relative path
|
|
6693
|
+
// would hit the page origin (e.g. the dev server), not the backend.
|
|
6694
|
+
const preview = KRFilePreview.open({
|
|
6695
|
+
src: `${KRHttp.getBaseUrl()}/api/system/conversationFile/${img.conversationFileID}/view`,
|
|
6683
6696
|
name: img.niceName || 'image',
|
|
6684
6697
|
});
|
|
6698
|
+
// The previewer's download button only fires a `download` event — the
|
|
6699
|
+
// consumer performs the actual download. Hit the view endpoint with
|
|
6700
|
+
// `?download=true` (Content-Disposition: attachment) in a new tab.
|
|
6701
|
+
preview.addEventListener('download', () => {
|
|
6702
|
+
window.open(`${KRHttp.getBaseUrl()}/api/system/conversationFile/${img.conversationFileID}/view?download=true`, '_blank');
|
|
6703
|
+
});
|
|
6685
6704
|
}
|
|
6686
6705
|
/** Whether the send button is active: needs text or at least one image. */
|
|
6687
6706
|
_canSend() {
|
|
@@ -7530,7 +7549,7 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
7530
7549
|
@click=${() => this._openImage(img)}
|
|
7531
7550
|
>
|
|
7532
7551
|
<img
|
|
7533
|
-
src="/api/system/conversationFile/${img.conversationFileID}/view"
|
|
7552
|
+
src="${KRHttp.getBaseUrl()}/api/system/conversationFile/${img.conversationFileID}/view"
|
|
7534
7553
|
alt=${img.niceName || ''}
|
|
7535
7554
|
/>
|
|
7536
7555
|
</button>
|
|
@@ -7554,7 +7573,7 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
7554
7573
|
${msg.content ? b `
|
|
7555
7574
|
<button
|
|
7556
7575
|
class="message-copy"
|
|
7557
|
-
title
|
|
7576
|
+
title=${this._copiedIndex === index ? 'Copied' : 'Copy'}
|
|
7558
7577
|
@click=${() => this._handleCopyMessage(msg.content, index)}
|
|
7559
7578
|
>
|
|
7560
7579
|
${this._copiedIndex === index ? b `
|
|
@@ -7568,7 +7587,6 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
7568
7587
|
>
|
|
7569
7588
|
<path d="M20 6 9 17l-5-5" />
|
|
7570
7589
|
</svg>
|
|
7571
|
-
Copied
|
|
7572
7590
|
` : b `
|
|
7573
7591
|
<svg
|
|
7574
7592
|
viewBox="0 0 24 24"
|
|
@@ -7587,7 +7605,6 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
7587
7605
|
/>
|
|
7588
7606
|
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
|
|
7589
7607
|
</svg>
|
|
7590
|
-
Copy
|
|
7591
7608
|
`}
|
|
7592
7609
|
</button>
|
|
7593
7610
|
` : A}
|
|
@@ -7954,7 +7971,7 @@ KRChatbot.styles = i$6 `
|
|
|
7954
7971
|
flex: 1;
|
|
7955
7972
|
display: flex;
|
|
7956
7973
|
flex-direction: column;
|
|
7957
|
-
gap:
|
|
7974
|
+
gap: 36px;
|
|
7958
7975
|
padding: 32px;
|
|
7959
7976
|
width: 100%;
|
|
7960
7977
|
max-width: 768px;
|
|
@@ -7983,6 +8000,17 @@ KRChatbot.styles = i$6 `
|
|
|
7983
8000
|
flex-direction: column;
|
|
7984
8001
|
max-width: 100%;
|
|
7985
8002
|
animation: chatbot-msg-in 0.3s ease-out;
|
|
8003
|
+
/* Reserve room for the copy button INSIDE the message box (so the button is
|
|
8004
|
+
part of the message's hover region — no dead zone to cross), then cancel
|
|
8005
|
+
that space for layout so message spacing is unchanged. */
|
|
8006
|
+
padding-bottom: 30px;
|
|
8007
|
+
margin-bottom: -30px;
|
|
8008
|
+
}
|
|
8009
|
+
|
|
8010
|
+
/* The reserved padding overhangs into the next message; lift the hovered one
|
|
8011
|
+
so its copy button isn't covered by (or stealing hover from) the sibling. */
|
|
8012
|
+
.message:hover {
|
|
8013
|
+
z-index: 1;
|
|
7986
8014
|
}
|
|
7987
8015
|
|
|
7988
8016
|
@keyframes chatbot-msg-in {
|
|
@@ -8031,43 +8059,41 @@ KRChatbot.styles = i$6 `
|
|
|
8031
8059
|
color: #b45309;
|
|
8032
8060
|
}
|
|
8033
8061
|
|
|
8034
|
-
/* Per-message copy button.
|
|
8035
|
-
|
|
8036
|
-
|
|
8062
|
+
/* Per-message copy button. Sits in the message's reserved bottom padding —
|
|
8063
|
+
inside the hover box, so moving the cursor down onto it never leaves the
|
|
8064
|
+
message. Height is reserved (via the message padding) so spacing doesn't
|
|
8065
|
+
jump; only opacity toggles on hover. */
|
|
8037
8066
|
.message-copy {
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8067
|
+
position: absolute;
|
|
8068
|
+
bottom: 0;
|
|
8069
|
+
left: 0;
|
|
8041
8070
|
display: inline-flex;
|
|
8042
8071
|
align-items: center;
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8072
|
+
justify-content: center;
|
|
8073
|
+
width: 26px;
|
|
8074
|
+
height: 26px;
|
|
8075
|
+
padding: 0;
|
|
8046
8076
|
background: none;
|
|
8047
8077
|
border: none;
|
|
8048
8078
|
border-radius: 6px;
|
|
8049
|
-
|
|
8050
|
-
font-size: 12px;
|
|
8051
|
-
color: #64668b;
|
|
8079
|
+
color: #000000;
|
|
8052
8080
|
cursor: pointer;
|
|
8053
8081
|
opacity: 0;
|
|
8054
|
-
pointer-events: none;
|
|
8055
8082
|
transition: opacity 0.15s, background-color 0.15s, color 0.15s;
|
|
8056
8083
|
}
|
|
8057
8084
|
|
|
8058
8085
|
.message--user .message-copy {
|
|
8059
|
-
|
|
8086
|
+
left: auto;
|
|
8087
|
+
right: 0;
|
|
8060
8088
|
}
|
|
8061
8089
|
|
|
8062
8090
|
.message:hover .message-copy,
|
|
8063
8091
|
.message-copy:focus-visible {
|
|
8064
8092
|
opacity: 1;
|
|
8065
|
-
pointer-events: auto;
|
|
8066
8093
|
}
|
|
8067
8094
|
|
|
8068
8095
|
.message-copy:hover {
|
|
8069
8096
|
background: rgba(0, 0, 0, 0.06);
|
|
8070
|
-
color: #1a1a2e;
|
|
8071
8097
|
}
|
|
8072
8098
|
|
|
8073
8099
|
.message-copy svg {
|
|
@@ -8641,6 +8667,7 @@ KRChatbot.styles = i$6 `
|
|
|
8641
8667
|
|
|
8642
8668
|
.message--user .attachments {
|
|
8643
8669
|
justify-content: flex-end;
|
|
8670
|
+
margin-bottom: 24px;
|
|
8644
8671
|
}
|
|
8645
8672
|
|
|
8646
8673
|
.attachment {
|