@kodaris/krubble-app-components 1.0.104 → 1.0.106

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.
@@ -5530,15 +5530,23 @@ var __decorate = (undefined && undefined.__decorate) || function (decorators, ta
5530
5530
  };
5531
5531
  /** Image extensions the chatbot renders as thumbnails (used when MIME is absent). */
5532
5532
  const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
5533
+ /**
5534
+ * Video extensions the picker accepts. The AI cannot watch video — these upload
5535
+ * and store for playback and tool use only, and the backend tells the model so.
5536
+ * Matches what kr-file-preview can play back.
5537
+ */
5538
+ const VIDEO_EXTENSIONS = ['mp4', 'webm', 'ogg', 'mov'];
5533
5539
  /**
5534
5540
  * File extensions the picker accepts. Mirrors what the backend can read: the
5535
5541
  * document/spreadsheet family Bedrock ingests, the plain-text family read as
5536
- * fallback, and the image formats. This is a UX convenience — the backend
5542
+ * fallback, and the image formats. Videos are accepted for upload/storage even
5543
+ * though the model can't read them. This is a UX convenience — the backend
5537
5544
  * accepts anything and just tells the model when a type can't be read.
5538
5545
  */
5539
5546
  const ACCEPTED_FILE_EXTENSIONS = [
5540
5547
  'pdf', 'doc', 'docx', 'xls', 'xlsx', 'csv', 'html', 'md', 'txt', 'json', 'xml',
5541
5548
  ...IMAGE_EXTENSIONS,
5549
+ ...VIDEO_EXTENSIONS,
5542
5550
  ];
5543
5551
  /**
5544
5552
  * AI chatbot component with SSE streaming.
@@ -6852,8 +6860,9 @@ let KRChatbot = class KRChatbot extends i$3 {
6852
6860
  return;
6853
6861
  }
6854
6862
  files.forEach((file) => {
6855
- // Only images get a local preview thumbnail; documents render an icon.
6856
- // Prefer the File's MIME, falling back to the extension when it's absent.
6863
+ // Only images get a local preview thumbnail; documents (and videos, which are
6864
+ // tiles too) render an icon. Prefer the File's MIME, falling back to the
6865
+ // extension when it's absent.
6857
6866
  let previewUrl;
6858
6867
  if (file.type.startsWith('image/') || IMAGE_EXTENSIONS.includes(this._getFileExtension(file.name))) {
6859
6868
  previewUrl = URL.createObjectURL(file);
@@ -6884,22 +6893,25 @@ let KRChatbot = class KRChatbot extends i$3 {
6884
6893
  });
6885
6894
  this._pendingConversationFiles = [];
6886
6895
  }
6887
- /** Open the shared full-screen previewer for a message image. */
6888
- _handleImageOpen(img) {
6896
+ /** Open the shared full-screen previewer for a message attachment (image or video). */
6897
+ _handleFileOpen(file) {
6889
6898
  // Use the local preview if the upload hasn't finished yet; otherwise the
6890
6899
  // backend view URL (prefixed with the base URL — a raw fetch of a relative
6891
6900
  // path would hit the page origin, e.g. the dev server, not the backend).
6892
- const src = img.previewUrl
6893
- || `${KRHttp.getBaseUrl()}/api/system/conversationFile/${img.conversationFileID}/view`;
6901
+ // The previewer picks image vs video playback off the name's extension, so
6902
+ // niceName has to carry it — hence the generic fallback keeps no extension
6903
+ // only when there's no name at all.
6904
+ const src = file.previewUrl
6905
+ || `${KRHttp.getBaseUrl()}/api/system/conversationFile/${file.conversationFileID}/view`;
6894
6906
  const preview = KRFilePreview.open({
6895
6907
  src,
6896
- name: img.niceName || 'image',
6908
+ name: file.niceName || 'file',
6897
6909
  });
6898
6910
  // The previewer's download button only fires a `download` event — the
6899
6911
  // consumer performs the actual download. Hit the view endpoint with
6900
6912
  // `?download=true` (Content-Disposition: attachment) in a new tab.
6901
6913
  preview.addEventListener('download', () => {
6902
- window.open(`${KRHttp.getBaseUrl()}/api/system/conversationFile/${img.conversationFileID}/view?download=true`, '_blank');
6914
+ window.open(`${KRHttp.getBaseUrl()}/api/system/conversationFile/${file.conversationFileID}/view?download=true`, '_blank');
6903
6915
  });
6904
6916
  }
6905
6917
  _handleSubmit() {
@@ -7834,15 +7846,18 @@ let KRChatbot = class KRChatbot extends i$3 {
7834
7846
  if (file.mimeType) {
7835
7847
  isImage = file.mimeType.startsWith('image/');
7836
7848
  }
7837
- // Images open in the previewer; documents just show a tile
7838
- // (the previewer is image-only).
7849
+ // An image shows its thumbnail; everything else shows a
7850
+ // file-type tile. Both open the previewer on click — it renders
7851
+ // images, video, PDFs, and text inline, and shows a download
7852
+ // tile for the rest (Office formats), so a click always does
7853
+ // something useful.
7839
7854
  if (isImage) {
7840
7855
  return b `
7841
7856
  <button
7842
7857
  class="attachment"
7843
7858
  type="button"
7844
7859
  title=${file.niceName || 'View image'}
7845
- @click=${() => this._handleImageOpen(file)}
7860
+ @click=${() => this._handleFileOpen(file)}
7846
7861
  >
7847
7862
  <img
7848
7863
  src=${file.previewUrl || `${KRHttp.getBaseUrl()}/api/system/conversationFile/${file.conversationFileID}/view`}
@@ -7852,13 +7867,15 @@ let KRChatbot = class KRChatbot extends i$3 {
7852
7867
  `;
7853
7868
  }
7854
7869
  return b `
7855
- <div
7856
- class="attachment attachment--doc"
7870
+ <button
7871
+ class="attachment attachment--doc attachment--openable"
7872
+ type="button"
7857
7873
  title=${fileName}
7874
+ @click=${() => this._handleFileOpen(file)}
7858
7875
  >
7859
7876
  <span class="attachment__type">${this._getFileExtension(fileName) || 'File'}</span>
7860
7877
  <span class="attachment__name">${fileName}</span>
7861
- </div>
7878
+ </button>
7862
7879
  `;
7863
7880
  })}
