@coffer-org/plugin-webchat 2.2.3 → 2.2.5

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.
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import { createContext, createElement, forwardRef, memo, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  import * as ReactDOM from "react-dom";
7
- import { Link, useLocation } from "react-router-dom";
7
+ import { useLocation, useNavigate } from "react-router-dom";
8
8
  //#region \0rolldown/runtime.js
9
9
  var __create = Object.create;
10
10
  var __defProp = Object.defineProperty;
@@ -658,6 +658,19 @@ var Plus = createLucideIcon("plus", [["path", {
658
658
  * This source code is licensed under the ISC license.
659
659
  * See the LICENSE file in the root directory of this source tree.
660
660
  */
661
+ var RotateCcw = createLucideIcon("rotate-ccw", [["path", {
662
+ d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",
663
+ key: "1357e3"
664
+ }], ["path", {
665
+ d: "M3 3v5h5",
666
+ key: "1xhq8a"
667
+ }]]);
668
+ /**
669
+ * @license lucide-react v1.24.0 - ISC
670
+ *
671
+ * This source code is licensed under the ISC license.
672
+ * See the LICENSE file in the root directory of this source tree.
673
+ */
661
674
  var Send = createLucideIcon("send", [["path", {
662
675
  d: "M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",
663
676
  key: "1ffxy3"
@@ -29209,11 +29222,17 @@ function ChatMarkdown({ text, className }) {
29209
29222
  }
29210
29223
  function ChatLink({ href, children }) {
29211
29224
  const onNavigate = useChatNav();
29225
+ const navigate = useNavigate();
29212
29226
  const routes = [...getSiteLinks(), ...getPluginRoutes().map((r) => ({ pattern: `/${r.path}` }))];
29213
29227
  const kind = classifyHref(href ?? "", window.location.origin, routes, getSiteShelves());
29214
- if (kind.kind === "internal") return /* @__PURE__ */ jsx(Link, {
29215
- to: kind.to,
29216
- onClick: onNavigate,
29228
+ if (kind.kind === "internal") return /* @__PURE__ */ jsx("a", {
29229
+ href: kind.to,
29230
+ onClick: (event) => {
29231
+ if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
29232
+ event.preventDefault();
29233
+ onNavigate();
29234
+ navigate(kind.to);
29235
+ },
29217
29236
  children
29218
29237
  });
29219
29238
  if (kind.kind === "external") return /* @__PURE__ */ jsx("a", {
@@ -29291,7 +29310,7 @@ var Bubble = memo(function Bubble({ role, text, reasoning, attachments }) {
29291
29310
  });
29292
29311
  //#endregion
29293
29312
  //#region src/ui/ChatComposer.tsx
29294
- function ChatComposer({ streaming, onSend, onStop, attachments, uploading, uploadError, uploadProgress, onPickFiles, onRemoveAttachment }) {
29313
+ function ChatComposer({ streaming, onSend, onStop, attachments, uploading, uploadError, uploadProgress, canRetryUpload, onRetryUpload, onPickFiles, onRemoveAttachment }) {
29295
29314
  const { t } = useTranslation();
29296
29315
  const [text, setText] = useState("");
29297
29316
  function submit() {
@@ -29350,9 +29369,21 @@ function ChatComposer({ streaming, onSend, onStop, attachments, uploading, uploa
29350
29369
  })
29351
29370
  ]
29352
29371
  }),
29353
- uploadError && /* @__PURE__ */ jsx("span", {
29354
- className: "text-xs text-danger",
29355
- children: t(uploadError)
29372
+ uploadError && /* @__PURE__ */ jsxs("div", {
29373
+ className: "flex min-w-0 flex-1 items-center gap-2 text-xs text-danger",
29374
+ children: [/* @__PURE__ */ jsx("span", {
29375
+ className: "min-w-0 flex-1",
29376
+ children: t(uploadError)
29377
+ }), canRetryUpload && /* @__PURE__ */ jsxs("button", {
29378
+ type: "button",
29379
+ className: "inline-flex shrink-0 items-center gap-1 rounded px-1.5 py-0.5 font-medium text-accent hover:bg-elevated",
29380
+ onClick: onRetryUpload,
29381
+ children: [
29382
+ /* @__PURE__ */ jsx(RotateCcw, { size: 12 }),
29383
+ " ",
29384
+ t("webchat.retryUpload")
29385
+ ]
29386
+ })]
29356
29387
  })
29357
29388
  ]
29358
29389
  }), /* @__PURE__ */ jsxs("div", {
@@ -29503,6 +29534,7 @@ function ChatWidget() {
29503
29534
  const [uploading, setUploading] = useState(false);
29504
29535
  const [uploadProgress, setUploadProgress] = useState(0);
29505
29536
  const [uploadError, setUploadError] = useState(null);
29537
+ const [retryFiles, setRetryFiles] = useState([]);
29506
29538
  const wide = useMinWidth("sm", 640);
29507
29539
  const wideNav = useMinWidth("nav", 768);
29508
29540
  const onChatNavigate = useCallback(() => {
@@ -29539,14 +29571,17 @@ function ChatWidget() {
29539
29571
  chat.newConversation();
29540
29572
  setAttachments([]);
29541
29573
  setUploadError(null);
29574
+ setRetryFiles([]);
29542
29575
  setThreadsOpen(false);
29543
29576
  }
29544
29577
  const pickFiles = useCallback(async (files) => {
29545
29578
  if (!files.length) return;
29546
29579
  setUploadError(null);
29580
+ setRetryFiles([]);
29547
29581
  setUploading(true);
29548
29582
  setUploadProgress(0);
29549
29583
  const added = [];
29584
+ const failedFiles = [];
29550
29585
  let error = null;
29551
29586
  for (const file of files) {
29552
29587
  if (file.size > MAX_CHAT_UPLOAD_BYTES) {
@@ -29560,16 +29595,24 @@ function ChatWidget() {
29560
29595
  ...rec,
29561
29596
  label: file.name
29562
29597
  });
29563
- else error ??= "webchat.uploadFailed";
29598
+ else {
29599
+ failedFiles.push(file);
29600
+ error ??= "webchat.uploadFailed";
29601
+ }
29564
29602
  } catch {
29603
+ failedFiles.push(file);
29565
29604
  error ??= "webchat.uploadFailed";
29566
29605
  }
29567
29606
  }
29568
29607
  if (added.length) setAttachments((prev) => [...prev, ...added]);
29569
29608
  setUploading(false);
29570
29609
  setUploadProgress(0);
29610
+ setRetryFiles(failedFiles);
29571
29611
  if (error) setUploadError(error);
29572
29612
  }, []);
29613
+ const retryUploads = useCallback(() => {
29614
+ if (retryFiles.length) pickFiles(retryFiles);
29615
+ }, [pickFiles, retryFiles]);
29573
29616
  const hasConversation = chat.messages.length > 0 || chat.pending !== null;
29574
29617
  const header = /* @__PURE__ */ jsxs("div", {
29575
29618
  className: "flex shrink-0 items-center justify-between border-b border-border px-3 py-2",
@@ -29628,6 +29671,8 @@ function ChatWidget() {
29628
29671
  uploading,
29629
29672
  uploadProgress,
29630
29673
  uploadError,
29674
+ canRetryUpload: retryFiles.length > 0 && !uploading,
29675
+ onRetryUpload: retryUploads,
29631
29676
  onPickFiles: (files) => void pickFiles(Array.from(files)),
29632
29677
  onRemoveAttachment: (index) => setAttachments((prev) => prev.filter((_, i) => i !== index)),
29633
29678
  onSend: (text, refs) => {
@@ -29635,6 +29680,7 @@ function ChatWidget() {
29635
29680
  if (accepted) {
29636
29681
  setAttachments([]);
29637
29682
  setUploadError(null);
29683
+ setRetryFiles([]);
29638
29684
  }
29639
29685
  return accepted;
29640
29686
  },
@@ -29679,6 +29725,7 @@ function ChatWidget() {
29679
29725
  chat.open(id);
29680
29726
  setAttachments([]);
29681
29727
  setUploadError(null);
29728
+ setRetryFiles([]);
29682
29729
  setThreadsOpen(false);
29683
29730
  },
29684
29731
  onNew: startNew,
package/dist/web.js CHANGED
@@ -11,7 +11,7 @@ import { definePluginUI } from "@coffer-org/web-sdk";
11
11
  var ui_default = definePluginUI({ slots: [{
12
12
  slot: "overlay",
13
13
  id: "webchat",
14
- load: () => import("./ChatWidget-1G0ZxQH2.js")
14
+ load: () => import("./ChatWidget-By7bmS3U.js")
15
15
  }] });
16
16
  //#endregion
17
17
  export { ui_default as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffer-org/plugin-webchat",
3
- "version": "2.2.3",
3
+ "version": "2.2.5",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=24"
@@ -26,9 +26,9 @@
26
26
  "test:ui": "vitest run --root ."
27
27
  },
28
28
  "dependencies": {
29
- "@coffer-org/plugin-orchestrator": "^2.3.0",
29
+ "@coffer-org/plugin-orchestrator": "^2.3.2",
30
30
  "@coffer-org/sdk": "^2.1.2",
31
- "@coffer-org/server": "^2.2.2",
31
+ "@coffer-org/server": "^2.5.0",
32
32
  "react-markdown": "^10.1.0",
33
33
  "remark-gfm": "^4.0.1"
34
34
  },