@useknest/widget-react 0.1.0-beta.11 → 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 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
 
@@ -5,6 +5,9 @@ export interface ChatMessageProps {
5
5
  avatarUrl?: string;
6
6
  brandColor?: string;
7
7
  showAvatar?: boolean;
8
+ /** Required for lazy signed URL resolution (widget context). */
9
+ publishableApiKey?: string;
10
+ baseUrl?: string;
8
11
  }
9
- export declare function ChatMessage({ message, isLoading, avatarUrl, brandColor, showAvatar }: ChatMessageProps): import("react/jsx-runtime").JSX.Element;
12
+ export declare function ChatMessage({ message, isLoading, avatarUrl, brandColor, showAvatar, publishableApiKey, baseUrl }: ChatMessageProps): import("react/jsx-runtime").JSX.Element;
10
13
  //# sourceMappingURL=ChatMessage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatMessage.d.ts","sourceRoot":"","sources":["../src/ChatMessage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGrD,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,EAC3B,OAAO,EACP,SAAiB,EACjB,SAAiC,EACjC,UAAgC,EAChC,UAAiB,EACjB,EAAE,gBAAgB,2CAkFlB"}
1
+ {"version":3,"file":"ChatMessage.d.ts","sourceRoot":"","sources":["../src/ChatMessage.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,uBAAuB,CAAC;AAGjE,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,WAAW,CAAC,EAC3B,OAAO,EACP,SAAiB,EACjB,SAAiC,EACjC,UAAgC,EAChC,UAAiB,EACjB,iBAAiB,EACjB,OAAO,EACP,EAAE,gBAAgB,2CAgKlB"}
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../src/ChatWidget.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAKX,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,2CA2ajB"}
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,39 +1,106 @@
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-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-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
- import { jsx as e, jsxs as r } from "react/jsx-runtime";
3
- import { useState as d, useRef as q, useEffect as E } from "react";
4
- import { formatContent as K, DEFAULT_BRAND_COLOR as O, DEFAULT_AVATAR_URL as X, DEFAULT_EXAMPLE_QUESTIONS as Y, initWidgetSentry as T, PUBLIC_SUPABASE_URL as $, PUBLIC_SUPABASE_ANON_KEY as J, initWidgetAuth as Z, saveChatStateDebounced as ee, subscribeToThread as te, AUTH_ERROR_MESSAGE as ne, fetchWidgetConfig as se, loadChatState as re, DEFAULT_WELCOME_MESSAGE as R, streamChatMessage as ae, captureWidgetException as oe, clearChatState as ce } from "@useknest/widget-core";
5
- function le({
6
- message: a,
7
- isLoading: M = !1,
8
- avatarUrl: y = "/default-avatar.svg",
9
- brandColor: h = O,
10
- showAvatar: v = !0
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
+ import { jsx as e, jsxs as l } from "react/jsx-runtime";
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
+ message: r,
7
+ isLoading: T = !1,
8
+ avatarUrl: W = "/default-avatar.svg",
9
+ brandColor: y = q,
10
+ showAvatar: f = !0,
11
+ publishableApiKey: p,
12
+ baseUrl: w
11
13
  }) {
12
- const [L, k] = d(!1), x = () => {
13
- k(!0);
14
- }, A = a.content ? K(a.content) : "";
15
- return /* @__PURE__ */ e("div", { className: "knest-message-wrapper", children: /* @__PURE__ */ r("div", { className: "knest-message", children: [
16
- v && /* @__PURE__ */ e("div", { className: "knest-message-avatar", children: a.role === "assistant" ? L ? /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: h }, children: "AI" }) : /* @__PURE__ */ e(
14
+ const [C, x] = d(!1), [A, _] = d({});
15
+ U(() => {
16
+ if (!r.attachments?.length || !p) return;
17
+ const n = r.attachments.filter(
18
+ (o) => o.storagePath && !o.url && !A[o.storagePath]
19
+ );
20
+ n.length !== 0 && Promise.all(
21
+ n.map(async (o) => {
22
+ const c = await oe({
23
+ publishableApiKey: p,
24
+ storagePath: o.storagePath,
25
+ baseUrl: w
26
+ });
27
+ return { storagePath: o.storagePath, url: c };
28
+ })
29
+ ).then((o) => {
30
+ const c = {};
31
+ for (const { storagePath: k, url: L } of o)
32
+ L && (c[k] = L);
33
+ Object.keys(c).length > 0 && _((k) => ({ ...k, ...c }));
34
+ });
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
+ return /* @__PURE__ */ e("div", { className: "knest-message-wrapper", children: /* @__PURE__ */ l("div", { className: "knest-message", children: [
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(
17
39
  "img",
18
40
  {
19
- src: y,
41
+ src: W,
20
42
  alt: "Avatar",
21
43
  className: "knest-avatar-img",
22
- onError: x
44
+ onError: B
23
45
  }
24
- ) : /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: h }, children: "U" }) }),
25
- /* @__PURE__ */ r("div", { className: "knest-message-content", children: [
26
- !a.content && M && a.role === "assistant" ? /* @__PURE__ */ r("div", { className: "knest-loading", children: [
46
+ ) : /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: y }, children: "U" }) }),
47
+ /* @__PURE__ */ l("div", { className: "knest-message-content", children: [
48
+ !r.content && T && r.role === "assistant" ? /* @__PURE__ */ l("div", { className: "knest-loading", children: [
27
49
  /* @__PURE__ */ e("div", { className: "knest-dot" }),
28
50
  /* @__PURE__ */ e("div", { className: "knest-dot" }),
29
51
  /* @__PURE__ */ e("div", { className: "knest-dot" })
30
- ] }) : /* @__PURE__ */ e("div", { dangerouslySetInnerHTML: { __html: A } }),
31
- a.sources && a.sources.length > 0 && /* @__PURE__ */ r("div", { className: "knest-sources", children: [
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
+ "a",
57
+ {
58
+ href: c,
59
+ target: "_blank",
60
+ rel: "noopener noreferrer",
61
+ className: "knest-attachment-image-link",
62
+ children: /* @__PURE__ */ e("img", { src: c, alt: n.fileName, className: "knest-attachment-image" })
63
+ },
64
+ o
65
+ ) : null : /* @__PURE__ */ l(
66
+ "a",
67
+ {
68
+ href: c || "#",
69
+ target: "_blank",
70
+ rel: "noopener noreferrer",
71
+ className: ["knest-attachment-file", !c && "knest-attachment-disabled"].filter(Boolean).join(" "),
72
+ children: [
73
+ /* @__PURE__ */ e(
74
+ "svg",
75
+ {
76
+ className: "knest-attachment-file-icon",
77
+ fill: "none",
78
+ stroke: "currentColor",
79
+ viewBox: "0 0 24 24",
80
+ children: /* @__PURE__ */ e(
81
+ "path",
82
+ {
83
+ strokeLinecap: "round",
84
+ strokeLinejoin: "round",
85
+ strokeWidth: "2",
86
+ d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
87
+ }
88
+ )
89
+ }
90
+ ),
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
+ ]
94
+ },
95
+ o
96
+ );
97
+ }) }),
98
+ r.sources && r.sources.length > 0 && /* @__PURE__ */ l("div", { className: "knest-sources", children: [
32
99
  /* @__PURE__ */ e("div", { className: "knest-sources-label", children: "Sources" }),
33
- a.sources.slice(0, 1).map((C, f) => /* @__PURE__ */ r(
100
+ r.sources.slice(0, 1).map((n, o) => /* @__PURE__ */ l(
34
101
  "a",
35
102
  {
36
- href: C.url,
103
+ href: n.url,
37
104
  target: "_blank",
38
105
  rel: "noopener noreferrer",
39
106
  className: "knest-source-item",
@@ -56,176 +123,289 @@ function le({
56
123
  )
57
124
  }
58
125
  ),
59
- /* @__PURE__ */ r("div", { className: "knest-source-text", children: [
60
- C.breadcrumb && /* @__PURE__ */ e("div", { className: "knest-source-breadcrumb", children: C.breadcrumb }),
61
- /* @__PURE__ */ e("div", { className: "knest-source-title", children: C.title })
126
+ /* @__PURE__ */ l("div", { className: "knest-source-text", 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 })
62
129
  ] })
63
130
  ]
64
131
  },
65
- f
132
+ o
66
133
  ))
67
134
  ] })
68
135
  ] })
69
136
  ] }) });
70
137
  }
71
- function ue({
72
- publishableApiKey: a,
73
- mode: M = "inline",
74
- defaultOpen: y = !1,
75
- _internal: h
138
+ function Se({
139
+ publishableApiKey: r,
140
+ mode: T = "inline",
141
+ defaultOpen: W = !1,
142
+ user: y,
143
+ _internal: f
76
144
  }) {
77
- const [v, L] = d(null), [k, x] = d(!0), [A, C] = d(null), [f, D] = d(!1), [l, i] = d([]), [g, b] = d(""), [p, B] = d(!1), [m, U] = d(void 0), [w, P] = d(y), S = q(null), j = v?.avatarUrl || X, F = v?.exampleQuestions || Y, W = v?.brandColor || O;
78
- E(() => {
79
- typeof requestIdleCallback < "u" ? requestIdleCallback(() => T()) : setTimeout(() => T(), 0);
80
- const t = h?.supabaseUrl || $, s = h?.supabaseAnonKey || J, u = Z(t, s);
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;
146
+ U(() => {
147
+ typeof requestIdleCallback < "u" ? requestIdleCallback(() => X()) : setTimeout(() => X(), 0);
148
+ const t = f?.supabaseUrl || ue, s = f?.supabaseAnonKey || me, m = fe(t, s);
81
149
  (async () => {
82
- const n = await se(
83
- a,
84
- h?.baseUrl,
85
- (V) => {
86
- L(V);
150
+ const g = await Ce(
151
+ r,
152
+ f?.baseUrl,
153
+ (v) => {
154
+ w(v);
87
155
  }
88
156
  );
89
- if (n.error) {
90
- C(n.error), x(!1);
157
+ if (g.error) {
158
+ _(g.error), x(!1);
91
159
  return;
92
160
  }
93
- L(n.config), x(!1);
94
- const o = re(a);
95
- o && o.messages.length > 0 ? (i(o.messages), U(o.threadId), b(o.input)) : i([
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([
96
164
  {
97
165
  role: "assistant",
98
- content: n.config?.welcomeMessage || R
166
+ content: g.config?.welcomeMessage || Y
99
167
  }
100
168
  ]);
101
- const c = await u;
102
- c || console.warn("Widget auth initialization failed"), D(c);
169
+ const a = await m;
170
+ a || console.warn("Widget auth initialization failed"), B(a);
103
171
  })();
104
- }, [a, h]), E(() => {
105
- l.length > 0 && S.current && S.current.scrollIntoView({ behavior: "smooth" });
106
- }, [l]), E(() => {
107
- l.length <= 1 && !g || ee(a, {
108
- threadId: m,
109
- messages: l,
110
- input: g,
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,
111
179
  savedAt: Date.now()
112
180
  });
113
- }, [l, m, g, a]), E(() => !m || !f ? void 0 : te(m, (s) => {
114
- s.role === "human" && i(
115
- (u) => u.some((N) => N.id === s.id) ? u : [...u, { id: s.id, role: "assistant", content: s.content }]
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 : [
186
+ ...i,
187
+ {
188
+ id: s.id,
189
+ role: "assistant",
190
+ content: s.content,
191
+ ...m.length > 0 ? { attachments: m } : {}
192
+ }
193
+ ]
116
194
  );
117
- }), [m, f]);
118
- const I = async () => {
119
- if (!g.trim() || p || !f) return;
120
- const t = g.trim();
121
- b(""), B(!0), i((n) => [...n, { role: "user", content: t }]);
122
- const s = l.length + 1;
123
- i((n) => [...n, { role: "assistant", content: "" }]);
124
- let u = "", N = [];
125
- await ae({
126
- publishableApiKey: a,
195
+ }), [h, E]);
196
+ const ee = (t) => {
197
+ const s = Array.from(t.target.files || []);
198
+ t.target.value = "", M(null);
199
+ for (const m of s) {
200
+ const i = Ne(m);
201
+ if (i) {
202
+ M(i);
203
+ return;
204
+ }
205
+ }
206
+ P((m) => {
207
+ const i = Ee - m.length;
208
+ return [...m, ...s.slice(0, i)];
209
+ });
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);
219
+ try {
220
+ s = await Promise.all(
221
+ I.map(
222
+ (a) => Le({
223
+ publishableApiKey: r,
224
+ threadId: h,
225
+ file: a,
226
+ baseUrl: f?.baseUrl
227
+ })
228
+ )
229
+ );
230
+ } catch (a) {
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);
235
+ return;
236
+ }
237
+ D(!1), P([]);
238
+ }
239
+ const m = s.length > 0 ? { attachments: s } : void 0;
240
+ n((a) => [
241
+ ...a,
242
+ { role: "user", content: t, ...s.length > 0 ? { attachments: s } : {} }
243
+ ]);
244
+ const i = u.length + 1;
245
+ n((a) => [...a, { role: "assistant", content: "" }]);
246
+ let g = "", b = [];
247
+ await we({
248
+ publishableApiKey: r,
127
249
  content: t,
128
- threadId: m,
129
- baseUrl: h?.baseUrl,
250
+ threadId: h,
251
+ baseUrl: f?.baseUrl,
252
+ metadata: m,
253
+ user: y,
130
254
  callbacks: {
131
- onInit: (n) => {
132
- m || U(n);
255
+ onInit: (a) => {
256
+ h || R(a);
133
257
  },
134
- onContent: (n) => {
135
- u += n, i((o) => {
136
- const c = [...o];
137
- return c[s] = {
258
+ onContent: (a) => {
259
+ g += a, n((v) => {
260
+ const N = [...v];
261
+ return N[i] = {
138
262
  role: "assistant",
139
- content: u
140
- }, c;
263
+ content: g
264
+ }, N;
141
265
  });
142
266
  },
143
- onComplete: (n) => {
144
- N = n, i((o) => {
145
- const c = [...o];
146
- return c[s] = {
267
+ onComplete: (a) => {
268
+ b = a, n((v) => {
269
+ const N = [...v];
270
+ return N[i] = {
147
271
  role: "assistant",
148
- content: u,
149
- sources: N
150
- }, c;
272
+ content: g,
273
+ sources: b
274
+ }, N;
151
275
  });
152
276
  },
153
- onDone: ({ humanTakeover: n }) => {
154
- n && i((o) => [
155
- ...o.slice(0, s),
156
- ...o.slice(s + 1)
277
+ onDone: ({ humanTakeover: a }) => {
278
+ a && n((v) => [
279
+ ...v.slice(0, i),
280
+ ...v.slice(i + 1)
157
281
  ]);
158
282
  },
159
- onError: (n) => {
160
- oe(n, { userMessage: t, threadId: m, baseUrl: h?.baseUrl }), i((o) => {
161
- const c = [...o];
162
- return c[s] = {
283
+ onError: (a) => {
284
+ $(a, { userMessage: t, threadId: h, baseUrl: f?.baseUrl }), n((v) => {
285
+ const N = [...v];
286
+ return N[i] = {
163
287
  role: "assistant",
164
- content: `Error: ${n}`
165
- }, c;
288
+ content: `Error: ${a}`
289
+ }, N;
166
290
  });
167
291
  }
168
292
  }
169
- }), B(!1);
170
- }, Q = () => {
171
- ce(a), U(void 0), i([
172
- { role: "assistant", content: v?.welcomeMessage || R }
173
- ]), b("");
174
- }, z = (t) => {
175
- t.key === "Enter" && !t.shiftKey && (t.preventDefault(), I());
176
- }, G = async (t) => {
177
- b(t), setTimeout(() => I(), 0);
178
- }, _ = k ? /* @__PURE__ */ e("div", { className: "knest-chat-card", children: /* @__PURE__ */ e("div", { className: "knest-loading-container", children: /* @__PURE__ */ r("div", { className: "knest-loading-content", children: [
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: [
179
303
  /* @__PURE__ */ e("div", { className: "knest-spinner-ring" }),
180
304
  /* @__PURE__ */ e("p", { className: "knest-loading-text", children: "Loading chat..." })
181
- ] }) }) }) : 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: ne }) }) }) }) : /* @__PURE__ */ r("div", { className: "knest-chat-card", children: [
182
- /* @__PURE__ */ r("div", { className: "knest-messages-container", children: [
183
- l.map((t, s) => /* @__PURE__ */ r("div", { children: [
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: [
306
+ /* @__PURE__ */ l("div", { className: "knest-messages-container", children: [
307
+ u.map((t, s) => /* @__PURE__ */ l("div", { children: [
184
308
  /* @__PURE__ */ e(
185
- le,
309
+ Ue,
186
310
  {
187
311
  message: t,
188
- isLoading: !t.content && p && t.role === "assistant",
189
- avatarUrl: j,
190
- brandColor: W
312
+ isLoading: !t.content && k && t.role === "assistant",
313
+ avatarUrl: Z,
314
+ brandColor: F,
315
+ publishableApiKey: r,
316
+ baseUrl: f?.baseUrl
191
317
  }
192
318
  ),
193
- s < l.length - 1 && /* @__PURE__ */ e("div", { className: "knest-separator" })
319
+ s < u.length - 1 && /* @__PURE__ */ e("div", { className: "knest-separator" })
194
320
  ] }, s)),
195
- l.length === 1 && !k && /* @__PURE__ */ r("div", { className: "knest-examples", children: [
321
+ u.length === 1 && !C && /* @__PURE__ */ l("div", { className: "knest-examples", children: [
196
322
  /* @__PURE__ */ e("h3", { children: "Example Questions" }),
197
- F.map((t, s) => /* @__PURE__ */ e(
323
+ K.map((t, s) => /* @__PURE__ */ e(
198
324
  "button",
199
325
  {
200
- onClick: () => G(t),
326
+ onClick: () => re(t),
201
327
  className: "knest-example-btn",
202
- style: s === 0 ? { borderColor: W, borderWidth: "2px" } : {},
328
+ style: s === 0 ? { borderColor: F, borderWidth: "2px" } : {},
203
329
  children: t
204
330
  },
205
331
  s
206
332
  ))
207
333
  ] }),
208
- /* @__PURE__ */ e("div", { ref: S })
334
+ /* @__PURE__ */ e("div", { ref: O })
209
335
  ] }),
210
- /* @__PURE__ */ r("div", { className: "knest-input-section", children: [
211
- /* @__PURE__ */ r("div", { className: "knest-input-wrapper", children: [
336
+ /* @__PURE__ */ l("div", { className: "knest-input-section", children: [
337
+ /* @__PURE__ */ e(
338
+ "input",
339
+ {
340
+ ref: H,
341
+ type: "file",
342
+ accept: pe,
343
+ multiple: !0,
344
+ style: { display: "none" },
345
+ onChange: ee
346
+ }
347
+ ),
348
+ I.length > 0 && /* @__PURE__ */ e("div", { className: "knest-file-preview", children: I.map((t, s) => /* @__PURE__ */ l("span", { className: "knest-file-chip", children: [
349
+ t.name,
350
+ /* @__PURE__ */ e(
351
+ "button",
352
+ {
353
+ type: "button",
354
+ className: "knest-chip-remove",
355
+ onClick: () => te(s),
356
+ "aria-label": `Remove ${t.name}`,
357
+ children: "×"
358
+ }
359
+ )
360
+ ] }, s)) }),
361
+ G && /* @__PURE__ */ e("p", { className: "knest-attach-error", children: G }),
362
+ /* @__PURE__ */ l("div", { className: "knest-input-wrapper", children: [
212
363
  /* @__PURE__ */ e(
213
364
  "input",
214
365
  {
215
366
  type: "text",
216
- value: g,
217
- onChange: (t) => b(t.target.value),
218
- onKeyPress: z,
367
+ value: o,
368
+ onChange: (t) => c(t.target.value),
369
+ onKeyDown: se,
219
370
  placeholder: "Ask me anything...",
220
- disabled: p || !f,
371
+ disabled: k || j || !E,
221
372
  className: "knest-input-field"
222
373
  }
223
374
  ),
224
375
  /* @__PURE__ */ e(
225
376
  "button",
226
377
  {
227
- onClick: I,
228
- disabled: p || !g.trim() || !f,
378
+ onClick: () => H.current?.click(),
379
+ disabled: !h || k || j,
380
+ className: "knest-attach-btn",
381
+ type: "button",
382
+ title: h ? "Attach file" : "Send a message first to enable attachments",
383
+ "aria-label": "Attach file",
384
+ children: /* @__PURE__ */ e(
385
+ "svg",
386
+ {
387
+ className: "knest-attach-icon",
388
+ fill: "none",
389
+ stroke: "currentColor",
390
+ viewBox: "0 0 24 24",
391
+ children: /* @__PURE__ */ e(
392
+ "path",
393
+ {
394
+ strokeLinecap: "round",
395
+ strokeLinejoin: "round",
396
+ strokeWidth: "2",
397
+ d: "M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13"
398
+ }
399
+ )
400
+ }
401
+ )
402
+ }
403
+ ),
404
+ /* @__PURE__ */ e(
405
+ "button",
406
+ {
407
+ onClick: z,
408
+ disabled: k || j || !o.trim() || !E,
229
409
  className: "knest-send-btn",
230
410
  "aria-label": "Send message",
231
411
  children: /* @__PURE__ */ e("svg", { className: "knest-send-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e(
@@ -240,8 +420,8 @@ function ue({
240
420
  }
241
421
  )
242
422
  ] }),
243
- l.length > 1 && !p && /* @__PURE__ */ e("div", { className: "knest-reset-row", children: /* @__PURE__ */ e("button", { onClick: Q, className: "knest-reset-btn", children: "Clear chat" }) }),
244
- /* @__PURE__ */ e("div", { className: "knest-footer", children: /* @__PURE__ */ r(
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" }) }),
424
+ /* @__PURE__ */ e("div", { className: "knest-footer", children: /* @__PURE__ */ l(
245
425
  "a",
246
426
  {
247
427
  href: "https://useknest.com",
@@ -250,7 +430,7 @@ function ue({
250
430
  className: "knest-powered-by",
251
431
  children: [
252
432
  /* @__PURE__ */ e("span", { children: "Powered by" }),
253
- /* @__PURE__ */ r(
433
+ /* @__PURE__ */ l(
254
434
  "svg",
255
435
  {
256
436
  width: "14",
@@ -317,19 +497,19 @@ function ue({
317
497
  ) })
318
498
  ] })
319
499
  ] });
320
- if (M === "inline")
321
- return _;
322
- const H = k ? "#9ca3af" : W;
323
- return /* @__PURE__ */ r("div", { className: "knest-bubble-container", children: [
324
- w && /* @__PURE__ */ e("div", { className: "knest-bubble-panel", children: _ }),
500
+ if (T === "inline")
501
+ return Q;
502
+ const ae = C ? "#9ca3af" : F;
503
+ return /* @__PURE__ */ l("div", { className: "knest-bubble-container", children: [
504
+ S && /* @__PURE__ */ e("div", { className: "knest-bubble-panel", children: Q }),
325
505
  /* @__PURE__ */ e(
326
506
  "button",
327
507
  {
328
- className: ["knest-bubble-button", k && "knest-bubble-loading"].filter(Boolean).join(" "),
329
- onClick: () => P(!w),
330
- "aria-label": k ? "Loading chat" : w ? "Close chat" : "Open chat",
331
- style: { backgroundColor: H },
332
- children: k ? /* @__PURE__ */ r(
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(
333
513
  "svg",
334
514
  {
335
515
  width: "24",
@@ -362,7 +542,7 @@ function ue({
362
542
  )
363
543
  ]
364
544
  }
365
- ) : w ? /* @__PURE__ */ e(
545
+ ) : S ? /* @__PURE__ */ e(
366
546
  "svg",
367
547
  {
368
548
  width: "24",
@@ -397,6 +577,6 @@ function ue({
397
577
  ] });
398
578
  }
399
579
  export {
400
- le as ChatMessage,
401
- ue as ChatWidget
580
+ Ue as ChatMessage,
581
+ Se as ChatWidget
402
582
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useknest/widget-react",
3
- "version": "0.1.0-beta.11",
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.11"
25
+ "@useknest/widget-core": "0.1.0-beta.13"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/react": "^18.3.3",