7864
7881
  </div>
@@ -8409,10 +8426,14 @@ KRChatbot.styles = i$6 `
8409
8426
  gap: 24px;
8410
8427
  }
8411
8428
 
8429
+ /* anywhere, NOT break-word: both break a long unbreakable run (a pasted URL) for
8430
+ layout, but only anywhere also shrinks the element's intrinsic min-content width.
8431
+ With break-word the URL still reports its full unbroken width as the minimum,
8432
+ which sizes this shrink-to-fit bubble past .messages-inner's 768px cap and
8433
+ overflows the page horizontally. */
8412
8434
  .message-content {
8413
8435
  line-height: 1.7;
8414
- word-wrap: break-word;
8415
- overflow-wrap: break-word;
8436
+ overflow-wrap: anywhere;
8416
8437
  }
8417
8438
 
8418
8439
  .message--user .message-content {
@@ -9130,15 +9151,22 @@ KRChatbot.styles = i$6 `
9130
9151
  display: block;
9131
9152
  }
9132
9153
 
9133
- /* Non-image attachment in a sent message — file-type label above the filename
9134
- (the previewer is image-only, so this isn't clickable). */
9154
+ /* Non-image attachment in a sent message — file-type label above the filename. */
9135
9155
  .attachment--doc {
9136
9156
  display: flex;
9137
9157
  flex-direction: column;
9138
9158
  padding: 16px 14px;
9139
9159
  box-sizing: border-box;
9140
9160
  text-align: left;
9141
- cursor: default;
9161
+ }
9162
+
9163
+ /* Opens the previewer on click — same affordance as the composer's doc chip. */
9164
+ .attachment--openable {
9165
+ cursor: pointer;
9166
+ }
9167
+
9168
+ .attachment--openable:hover {
9169
+ background: #dfdddd;
9142
9170
  }
9143
9171
 
9144
9172
  .attachment__type {