@useknest/widget-react 0.1.0-beta.12 → 0.1.0-beta.13
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/README.md +24 -5
- package/dist/ChatWidget.d.ts +4 -2
- package/dist/ChatWidget.d.ts.map +1 -1
- package/dist/index.js +178 -176
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -34,11 +34,30 @@ function App() {
|
|
|
34
34
|
|
|
35
35
|
### ChatWidget
|
|
36
36
|
|
|
37
|
-
| Prop | Type | Required | Default | Description
|
|
38
|
-
| ------------------- | ---------------------- | -------- | ---------- |
|
|
39
|
-
| `publishableApiKey` | `string` | Yes | - | Your project's publishable API key
|
|
40
|
-
| `mode` | `'inline' \| 'bubble'` | No | `'inline'` | Display mode: inline or floating bubble button
|
|
41
|
-
| `defaultOpen` | `boolean` | No | `false` | Whether the chat starts open (only applies to bubble mode)
|
|
37
|
+
| Prop | Type | Required | Default | Description |
|
|
38
|
+
| ------------------- | ---------------------- | -------- | ---------- | -------------------------------------------------------------------- |
|
|
39
|
+
| `publishableApiKey` | `string` | Yes | - | Your project's publishable API key |
|
|
40
|
+
| `mode` | `'inline' \| 'bubble'` | No | `'inline'` | Display mode: inline or floating bubble button |
|
|
41
|
+
| `defaultOpen` | `boolean` | No | `false` | Whether the chat starts open (only applies to bubble mode) |
|
|
42
|
+
| `user` | `WidgetUser` | No | - | Identifies the logged-in user; requires at least `id` or `email` |
|
|
43
|
+
|
|
44
|
+
#### `WidgetUser`
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
interface WidgetUser {
|
|
48
|
+
id?: string; // Your system's user ID (cross-device dedup key)
|
|
49
|
+
email?: string;
|
|
50
|
+
fullName?: string;
|
|
51
|
+
metadata?: Record<string, unknown>; // Custom attributes (e.g. plan, company)
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
<ChatWidget
|
|
57
|
+
publishableApiKey="pk_..."
|
|
58
|
+
user={{ id: currentUser.id, email: currentUser.email, fullName: currentUser.name }}
|
|
59
|
+
/>
|
|
60
|
+
```
|
|
42
61
|
|
|
43
62
|
## Features
|
|
44
63
|
|
package/dist/ChatWidget.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WidgetMode } from '@useknest/widget-core';
|
|
1
|
+
import { WidgetMode, WidgetUser } from '@useknest/widget-core';
|
|
2
2
|
/** Internal config for testing/development - not part of the public API. */
|
|
3
3
|
export interface InternalConfig {
|
|
4
4
|
baseUrl?: string;
|
|
@@ -11,8 +11,10 @@ export interface ChatWidgetProps {
|
|
|
11
11
|
mode?: WidgetMode;
|
|
12
12
|
/** Whether to auto-open the chat in bubble mode. Defaults to false. */
|
|
13
13
|
defaultOpen?: boolean;
|
|
14
|
+
/** Identifies the logged-in user on the customer's platform. Requires at least id or email. */
|
|
15
|
+
user?: WidgetUser;
|
|
14
16
|
/** Internal config for testing/development - not part of the public API. */
|
|
15
17
|
_internal?: InternalConfig;
|
|
16
18
|
}
|
|
17
|
-
export declare function ChatWidget({ publishableApiKey, mode, defaultOpen, _internal }: ChatWidgetProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare function ChatWidget({ publishableApiKey, mode, defaultOpen, user, _internal }: ChatWidgetProps): import("react/jsx-runtime").JSX.Element;
|
|
18
20
|
//# sourceMappingURL=ChatWidget.d.ts.map
|
package/dist/ChatWidget.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../src/ChatWidget.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAMX,UAAU,EACV,MAAM,uBAAuB,CAAC;AAK/B,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qGAAqG;IACrG,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,uEAAuE;IACvE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,EAC1B,iBAAiB,EACjB,IAAe,EACf,WAAmB,EACnB,SAAS,EACT,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../src/ChatWidget.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAMX,UAAU,EACV,UAAU,EACV,MAAM,uBAAuB,CAAC;AAK/B,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qGAAqG;IACrG,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,uEAAuE;IACvE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+FAA+F;IAC/F,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,EAC1B,iBAAiB,EACjB,IAAe,EACf,WAAmB,EACnB,IAAI,EACJ,SAAS,EACT,EAAE,eAAe,2CA2iBjB"}
|
package/dist/index.js
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
1
|
(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".knest-chat-card{display:flex;flex-direction:column;height:100%;background:#fff;color:#374151;border-radius:1rem;box-shadow:0 10px 15px -3px #0000001a;overflow:hidden;font-family:system-ui,-apple-system,sans-serif}.knest-loading-container{display:flex;align-items:center;justify-content:center;height:100%;background:linear-gradient(135deg,#fdfbf7,#fff)}.knest-loading-content{display:flex;flex-direction:column;align-items:center;gap:1.5rem}.knest-spinner-ring{width:3rem;height:3rem;border:3px solid #f3f4f6;border-top-color:#3b82f6;border-radius:50%;animation:knest-spin .8s linear infinite}@keyframes knest-spin{to{transform:rotate(360deg)}}.knest-loading-text{font-size:.875rem;font-weight:500;color:#6b7280;margin:0}.knest-error-container{display:flex;align-items:center;justify-content:center;height:100%;background:linear-gradient(135deg,#fef2f2,#fff);padding:2rem}.knest-error-content{text-align:center;max-width:300px}.knest-error-text{font-size:.875rem;color:#991b1b;margin:0;line-height:1.5}.knest-header{border-bottom:1px solid #f3f4f6;padding:1rem}.knest-header-content{display:flex;align-items:center;gap:.75rem}.knest-avatar-img{width:2rem;height:2rem;object-fit:cover;border-radius:.25rem}.knest-header h2{font-size:1.125rem;font-weight:600;color:#111827;margin:0 0 .25rem}.knest-badge{display:inline-block;padding:.25rem .5rem;border-radius:9999px;font-size:.75rem;font-weight:500;color:#fff}.knest-messages-container{flex:1;overflow-y:auto}.knest-separator{margin:0 1.5rem;border-bottom:1px solid #e5e7eb}.knest-message-wrapper{display:flex;flex-direction:column}.knest-message{display:flex;gap:1rem;padding:1.25rem 1.5rem;align-items:center}.knest-message-avatar{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;flex-shrink:0}.knest-message-avatar .knest-avatar-img{width:100%;height:100%;border-radius:.25rem;object-fit:cover}.knest-user-avatar{width:2rem;height:2rem;border-radius:.25rem;display:flex;align-items:center;justify-content:center;color:#fff;font-size:.875rem;font-weight:500}.knest-message-content{flex:1;min-width:0}.knest-message-content p{margin:0 0 .5rem;font-size:.875rem;line-height:1.625;color:inherit;word-wrap:break-word}.knest-message-content p:last-child{margin-bottom:0}.knest-message-content code{background-color:#f3f4f6;padding:.125rem .375rem;border-radius:.25rem;font-family:ui-monospace,monospace;font-size:.8125rem;color:#ef4444}.knest-message-content pre{background-color:#1f2937;color:#f9fafb;padding:12px;border-radius:6px;overflow-x:auto;margin:8px 0}.knest-message-content pre code{background-color:transparent;padding:0;color:inherit;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.8125rem;line-height:1.5}.knest-message-content .token.keyword,.knest-message-content .token.builtin,.knest-message-content .token.tag{color:#ff7b72}.knest-message-content .token.string,.knest-message-content .token.attr-value{color:#a5d6ff}.knest-message-content .token.number,.knest-message-content .token.boolean{color:#79c0ff}.knest-message-content .token.function,.knest-message-content .token.class-name{color:#d2a8ff}.knest-message-content .token.comment{color:#8b949e;font-style:italic}.knest-message-content .token.variable,.knest-message-content .token.property{color:#ffa657}.knest-message-content .token.operator,.knest-message-content .token.punctuation{color:#c9d1d9}.knest-message-content a{color:inherit;text-decoration:underline}.knest-message-content ul,.knest-message-content ol{margin:8px 0;padding-left:24px}.knest-message-content li{margin:4px 0;color:inherit}.knest-message-content strong{font-weight:600;color:inherit}.knest-message-content em{font-style:italic}.knest-loading{display:flex;gap:.25rem;align-items:center}.knest-dot{width:.5rem;height:.5rem;background:#9ca3af;border-radius:50%;animation:knest-bounce 1.4s infinite ease-in-out both}.knest-dot:nth-child(2){animation-delay:.16s}.knest-dot:nth-child(3){animation-delay:.32s}@keyframes knest-bounce{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}.knest-sources{margin-top:.75rem}.knest-sources-label{font-size:.75rem;font-weight:500;color:#6b7280;margin-bottom:.5rem}.knest-source-item{display:flex;gap:.5rem;padding:.5rem .75rem;margin-bottom:.25rem;border:1px solid #e5e7eb;border-radius:.375rem;background:#f9fafb;text-decoration:none;transition:all .15s}.knest-source-item:hover{border-color:#d1d5db;background:#f3f4f6}.knest-source-icon{width:1rem;height:1rem;color:#6b7280;flex-shrink:0}.knest-source-text{flex:1;min-width:0}.knest-source-breadcrumb{font-size:.75rem;color:#6b7280;margin-bottom:.125rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.knest-source-title{font-size:.875rem;font-weight:500;color:#374151;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.knest-examples{border-top:1px solid #e5e7eb;padding:1.25rem 1.5rem}.knest-examples h3{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:#6b7280;margin:0 0 1rem}.knest-example-btn{width:100%;padding:.75rem;margin-bottom:.75rem;border:1px solid #e5e7eb;border-radius:.5rem;background:#fff;text-align:left;font-size:.875rem;color:#374151;cursor:pointer;transition:background .15s}.knest-example-btn:hover{background:#f9fafb}.knest-input-section{border-top:1px solid #f3f4f6;padding:1rem}.knest-input-wrapper{display:flex;align-items:center;gap:.5rem}.knest-input-field{flex:1;padding:.75rem 1rem;border:1px solid #e5e7eb;border-radius:.5rem;background:#f9fafb;font-size:.875rem;color:#374151;outline:none}.knest-input-field:focus{background:#fff;border-color:#d1d5db}.knest-input-field:disabled{opacity:.5}.knest-attach-btn{width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:center;border:none;border-radius:.5rem;background:#e5e7eb;color:#6b7280;cursor:pointer;transition:background .15s;flex-shrink:0}.knest-attach-btn:hover:not(:disabled){background:#d1d5db}.knest-attach-btn:disabled{opacity:.4;cursor:not-allowed}.knest-attach-icon{width:1rem;height:1rem}.knest-file-preview{display:flex;flex-wrap:wrap;gap:.375rem;margin-bottom:.5rem}.knest-file-chip{display:inline-flex;align-items:center;gap:.25rem;padding:.25rem .5rem;background:#f3f4f6;border:1px solid #e5e7eb;border-radius:9999px;font-size:.75rem;color:#374151;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.knest-chip-remove{background:none;border:none;padding:0;font-size:1rem;line-height:1;color:#9ca3af;cursor:pointer;flex-shrink:0}.knest-chip-remove:hover{color:#374151}.knest-attach-error{font-size:.75rem;color:#dc2626;margin:0 0 .375rem}.knest-send-btn{width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:center;border:none;border-radius:.5rem;background:#e5e7eb;color:#6b7280;cursor:pointer;transition:background .15s}.knest-send-btn:hover:not(:disabled){background:#d1d5db}.knest-send-btn:disabled{opacity:.5;cursor:not-allowed}.knest-send-icon{width:1rem;height:1rem}.knest-attachments{display:flex;flex-direction:column;gap:.5rem;margin-top:.5rem}.knest-attachment-image-link{display:inline-block}.knest-attachment-image{max-width:240px;border-radius:.5rem;display:block}.knest-attachment-file{display:inline-flex;align-items:center;gap:.375rem;padding:.375rem .625rem;border:1px solid #e5e7eb;border-radius:9999px;background:#f9fafb;text-decoration:none;font-size:.8125rem;color:#374151;transition:background .15s}.knest-attachment-file:hover:not(.knest-attachment-disabled){background:#f3f4f6}.knest-attachment-disabled{opacity:.5;pointer-events:none}.knest-attachment-file-icon{width:.875rem;height:.875rem;color:#6b7280;flex-shrink:0}.knest-attachment-file-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:160px}.knest-attachment-file-size{color:#9ca3af;flex-shrink:0}.knest-reset-row{display:flex;justify-content:center;margin-top:.5rem}.knest-reset-btn{background:none;border:none;padding:0;font-size:.75rem;color:#9ca3af;cursor:pointer;transition:color .15s}.knest-reset-btn:hover{color:#6b7280}.knest-footer{margin-top:.75rem;display:flex;justify-content:center}.knest-powered-by{display:flex;align-items:center;gap:.125rem;font-size:.75rem;color:#6b7280;text-decoration:none;transition:color .15s}.knest-powered-by:hover{color:#374151;text-decoration:underline}.knest-bubble-container{position:fixed;bottom:24px;right:24px;z-index:9999;display:flex;flex-direction:column;align-items:flex-end;gap:16px;font-family:system-ui,-apple-system,sans-serif}.knest-bubble-button{width:56px;height:56px;border-radius:50%;border:none;color:#fff;cursor:pointer;box-shadow:0 4px 12px #00000026;display:flex;align-items:center;justify-content:center;transition:transform .2s,box-shadow .2s}.knest-bubble-button:hover{transform:scale(1.05);box-shadow:0 6px 16px #0003}.knest-bubble-spinner{animation:knest-spin 1s linear infinite}.knest-bubble-panel{width:380px;height:520px;max-width:calc(100vw - 48px);max-height:calc(100vh - 100px);border-radius:1rem;border:1px solid rgba(0,0,0,.1);box-shadow:0 10px 15px -3px #0000001a;overflow:hidden}.knest-bubble-panel .knest-chat-card{height:100%}@media (max-width: 440px){.knest-bubble-container{bottom:16px;right:16px}.knest-bubble-panel{width:calc(100vw - 32px);height:calc(100vh - 100px)}}")),document.head.appendChild(e)}}catch(t){console.error("vite-plugin-css-injected-by-js",t)}})();
|
|
2
2
|
import { jsx as e, jsxs as l } from "react/jsx-runtime";
|
|
3
|
-
import { useState as
|
|
4
|
-
import { fetchSignedUrl as
|
|
5
|
-
function
|
|
3
|
+
import { useState as d, useEffect as U, useRef as V } from "react";
|
|
4
|
+
import { fetchSignedUrl as oe, formatContent as le, DEFAULT_BRAND_COLOR as q, isImageType as ce, formatFileSize as ie, DEFAULT_AVATAR_URL as de, DEFAULT_EXAMPLE_QUESTIONS as he, initWidgetSentry as X, PUBLIC_SUPABASE_URL as ue, PUBLIC_SUPABASE_ANON_KEY as me, initWidgetAuth as fe, saveChatStateDebounced as ke, subscribeToThread as ge, AUTH_ERROR_MESSAGE as ve, ACCEPTED_FILE_TYPES_STRING as pe, fetchWidgetConfig as Ce, loadChatState as be, DEFAULT_WELCOME_MESSAGE as Y, validateAttachment as Ne, MAX_ATTACHMENTS_PER_MESSAGE as Ee, uploadAttachment as Le, captureWidgetException as $, streamChatMessage as we, clearChatState as Me } from "@useknest/widget-core";
|
|
5
|
+
function Ue({
|
|
6
6
|
message: r,
|
|
7
|
-
isLoading:
|
|
8
|
-
avatarUrl:
|
|
9
|
-
brandColor:
|
|
10
|
-
showAvatar:
|
|
11
|
-
publishableApiKey:
|
|
12
|
-
baseUrl:
|
|
7
|
+
isLoading: T = !1,
|
|
8
|
+
avatarUrl: W = "/default-avatar.svg",
|
|
9
|
+
brandColor: y = q,
|
|
10
|
+
showAvatar: f = !0,
|
|
11
|
+
publishableApiKey: p,
|
|
12
|
+
baseUrl: w
|
|
13
13
|
}) {
|
|
14
|
-
const [
|
|
14
|
+
const [C, x] = d(!1), [A, _] = d({});
|
|
15
15
|
U(() => {
|
|
16
|
-
if (!r.attachments?.length || !
|
|
17
|
-
const
|
|
18
|
-
(o) => o.storagePath && !o.url && !
|
|
16
|
+
if (!r.attachments?.length || !p) return;
|
|
17
|
+
const n = r.attachments.filter(
|
|
18
|
+
(o) => o.storagePath && !o.url && !A[o.storagePath]
|
|
19
19
|
);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const c = await
|
|
23
|
-
publishableApiKey:
|
|
20
|
+
n.length !== 0 && Promise.all(
|
|
21
|
+
n.map(async (o) => {
|
|
22
|
+
const c = await oe({
|
|
23
|
+
publishableApiKey: p,
|
|
24
24
|
storagePath: o.storagePath,
|
|
25
|
-
baseUrl:
|
|
25
|
+
baseUrl: w
|
|
26
26
|
});
|
|
27
27
|
return { storagePath: o.storagePath, url: c };
|
|
28
28
|
})
|
|
29
29
|
).then((o) => {
|
|
30
30
|
const c = {};
|
|
31
|
-
for (const { storagePath:
|
|
32
|
-
|
|
33
|
-
Object.keys(c).length > 0 &&
|
|
31
|
+
for (const { storagePath: k, url: L } of o)
|
|
32
|
+
L && (c[k] = L);
|
|
33
|
+
Object.keys(c).length > 0 && _((k) => ({ ...k, ...c }));
|
|
34
34
|
});
|
|
35
|
-
}, [r.attachments,
|
|
36
|
-
const
|
|
35
|
+
}, [r.attachments, p, w]);
|
|
36
|
+
const E = (n) => n.url || (n.storagePath ? A[n.storagePath] : void 0), B = () => x(!0), u = r.content ? le(r.content) : "";
|
|
37
37
|
return /* @__PURE__ */ e("div", { className: "knest-message-wrapper", children: /* @__PURE__ */ l("div", { className: "knest-message", children: [
|
|
38
|
-
|
|
38
|
+
f && /* @__PURE__ */ e("div", { className: "knest-message-avatar", children: r.role === "assistant" ? C ? /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: y }, children: "AI" }) : /* @__PURE__ */ e(
|
|
39
39
|
"img",
|
|
40
40
|
{
|
|
41
|
-
src:
|
|
41
|
+
src: W,
|
|
42
42
|
alt: "Avatar",
|
|
43
43
|
className: "knest-avatar-img",
|
|
44
|
-
onError:
|
|
44
|
+
onError: B
|
|
45
45
|
}
|
|
46
|
-
) : /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor:
|
|
46
|
+
) : /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: y }, children: "U" }) }),
|
|
47
47
|
/* @__PURE__ */ l("div", { className: "knest-message-content", children: [
|
|
48
|
-
!r.content &&
|
|
48
|
+
!r.content && T && r.role === "assistant" ? /* @__PURE__ */ l("div", { className: "knest-loading", children: [
|
|
49
49
|
/* @__PURE__ */ e("div", { className: "knest-dot" }),
|
|
50
50
|
/* @__PURE__ */ e("div", { className: "knest-dot" }),
|
|
51
51
|
/* @__PURE__ */ e("div", { className: "knest-dot" })
|
|
52
|
-
] }) : /* @__PURE__ */ e("div", { dangerouslySetInnerHTML: { __html:
|
|
53
|
-
r.attachments && r.attachments.length > 0 && /* @__PURE__ */ e("div", { className: "knest-attachments", children: r.attachments.map((
|
|
54
|
-
const c =
|
|
55
|
-
return
|
|
52
|
+
] }) : /* @__PURE__ */ e("div", { dangerouslySetInnerHTML: { __html: u } }),
|
|
53
|
+
r.attachments && r.attachments.length > 0 && /* @__PURE__ */ e("div", { className: "knest-attachments", children: r.attachments.map((n, o) => {
|
|
54
|
+
const c = E(n);
|
|
55
|
+
return ce(n.fileType) ? c ? /* @__PURE__ */ e(
|
|
56
56
|
"a",
|
|
57
57
|
{
|
|
58
58
|
href: c,
|
|
59
59
|
target: "_blank",
|
|
60
60
|
rel: "noopener noreferrer",
|
|
61
61
|
className: "knest-attachment-image-link",
|
|
62
|
-
children: /* @__PURE__ */ e("img", { src: c, alt:
|
|
62
|
+
children: /* @__PURE__ */ e("img", { src: c, alt: n.fileName, className: "knest-attachment-image" })
|
|
63
63
|
},
|
|
64
64
|
o
|
|
65
65
|
) : null : /* @__PURE__ */ l(
|
|
@@ -88,8 +88,8 @@ function Me({
|
|
|
88
88
|
)
|
|
89
89
|
}
|
|
90
90
|
),
|
|
91
|
-
/* @__PURE__ */ e("span", { className: "knest-attachment-file-name", children:
|
|
92
|
-
/* @__PURE__ */ e("span", { className: "knest-attachment-file-size", children:
|
|
91
|
+
/* @__PURE__ */ e("span", { className: "knest-attachment-file-name", children: n.fileName }),
|
|
92
|
+
/* @__PURE__ */ e("span", { className: "knest-attachment-file-size", children: ie(n.fileSize) })
|
|
93
93
|
]
|
|
94
94
|
},
|
|
95
95
|
o
|
|
@@ -97,10 +97,10 @@ function Me({
|
|
|
97
97
|
}) }),
|
|
98
98
|
r.sources && r.sources.length > 0 && /* @__PURE__ */ l("div", { className: "knest-sources", children: [
|
|
99
99
|
/* @__PURE__ */ e("div", { className: "knest-sources-label", children: "Sources" }),
|
|
100
|
-
r.sources.slice(0, 1).map((
|
|
100
|
+
r.sources.slice(0, 1).map((n, o) => /* @__PURE__ */ l(
|
|
101
101
|
"a",
|
|
102
102
|
{
|
|
103
|
-
href:
|
|
103
|
+
href: n.url,
|
|
104
104
|
target: "_blank",
|
|
105
105
|
rel: "noopener noreferrer",
|
|
106
106
|
className: "knest-source-item",
|
|
@@ -124,8 +124,8 @@ function Me({
|
|
|
124
124
|
}
|
|
125
125
|
),
|
|
126
126
|
/* @__PURE__ */ l("div", { className: "knest-source-text", children: [
|
|
127
|
-
|
|
128
|
-
/* @__PURE__ */ e("div", { className: "knest-source-title", children:
|
|
127
|
+
n.breadcrumb && /* @__PURE__ */ e("div", { className: "knest-source-breadcrumb", children: n.breadcrumb }),
|
|
128
|
+
/* @__PURE__ */ e("div", { className: "knest-source-title", children: n.title })
|
|
129
129
|
] })
|
|
130
130
|
]
|
|
131
131
|
},
|
|
@@ -135,249 +135,251 @@ function Me({
|
|
|
135
135
|
] })
|
|
136
136
|
] }) });
|
|
137
137
|
}
|
|
138
|
-
function
|
|
138
|
+
function Se({
|
|
139
139
|
publishableApiKey: r,
|
|
140
|
-
mode:
|
|
141
|
-
defaultOpen:
|
|
142
|
-
|
|
140
|
+
mode: T = "inline",
|
|
141
|
+
defaultOpen: W = !1,
|
|
142
|
+
user: y,
|
|
143
|
+
_internal: f
|
|
143
144
|
}) {
|
|
144
|
-
const [
|
|
145
|
+
const [p, w] = d(null), [C, x] = d(!0), [A, _] = d(null), [E, B] = d(!1), [u, n] = d([]), [o, c] = d(""), [k, L] = d(!1), [h, R] = d(void 0), [S, J] = d(W), [I, P] = d([]), [j, D] = d(!1), [G, M] = d(null), O = V(null), H = V(null), Z = p?.avatarUrl || de, K = p?.exampleQuestions || he, F = p?.brandColor || q;
|
|
145
146
|
U(() => {
|
|
146
|
-
typeof requestIdleCallback < "u" ? requestIdleCallback(() =>
|
|
147
|
-
const t =
|
|
147
|
+
typeof requestIdleCallback < "u" ? requestIdleCallback(() => X()) : setTimeout(() => X(), 0);
|
|
148
|
+
const t = f?.supabaseUrl || ue, s = f?.supabaseAnonKey || me, m = fe(t, s);
|
|
148
149
|
(async () => {
|
|
149
|
-
const g = await
|
|
150
|
+
const g = await Ce(
|
|
150
151
|
r,
|
|
151
|
-
|
|
152
|
+
f?.baseUrl,
|
|
152
153
|
(v) => {
|
|
153
154
|
w(v);
|
|
154
155
|
}
|
|
155
156
|
);
|
|
156
157
|
if (g.error) {
|
|
157
|
-
|
|
158
|
+
_(g.error), x(!1);
|
|
158
159
|
return;
|
|
159
160
|
}
|
|
160
|
-
w(g.config),
|
|
161
|
-
const
|
|
162
|
-
|
|
161
|
+
w(g.config), x(!1);
|
|
162
|
+
const b = be(r);
|
|
163
|
+
b && b.messages.length > 0 ? (n(b.messages), R(b.threadId), c(b.input)) : n([
|
|
163
164
|
{
|
|
164
165
|
role: "assistant",
|
|
165
|
-
content: g.config?.welcomeMessage ||
|
|
166
|
+
content: g.config?.welcomeMessage || Y
|
|
166
167
|
}
|
|
167
168
|
]);
|
|
168
|
-
const a = await
|
|
169
|
-
a || console.warn("Widget auth initialization failed"),
|
|
169
|
+
const a = await m;
|
|
170
|
+
a || console.warn("Widget auth initialization failed"), B(a);
|
|
170
171
|
})();
|
|
171
|
-
}, [r,
|
|
172
|
-
|
|
173
|
-
}, [
|
|
174
|
-
|
|
175
|
-
threadId:
|
|
176
|
-
messages:
|
|
177
|
-
input:
|
|
172
|
+
}, [r, f]), U(() => {
|
|
173
|
+
u.length > 0 && O.current && O.current.scrollIntoView({ behavior: "smooth" });
|
|
174
|
+
}, [u]), U(() => {
|
|
175
|
+
u.length <= 1 && !o || ke(r, {
|
|
176
|
+
threadId: h,
|
|
177
|
+
messages: u,
|
|
178
|
+
input: o,
|
|
178
179
|
savedAt: Date.now()
|
|
179
180
|
});
|
|
180
|
-
}, [
|
|
181
|
-
if (
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
(i) => i.some((g) => g.id ===
|
|
181
|
+
}, [u, h, o, r]), U(() => !h || !E ? void 0 : ge(h, (s) => {
|
|
182
|
+
if (s.role !== "human") return;
|
|
183
|
+
const m = s.metadata?.attachments ?? [];
|
|
184
|
+
n(
|
|
185
|
+
(i) => i.some((g) => g.id === s.id) ? i : [
|
|
185
186
|
...i,
|
|
186
187
|
{
|
|
187
|
-
id:
|
|
188
|
+
id: s.id,
|
|
188
189
|
role: "assistant",
|
|
189
|
-
content:
|
|
190
|
-
...
|
|
190
|
+
content: s.content,
|
|
191
|
+
...m.length > 0 ? { attachments: m } : {}
|
|
191
192
|
}
|
|
192
193
|
]
|
|
193
194
|
);
|
|
194
|
-
}), [
|
|
195
|
-
const
|
|
196
|
-
const
|
|
195
|
+
}), [h, E]);
|
|
196
|
+
const ee = (t) => {
|
|
197
|
+
const s = Array.from(t.target.files || []);
|
|
197
198
|
t.target.value = "", M(null);
|
|
198
|
-
for (const
|
|
199
|
-
const i =
|
|
199
|
+
for (const m of s) {
|
|
200
|
+
const i = Ne(m);
|
|
200
201
|
if (i) {
|
|
201
202
|
M(i);
|
|
202
203
|
return;
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
|
-
|
|
206
|
-
const i =
|
|
207
|
-
return [...
|
|
206
|
+
P((m) => {
|
|
207
|
+
const i = Ee - m.length;
|
|
208
|
+
return [...m, ...s.slice(0, i)];
|
|
208
209
|
});
|
|
209
|
-
},
|
|
210
|
-
|
|
211
|
-
},
|
|
212
|
-
if (!
|
|
213
|
-
const t =
|
|
214
|
-
|
|
215
|
-
let
|
|
216
|
-
if (
|
|
217
|
-
|
|
210
|
+
}, te = (t) => {
|
|
211
|
+
P((s) => s.filter((m, i) => i !== t));
|
|
212
|
+
}, z = async () => {
|
|
213
|
+
if (!o.trim() || k || !E) return;
|
|
214
|
+
const t = o.trim();
|
|
215
|
+
c(""), L(!0), M(null);
|
|
216
|
+
let s = [];
|
|
217
|
+
if (I.length > 0 && h) {
|
|
218
|
+
D(!0);
|
|
218
219
|
try {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
(a) =>
|
|
220
|
+
s = await Promise.all(
|
|
221
|
+
I.map(
|
|
222
|
+
(a) => Le({
|
|
222
223
|
publishableApiKey: r,
|
|
223
|
-
threadId:
|
|
224
|
+
threadId: h,
|
|
224
225
|
file: a,
|
|
225
|
-
baseUrl:
|
|
226
|
+
baseUrl: f?.baseUrl
|
|
226
227
|
})
|
|
227
228
|
)
|
|
228
229
|
);
|
|
229
230
|
} catch (a) {
|
|
230
|
-
|
|
231
|
-
threadId:
|
|
232
|
-
baseUrl:
|
|
233
|
-
}), M(a instanceof Error ? a.message : "Upload failed."),
|
|
231
|
+
$(a instanceof Error ? a.message : "Upload failed", {
|
|
232
|
+
threadId: h,
|
|
233
|
+
baseUrl: f?.baseUrl
|
|
234
|
+
}), M(a instanceof Error ? a.message : "Upload failed."), L(!1), D(!1);
|
|
234
235
|
return;
|
|
235
236
|
}
|
|
236
|
-
|
|
237
|
+
D(!1), P([]);
|
|
237
238
|
}
|
|
238
|
-
const
|
|
239
|
-
|
|
239
|
+
const m = s.length > 0 ? { attachments: s } : void 0;
|
|
240
|
+
n((a) => [
|
|
240
241
|
...a,
|
|
241
|
-
{ role: "user", content: t, ...
|
|
242
|
+
{ role: "user", content: t, ...s.length > 0 ? { attachments: s } : {} }
|
|
242
243
|
]);
|
|
243
|
-
const i =
|
|
244
|
-
|
|
245
|
-
let g = "",
|
|
246
|
-
await
|
|
244
|
+
const i = u.length + 1;
|
|
245
|
+
n((a) => [...a, { role: "assistant", content: "" }]);
|
|
246
|
+
let g = "", b = [];
|
|
247
|
+
await we({
|
|
247
248
|
publishableApiKey: r,
|
|
248
249
|
content: t,
|
|
249
|
-
threadId:
|
|
250
|
-
baseUrl:
|
|
251
|
-
metadata:
|
|
250
|
+
threadId: h,
|
|
251
|
+
baseUrl: f?.baseUrl,
|
|
252
|
+
metadata: m,
|
|
253
|
+
user: y,
|
|
252
254
|
callbacks: {
|
|
253
255
|
onInit: (a) => {
|
|
254
|
-
|
|
256
|
+
h || R(a);
|
|
255
257
|
},
|
|
256
258
|
onContent: (a) => {
|
|
257
|
-
g += a,
|
|
258
|
-
const
|
|
259
|
-
return
|
|
259
|
+
g += a, n((v) => {
|
|
260
|
+
const N = [...v];
|
|
261
|
+
return N[i] = {
|
|
260
262
|
role: "assistant",
|
|
261
263
|
content: g
|
|
262
|
-
},
|
|
264
|
+
}, N;
|
|
263
265
|
});
|
|
264
266
|
},
|
|
265
267
|
onComplete: (a) => {
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
return
|
|
268
|
+
b = a, n((v) => {
|
|
269
|
+
const N = [...v];
|
|
270
|
+
return N[i] = {
|
|
269
271
|
role: "assistant",
|
|
270
272
|
content: g,
|
|
271
|
-
sources:
|
|
272
|
-
},
|
|
273
|
+
sources: b
|
|
274
|
+
}, N;
|
|
273
275
|
});
|
|
274
276
|
},
|
|
275
277
|
onDone: ({ humanTakeover: a }) => {
|
|
276
|
-
a &&
|
|
278
|
+
a && n((v) => [
|
|
277
279
|
...v.slice(0, i),
|
|
278
280
|
...v.slice(i + 1)
|
|
279
281
|
]);
|
|
280
282
|
},
|
|
281
283
|
onError: (a) => {
|
|
282
|
-
|
|
283
|
-
const
|
|
284
|
-
return
|
|
284
|
+
$(a, { userMessage: t, threadId: h, baseUrl: f?.baseUrl }), n((v) => {
|
|
285
|
+
const N = [...v];
|
|
286
|
+
return N[i] = {
|
|
285
287
|
role: "assistant",
|
|
286
288
|
content: `Error: ${a}`
|
|
287
|
-
},
|
|
289
|
+
}, N;
|
|
288
290
|
});
|
|
289
291
|
}
|
|
290
292
|
}
|
|
291
|
-
}),
|
|
292
|
-
},
|
|
293
|
-
|
|
294
|
-
{ role: "assistant", content:
|
|
295
|
-
]),
|
|
296
|
-
},
|
|
297
|
-
t.key === "Enter" && !t.shiftKey && (t.preventDefault(),
|
|
298
|
-
},
|
|
299
|
-
|
|
300
|
-
},
|
|
293
|
+
}), L(!1);
|
|
294
|
+
}, ne = () => {
|
|
295
|
+
Me(r), R(void 0), n([
|
|
296
|
+
{ role: "assistant", content: p?.welcomeMessage || Y }
|
|
297
|
+
]), c(""), P([]), M(null);
|
|
298
|
+
}, se = (t) => {
|
|
299
|
+
t.key === "Enter" && !t.shiftKey && (t.preventDefault(), z());
|
|
300
|
+
}, re = async (t) => {
|
|
301
|
+
c(t), setTimeout(() => z(), 0);
|
|
302
|
+
}, Q = C ? /* @__PURE__ */ e("div", { className: "knest-chat-card", children: /* @__PURE__ */ e("div", { className: "knest-loading-container", children: /* @__PURE__ */ l("div", { className: "knest-loading-content", children: [
|
|
301
303
|
/* @__PURE__ */ e("div", { className: "knest-spinner-ring" }),
|
|
302
304
|
/* @__PURE__ */ e("p", { className: "knest-loading-text", children: "Loading chat..." })
|
|
303
|
-
] }) }) }) :
|
|
305
|
+
] }) }) }) : A === "auth" ? /* @__PURE__ */ e("div", { className: "knest-chat-card", children: /* @__PURE__ */ e("div", { className: "knest-error-container", children: /* @__PURE__ */ e("div", { className: "knest-error-content", children: /* @__PURE__ */ e("p", { className: "knest-error-text", children: ve }) }) }) }) : /* @__PURE__ */ l("div", { className: "knest-chat-card", children: [
|
|
304
306
|
/* @__PURE__ */ l("div", { className: "knest-messages-container", children: [
|
|
305
|
-
|
|
307
|
+
u.map((t, s) => /* @__PURE__ */ l("div", { children: [
|
|
306
308
|
/* @__PURE__ */ e(
|
|
307
|
-
|
|
309
|
+
Ue,
|
|
308
310
|
{
|
|
309
311
|
message: t,
|
|
310
|
-
isLoading: !t.content &&
|
|
311
|
-
avatarUrl:
|
|
312
|
-
brandColor:
|
|
312
|
+
isLoading: !t.content && k && t.role === "assistant",
|
|
313
|
+
avatarUrl: Z,
|
|
314
|
+
brandColor: F,
|
|
313
315
|
publishableApiKey: r,
|
|
314
|
-
baseUrl:
|
|
316
|
+
baseUrl: f?.baseUrl
|
|
315
317
|
}
|
|
316
318
|
),
|
|
317
|
-
|
|
318
|
-
] },
|
|
319
|
-
|
|
319
|
+
s < u.length - 1 && /* @__PURE__ */ e("div", { className: "knest-separator" })
|
|
320
|
+
] }, s)),
|
|
321
|
+
u.length === 1 && !C && /* @__PURE__ */ l("div", { className: "knest-examples", children: [
|
|
320
322
|
/* @__PURE__ */ e("h3", { children: "Example Questions" }),
|
|
321
|
-
|
|
323
|
+
K.map((t, s) => /* @__PURE__ */ e(
|
|
322
324
|
"button",
|
|
323
325
|
{
|
|
324
|
-
onClick: () =>
|
|
326
|
+
onClick: () => re(t),
|
|
325
327
|
className: "knest-example-btn",
|
|
326
|
-
style:
|
|
328
|
+
style: s === 0 ? { borderColor: F, borderWidth: "2px" } : {},
|
|
327
329
|
children: t
|
|
328
330
|
},
|
|
329
|
-
|
|
331
|
+
s
|
|
330
332
|
))
|
|
331
333
|
] }),
|
|
332
|
-
/* @__PURE__ */ e("div", { ref:
|
|
334
|
+
/* @__PURE__ */ e("div", { ref: O })
|
|
333
335
|
] }),
|
|
334
336
|
/* @__PURE__ */ l("div", { className: "knest-input-section", children: [
|
|
335
337
|
/* @__PURE__ */ e(
|
|
336
338
|
"input",
|
|
337
339
|
{
|
|
338
|
-
ref:
|
|
340
|
+
ref: H,
|
|
339
341
|
type: "file",
|
|
340
|
-
accept:
|
|
342
|
+
accept: pe,
|
|
341
343
|
multiple: !0,
|
|
342
344
|
style: { display: "none" },
|
|
343
|
-
onChange:
|
|
345
|
+
onChange: ee
|
|
344
346
|
}
|
|
345
347
|
),
|
|
346
|
-
|
|
348
|
+
I.length > 0 && /* @__PURE__ */ e("div", { className: "knest-file-preview", children: I.map((t, s) => /* @__PURE__ */ l("span", { className: "knest-file-chip", children: [
|
|
347
349
|
t.name,
|
|
348
350
|
/* @__PURE__ */ e(
|
|
349
351
|
"button",
|
|
350
352
|
{
|
|
351
353
|
type: "button",
|
|
352
354
|
className: "knest-chip-remove",
|
|
353
|
-
onClick: () =>
|
|
355
|
+
onClick: () => te(s),
|
|
354
356
|
"aria-label": `Remove ${t.name}`,
|
|
355
357
|
children: "×"
|
|
356
358
|
}
|
|
357
359
|
)
|
|
358
|
-
] },
|
|
359
|
-
|
|
360
|
+
] }, s)) }),
|
|
361
|
+
G && /* @__PURE__ */ e("p", { className: "knest-attach-error", children: G }),
|
|
360
362
|
/* @__PURE__ */ l("div", { className: "knest-input-wrapper", children: [
|
|
361
363
|
/* @__PURE__ */ e(
|
|
362
364
|
"input",
|
|
363
365
|
{
|
|
364
366
|
type: "text",
|
|
365
|
-
value:
|
|
366
|
-
onChange: (t) =>
|
|
367
|
-
onKeyDown:
|
|
367
|
+
value: o,
|
|
368
|
+
onChange: (t) => c(t.target.value),
|
|
369
|
+
onKeyDown: se,
|
|
368
370
|
placeholder: "Ask me anything...",
|
|
369
|
-
disabled:
|
|
371
|
+
disabled: k || j || !E,
|
|
370
372
|
className: "knest-input-field"
|
|
371
373
|
}
|
|
372
374
|
),
|
|
373
375
|
/* @__PURE__ */ e(
|
|
374
376
|
"button",
|
|
375
377
|
{
|
|
376
|
-
onClick: () =>
|
|
377
|
-
disabled: !
|
|
378
|
+
onClick: () => H.current?.click(),
|
|
379
|
+
disabled: !h || k || j,
|
|
378
380
|
className: "knest-attach-btn",
|
|
379
381
|
type: "button",
|
|
380
|
-
title:
|
|
382
|
+
title: h ? "Attach file" : "Send a message first to enable attachments",
|
|
381
383
|
"aria-label": "Attach file",
|
|
382
384
|
children: /* @__PURE__ */ e(
|
|
383
385
|
"svg",
|
|
@@ -402,8 +404,8 @@ function Ae({
|
|
|
402
404
|
/* @__PURE__ */ e(
|
|
403
405
|
"button",
|
|
404
406
|
{
|
|
405
|
-
onClick:
|
|
406
|
-
disabled:
|
|
407
|
+
onClick: z,
|
|
408
|
+
disabled: k || j || !o.trim() || !E,
|
|
407
409
|
className: "knest-send-btn",
|
|
408
410
|
"aria-label": "Send message",
|
|
409
411
|
children: /* @__PURE__ */ e("svg", { className: "knest-send-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e(
|
|
@@ -418,7 +420,7 @@ function Ae({
|
|
|
418
420
|
}
|
|
419
421
|
)
|
|
420
422
|
] }),
|
|
421
|
-
|
|
423
|
+
u.length > 1 && !k && /* @__PURE__ */ e("div", { className: "knest-reset-row", children: /* @__PURE__ */ e("button", { onClick: ne, className: "knest-reset-btn", children: "Clear chat" }) }),
|
|
422
424
|
/* @__PURE__ */ e("div", { className: "knest-footer", children: /* @__PURE__ */ l(
|
|
423
425
|
"a",
|
|
424
426
|
{
|
|
@@ -495,19 +497,19 @@ function Ae({
|
|
|
495
497
|
) })
|
|
496
498
|
] })
|
|
497
499
|
] });
|
|
498
|
-
if (
|
|
499
|
-
return
|
|
500
|
-
const
|
|
500
|
+
if (T === "inline")
|
|
501
|
+
return Q;
|
|
502
|
+
const ae = C ? "#9ca3af" : F;
|
|
501
503
|
return /* @__PURE__ */ l("div", { className: "knest-bubble-container", children: [
|
|
502
|
-
|
|
504
|
+
S && /* @__PURE__ */ e("div", { className: "knest-bubble-panel", children: Q }),
|
|
503
505
|
/* @__PURE__ */ e(
|
|
504
506
|
"button",
|
|
505
507
|
{
|
|
506
|
-
className: ["knest-bubble-button",
|
|
507
|
-
onClick: () =>
|
|
508
|
-
"aria-label":
|
|
509
|
-
style: { backgroundColor:
|
|
510
|
-
children:
|
|
508
|
+
className: ["knest-bubble-button", C && "knest-bubble-loading"].filter(Boolean).join(" "),
|
|
509
|
+
onClick: () => J(!S),
|
|
510
|
+
"aria-label": C ? "Loading chat" : S ? "Close chat" : "Open chat",
|
|
511
|
+
style: { backgroundColor: ae },
|
|
512
|
+
children: C ? /* @__PURE__ */ l(
|
|
511
513
|
"svg",
|
|
512
514
|
{
|
|
513
515
|
width: "24",
|
|
@@ -540,7 +542,7 @@ function Ae({
|
|
|
540
542
|
)
|
|
541
543
|
]
|
|
542
544
|
}
|
|
543
|
-
) :
|
|
545
|
+
) : S ? /* @__PURE__ */ e(
|
|
544
546
|
"svg",
|
|
545
547
|
{
|
|
546
548
|
width: "24",
|
|
@@ -575,6 +577,6 @@ function Ae({
|
|
|
575
577
|
] });
|
|
576
578
|
}
|
|
577
579
|
export {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
+
Ue as ChatMessage,
|
|
581
|
+
Se as ChatWidget
|
|
580
582
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useknest/widget-react",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.13",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Native React component for Knest chat widget",
|
|
6
6
|
"files": [
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@useknest/widget-core": "0.1.0-beta.
|
|
25
|
+
"@useknest/widget-core": "0.1.0-beta.13"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/react": "^18.3.3",
|