@useknest/widget-react 0.1.0-beta.9 → 0.1.0

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,9 +1,9 @@
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;
5
5
  supabaseUrl?: string;
6
- supabaseAnonKey?: string;
6
+ supabasePublishableKey?: string;
7
7
  }
8
8
  export interface ChatWidgetProps {
9
9
  publishableApiKey: 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":"AAeA,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,2CA+WjB"}
1
+ {"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../src/ChatWidget.tsx"],"names":[],"mappings":"AA4BA,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,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAChC;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,2CAgmBjB"}
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-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 s } from "react/jsx-runtime";
3
- import { useState as l, useRef as z, useEffect as B } from "react";
4
- import { formatContent as G, DEFAULT_BRAND_COLOR as R, DEFAULT_AVATAR_URL as H, DEFAULT_EXAMPLE_QUESTIONS as V, initWidgetSentry as _, PUBLIC_SUPABASE_URL as q, PUBLIC_SUPABASE_ANON_KEY as X, initWidgetAuth as Y, AUTH_ERROR_MESSAGE as $, fetchWidgetConfig as J, DEFAULT_WELCOME_MESSAGE as Z, streamChatMessage as ee, captureWidgetException as te } from "@useknest/widget-core";
5
- function ne({
6
- message: r,
7
- isLoading: L = !1,
8
- avatarUrl: x = "/default-avatar.svg",
9
- brandColor: c = R,
10
- showAvatar: m = !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-presence-caption{display:flex;align-items:center;gap:.375rem;font-size:.75rem;color:#6b7280;margin:0 0 .375rem}.knest-online-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:#22c55e;flex-shrink:0}.knest-human-takeover-caption{font-size:.75rem;color:#9ca3af;text-align:center;margin:.1875rem 0 .75rem}.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{position:relative;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%}.knest-bubble-close-btn{display:none;position:absolute;top:.75rem;right:.75rem;z-index:10;width:2rem;height:2rem;align-items:center;justify-content:center;border:none;border-radius:50%;background:#0000000f;color:#374151;cursor:pointer}.knest-bubble-close-btn:hover{background:#0000001f}@media (max-width: 440px){.knest-bubble-container.knest-bubble-open{inset:0}.knest-bubble-container.knest-bubble-open .knest-bubble-button{display:none}.knest-bubble-panel{width:100%;height:100dvh;max-width:none;max-height:none;border-radius:0;border:none;box-shadow:none;padding-top:env(safe-area-inset-top);padding-bottom:env(safe-area-inset-bottom)}.knest-bubble-close-btn{display:flex}.knest-bubble-panel .knest-messages-container>:first-child{padding-right:2.5rem}}")),document.head.appendChild(e)}}catch(t){console.error("vite-plugin-css-injected-by-js",t)}})();
2
+ import { jsx as e, jsxs as o } from "react/jsx-runtime";
3
+ import { useState as i, useEffect as A, useRef as J } from "react";
4
+ import { fetchSignedUrl as me, formatContent as ke, DEFAULT_BRAND_COLOR as ne, isImageType as fe, formatFileSize as ge, DEFAULT_AVATAR_URL as ve, DEFAULT_EXAMPLE_QUESTIONS as pe, initWidgetSentry as Z, PUBLIC_SUPABASE_URL as Ce, PUBLIC_SUPABASE_PUBLISHABLE_KEY as be, initWidgetAuth as Ne, saveChatStateDebounced as Ee, MOBILE_BREAKPOINT_PX as Le, lockBodyScroll as we, unlockBodyScroll as K, subscribeToThread as Me, AUTH_ERROR_MESSAGE as Ae, HUMAN_TAKEOVER_CAPTION as xe, PRESENCE_LABEL_WIDGET as Ue, ACCEPTED_FILE_TYPES_STRING as Se, fetchWidgetConfig as ye, loadChatState as Ie, DEFAULT_WELCOME_MESSAGE as ee, validateAttachment as Pe, MAX_ATTACHMENTS_PER_MESSAGE as Te, uploadAttachment as Be, captureWidgetException as te, streamChatMessage as _e, clearChatState as We } from "@useknest/widget-core";
5
+ function Re({
6
+ message: s,
7
+ isLoading: _ = !1,
8
+ avatarUrl: W = "/default-avatar.svg",
9
+ brandColor: S = ne,
10
+ showAvatar: k = !0,
11
+ publishableApiKey: v,
12
+ baseUrl: x
11
13
  }) {
12
- const [v, i] = l(!1), p = () => {
13
- i(!0);
14
- }, y = r.content ? G(r.content) : "";
15
- return /* @__PURE__ */ e("div", { className: "knest-message-wrapper", children: /* @__PURE__ */ s("div", { className: "knest-message", children: [
16
- m && /* @__PURE__ */ e("div", { className: "knest-message-avatar", children: r.role === "assistant" ? v ? /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: c }, children: "AI" }) : /* @__PURE__ */ e(
14
+ const [p, y] = i(!1), [I, R] = i({});
15
+ A(() => {
16
+ if (!s.attachments?.length || !v) return;
17
+ const n = s.attachments.filter(
18
+ (l) => l.storagePath && !l.url && !I[l.storagePath]
19
+ );
20
+ n.length !== 0 && Promise.all(
21
+ n.map(async (l) => {
22
+ const c = await me({
23
+ publishableApiKey: v,
24
+ storagePath: l.storagePath,
25
+ baseUrl: x
26
+ });
27
+ return { storagePath: l.storagePath, url: c };
28
+ })
29
+ ).then((l) => {
30
+ const c = {};
31
+ for (const { storagePath: g, url: w } of l)
32
+ w && (c[g] = w);
33
+ Object.keys(c).length > 0 && R((g) => ({ ...g, ...c }));
34
+ });
35
+ }, [s.attachments, v, x]);
36
+ const N = (n) => n.url || (n.storagePath ? I[n.storagePath] : void 0), O = () => y(!0), m = s.content ? ke(s.content) : "";
37
+ return /* @__PURE__ */ e("div", { className: "knest-message-wrapper", children: /* @__PURE__ */ o("div", { className: "knest-message", children: [
38
+ k && /* @__PURE__ */ e("div", { className: "knest-message-avatar", children: s.role === "assistant" ? p ? /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: S }, children: "AI" }) : /* @__PURE__ */ e(
17
39
  "img",
18
40
  {
19
- src: x,
41
+ src: W,
20
42
  alt: "Avatar",
21
43
  className: "knest-avatar-img",
22
- onError: p
44
+ onError: O
23
45
  }
24
- ) : /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: c }, children: "U" }) }),
25
- /* @__PURE__ */ s("div", { className: "knest-message-content", children: [
26
- !r.content && L && r.role === "assistant" ? /* @__PURE__ */ s("div", { className: "knest-loading", children: [
46
+ ) : /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: S }, children: "U" }) }),
47
+ /* @__PURE__ */ o("div", { className: "knest-message-content", children: [
48
+ !s.content && _ && s.role === "assistant" ? /* @__PURE__ */ o("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: y } }),
31
- r.sources && r.sources.length > 0 && /* @__PURE__ */ s("div", { className: "knest-sources", children: [
52
+ ] }) : /* @__PURE__ */ e("div", { dangerouslySetInnerHTML: { __html: m } }),
53
+ s.attachments && s.attachments.length > 0 && /* @__PURE__ */ e("div", { className: "knest-attachments", children: s.attachments.map((n, l) => {
54
+ const c = N(n);
55
+ return fe(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
+ l
65
+ ) : null : /* @__PURE__ */ o(
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: ge(n.fileSize) })
93
+ ]
94
+ },
95
+ l
96
+ );
97
+ }) }),
98
+ s.sources && s.sources.length > 0 && /* @__PURE__ */ o("div", { className: "knest-sources", children: [
32
99
  /* @__PURE__ */ e("div", { className: "knest-sources-label", children: "Sources" }),
33
- r.sources.slice(0, 1).map((h, f) => /* @__PURE__ */ s(
100
+ s.sources.slice(0, 1).map((n, l) => /* @__PURE__ */ o(
34
101
  "a",
35
102
  {
36
- href: h.url,
103
+ href: n.url,
37
104
  target: "_blank",
38
105
  rel: "noopener noreferrer",
39
106
  className: "knest-source-item",
@@ -56,153 +123,305 @@ function ne({
56
123
  )
57
124
  }
58
125
  ),
59
- /* @__PURE__ */ s("div", { className: "knest-source-text", children: [
60
- h.breadcrumb && /* @__PURE__ */ e("div", { className: "knest-source-breadcrumb", children: h.breadcrumb }),
61
- /* @__PURE__ */ e("div", { className: "knest-source-title", children: h.title })
126
+ /* @__PURE__ */ o("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
+ l
66
133
  ))
67
134
  ] })
68
135
  ] })
69
136
  ] }) });
70
137
  }
71
- function ae({
72
- publishableApiKey: r,
73
- mode: L = "inline",
74
- defaultOpen: x = !1,
75
- _internal: c
138
+ function Fe({
139
+ publishableApiKey: s,
140
+ mode: _ = "inline",
141
+ defaultOpen: W = !1,
142
+ user: S,
143
+ _internal: k
76
144
  }) {
77
- const [m, v] = l(null), [i, p] = l(!0), [y, h] = l(null), [f, T] = l(!1), [u, k] = l([]), [C, E] = l(""), [b, I] = l(!1), [w, O] = l(void 0), [N, P] = l(x), A = z(null), j = m?.avatarUrl || H, D = m?.exampleQuestions || V, M = m?.brandColor || R;
78
- B(() => {
79
- typeof requestIdleCallback < "u" ? requestIdleCallback(() => _()) : setTimeout(() => _(), 0);
80
- const t = c?.supabaseUrl || q, o = c?.supabaseAnonKey || X, g = Y(t, o);
145
+ const [v, x] = i(null), [p, y] = i(!0), [I, R] = i(null), [N, O] = i(!1), [m, n] = i([]), [l, c] = i(""), [g, w] = i(!1), [u, j] = i(void 0), [E, V] = i(W), [P, T] = i([]), [D, F] = i(!1), [Q, U] = i(null), [se, X] = i(!1), [re, $] = i(!1), z = J(null), q = J(null), ae = v?.avatarUrl || ve, oe = v?.exampleQuestions || pe, H = v?.brandColor || ne;
146
+ A(() => {
147
+ typeof requestIdleCallback < "u" ? requestIdleCallback(() => Z()) : setTimeout(() => Z(), 0);
148
+ const t = k?.supabaseUrl || Ce, a = k?.supabasePublishableKey || be, d = Ne(t, a);
81
149
  (async () => {
82
- const n = await J(
83
- r,
84
- c?.baseUrl,
85
- (a) => {
86
- v(a);
150
+ const M = await ye(
151
+ s,
152
+ k?.baseUrl,
153
+ (B) => {
154
+ x(B);
87
155
  }
88
156
  );
89
- if (n.error) {
90
- h(n.error), p(!1);
157
+ if (M.error) {
158
+ R(M.error), y(!1);
91
159
  return;
92
160
  }
93
- v(n.config), p(!1), k([
161
+ x(M.config), y(!1);
162
+ const f = Ie(s);
163
+ f && f.messages.length > 0 ? (n(f.messages), j(f.threadId), c(f.input)) : n([
94
164
  {
95
165
  role: "assistant",
96
- content: n.config?.welcomeMessage || Z
166
+ content: M.config?.welcomeMessage || ee
97
167
  }
98
168
  ]);
99
- const d = await g;
100
- d || console.warn("Widget auth initialization failed"), T(d);
169
+ const L = await d;
170
+ L || console.warn("Widget auth initialization failed"), O(L);
101
171
  })();
102
- }, [r, c]), B(() => {
103
- u.length > 0 && A.current && A.current.scrollIntoView({ behavior: "smooth" });
104
- }, [u]);
105
- const U = async () => {
106
- if (!C.trim() || b || !f) return;
107
- const t = C.trim();
108
- E(""), I(!0), k((n) => [...n, { role: "user", content: t }]);
109
- const o = u.length + 1;
110
- k((n) => [...n, { role: "assistant", content: "" }]);
111
- let g = "", W = [];
112
- await ee({
113
- publishableApiKey: r,
114
- content: t,
115
- threadId: w,
116
- baseUrl: c?.baseUrl,
172
+ }, [s, k]), A(() => {
173
+ m.length > 0 && z.current && z.current.scrollIntoView({ behavior: "smooth" });
174
+ }, [m]), A(() => {
175
+ m.length <= 1 && !l || Ee(s, {
176
+ threadId: u,
177
+ messages: m,
178
+ input: l,
179
+ savedAt: Date.now()
180
+ });
181
+ }, [m, u, l, s]), A(() => {
182
+ const t = window.matchMedia(`(max-width: ${Le}px)`);
183
+ return E && t.matches ? we() : K(), () => K();
184
+ }, [E]), A(() => {
185
+ if (!(!u || !N))
186
+ return Me(
187
+ u,
188
+ (t) => {
189
+ if (t.role !== "human") return;
190
+ const a = t.metadata?.attachments ?? [];
191
+ n(
192
+ (d) => d.some((h) => h.id === t.id) ? d : [
193
+ ...d,
194
+ {
195
+ id: t.id,
196
+ role: "assistant",
197
+ content: t.content,
198
+ ...a.length > 0 ? { attachments: a } : {}
199
+ }
200
+ ]
201
+ );
202
+ },
203
+ { role: "visitor", onPresenceChange: (t) => $(t) }
204
+ );
205
+ }, [u, N]);
206
+ const le = (t) => {
207
+ const a = Array.from(t.target.files || []);
208
+ t.target.value = "", U(null);
209
+ for (const d of a) {
210
+ const h = Pe(d);
211
+ if (h) {
212
+ U(h);
213
+ return;
214
+ }
215
+ }
216
+ T((d) => {
217
+ const h = Te - d.length;
218
+ return [...d, ...a.slice(0, h)];
219
+ });
220
+ }, ce = (t) => {
221
+ T((a) => a.filter((d, h) => h !== t));
222
+ }, G = async (t) => {
223
+ const a = t ?? l;
224
+ if (!a.trim() || g || !N) return;
225
+ const d = a.trim();
226
+ c(""), w(!0), U(null);
227
+ let h = [];
228
+ if (P.length > 0 && u) {
229
+ F(!0);
230
+ try {
231
+ h = await Promise.all(
232
+ P.map(
233
+ (r) => Be({
234
+ publishableApiKey: s,
235
+ threadId: u,
236
+ file: r,
237
+ baseUrl: k?.baseUrl
238
+ })
239
+ )
240
+ );
241
+ } catch (r) {
242
+ te(r instanceof Error ? r.message : "Upload failed", {
243
+ threadId: u,
244
+ baseUrl: k?.baseUrl
245
+ }), U(r instanceof Error ? r.message : "Upload failed."), w(!1), F(!1);
246
+ return;
247
+ }
248
+ F(!1), T([]);
249
+ }
250
+ const M = h.length > 0 ? { attachments: h } : void 0;
251
+ n((r) => [
252
+ ...r,
253
+ { role: "user", content: d, ...h.length > 0 ? { attachments: h } : {} }
254
+ ]);
255
+ const f = m.length + 1;
256
+ n((r) => [...r, { role: "assistant", content: "" }]);
257
+ let L = "", B = [];
258
+ await _e({
259
+ publishableApiKey: s,
260
+ content: d,
261
+ threadId: u,
262
+ baseUrl: k?.baseUrl,
263
+ metadata: M,
264
+ user: S,
117
265
  callbacks: {
118
- onInit: (n) => {
119
- w || O(n);
266
+ onInit: (r) => {
267
+ u || j(r);
120
268
  },
121
- onContent: (n) => {
122
- g += n, k((d) => {
123
- const a = [...d];
124
- return a[o] = {
269
+ onContent: (r) => {
270
+ L += r, n((C) => {
271
+ const b = [...C];
272
+ return b[f] = {
125
273
  role: "assistant",
126
- content: g
127
- }, a;
274
+ content: L
275
+ }, b;
128
276
  });
129
277
  },
130
- onComplete: (n) => {
131
- W = n, k((d) => {
132
- const a = [...d];
133
- return a[o] = {
278
+ onComplete: (r) => {
279
+ B = r, n((C) => {
280
+ const b = [...C];
281
+ return b[f] = {
134
282
  role: "assistant",
135
- content: g,
136
- sources: W
137
- }, a;
283
+ content: L,
284
+ sources: B
285
+ }, b;
138
286
  });
139
287
  },
140
- onError: (n) => {
141
- te(n, { userMessage: t, threadId: w, baseUrl: c?.baseUrl }), k((d) => {
142
- const a = [...d];
143
- return a[o] = {
288
+ onDone: ({ humanTakeover: r }) => {
289
+ X(!!r), r && !L && n((C) => [
290
+ ...C.slice(0, f),
291
+ ...C.slice(f + 1)
292
+ ]);
293
+ },
294
+ onError: (r) => {
295
+ te(r, { userMessage: d, threadId: u, baseUrl: k?.baseUrl }), n((C) => {
296
+ const b = [...C];
297
+ return b[f] = {
144
298
  role: "assistant",
145
- content: `Error: ${n}`
146
- }, a;
299
+ content: `Error: ${r}`
300
+ }, b;
147
301
  });
148
302
  }
149
303
  }
150
- }), I(!1);
151
- }, K = (t) => {
152
- t.key === "Enter" && !t.shiftKey && (t.preventDefault(), U());
153
- }, F = async (t) => {
154
- E(t), setTimeout(() => U(), 0);
155
- }, S = i ? /* @__PURE__ */ e("div", { className: "knest-chat-card", children: /* @__PURE__ */ e("div", { className: "knest-loading-container", children: /* @__PURE__ */ s("div", { className: "knest-loading-content", children: [
304
+ }), w(!1);
305
+ }, ie = () => {
306
+ We(s), j(void 0), n([
307
+ { role: "assistant", content: v?.welcomeMessage || ee }
308
+ ]), c(""), T([]), U(null), X(!1), $(!1);
309
+ }, de = (t) => {
310
+ t.key === "Enter" && !t.shiftKey && (t.preventDefault(), G());
311
+ }, he = (t) => {
312
+ G(t);
313
+ }, Y = p ? /* @__PURE__ */ e("div", { className: "knest-chat-card", children: /* @__PURE__ */ e("div", { className: "knest-loading-container", children: /* @__PURE__ */ o("div", { className: "knest-loading-content", children: [
156
314
  /* @__PURE__ */ e("div", { className: "knest-spinner-ring" }),
157
315
  /* @__PURE__ */ e("p", { className: "knest-loading-text", children: "Loading chat..." })
158
- ] }) }) }) : y === "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: $ }) }) }) }) : /* @__PURE__ */ s("div", { className: "knest-chat-card", children: [
159
- /* @__PURE__ */ s("div", { className: "knest-messages-container", children: [
160
- u.map((t, o) => /* @__PURE__ */ s("div", { children: [
316
+ ] }) }) }) : I === "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: Ae }) }) }) }) : /* @__PURE__ */ o("div", { className: "knest-chat-card", children: [
317
+ /* @__PURE__ */ o("div", { className: "knest-messages-container", children: [
318
+ m.map((t, a) => /* @__PURE__ */ o("div", { children: [
161
319
  /* @__PURE__ */ e(
162
- ne,
320
+ Re,
163
321
  {
164
322
  message: t,
165
- isLoading: !t.content && b && t.role === "assistant",
166
- avatarUrl: j,
167
- brandColor: M
323
+ isLoading: !t.content && g && t.role === "assistant",
324
+ avatarUrl: ae,
325
+ brandColor: H,
326
+ publishableApiKey: s,
327
+ baseUrl: k?.baseUrl
168
328
  }
169
329
  ),
170
- o < u.length - 1 && /* @__PURE__ */ e("div", { className: "knest-separator" })
171
- ] }, o)),
172
- u.length === 1 && !i && /* @__PURE__ */ s("div", { className: "knest-examples", children: [
330
+ a < m.length - 1 && /* @__PURE__ */ e("div", { className: "knest-separator" })
331
+ ] }, a)),
332
+ m.length === 1 && !p && /* @__PURE__ */ o("div", { className: "knest-examples", children: [
173
333
  /* @__PURE__ */ e("h3", { children: "Example Questions" }),
174
- D.map((t, o) => /* @__PURE__ */ e(
334
+ oe.map((t, a) => /* @__PURE__ */ e(
175
335
  "button",
176
336
  {
177
- onClick: () => F(t),
337
+ onClick: () => he(t),
178
338
  className: "knest-example-btn",
179
- style: o === 0 ? { borderColor: M, borderWidth: "2px" } : {},
339
+ style: a === 0 ? { borderColor: H, borderWidth: "2px" } : {},
180
340
  children: t
181
341
  },
182
- o
342
+ a
183
343
  ))
184
344
  ] }),
185
- /* @__PURE__ */ e("div", { ref: A })
345
+ se && /* @__PURE__ */ e("p", { className: "knest-human-takeover-caption", children: xe }),
346
+ /* @__PURE__ */ e("div", { ref: z })
186
347
  ] }),
187
- /* @__PURE__ */ s("div", { className: "knest-input-section", children: [
188
- /* @__PURE__ */ s("div", { className: "knest-input-wrapper", children: [
348
+ /* @__PURE__ */ o("div", { className: "knest-input-section", children: [
349
+ re && /* @__PURE__ */ o("p", { className: "knest-presence-caption", children: [
350
+ /* @__PURE__ */ e("span", { className: "knest-online-dot" }),
351
+ Ue
352
+ ] }),
353
+ /* @__PURE__ */ e(
354
+ "input",
355
+ {
356
+ ref: q,
357
+ type: "file",
358
+ accept: Se,
359
+ multiple: !0,
360
+ style: { display: "none" },
361
+ onChange: le
362
+ }
363
+ ),
364
+ P.length > 0 && /* @__PURE__ */ e("div", { className: "knest-file-preview", children: P.map((t, a) => /* @__PURE__ */ o("span", { className: "knest-file-chip", children: [
365
+ t.name,
366
+ /* @__PURE__ */ e(
367
+ "button",
368
+ {
369
+ type: "button",
370
+ className: "knest-chip-remove",
371
+ onClick: () => ce(a),
372
+ "aria-label": `Remove ${t.name}`,
373
+ children: "×"
374
+ }
375
+ )
376
+ ] }, a)) }),
377
+ Q && /* @__PURE__ */ e("p", { className: "knest-attach-error", children: Q }),
378
+ /* @__PURE__ */ o("div", { className: "knest-input-wrapper", children: [
189
379
  /* @__PURE__ */ e(
190
380
  "input",
191
381
  {
192
382
  type: "text",
193
- value: C,
194
- onChange: (t) => E(t.target.value),
195
- onKeyPress: K,
383
+ value: l,
384
+ onChange: (t) => c(t.target.value),
385
+ onKeyDown: de,
196
386
  placeholder: "Ask me anything...",
197
- disabled: b || !f,
387
+ disabled: g || D || !N,
198
388
  className: "knest-input-field"
199
389
  }
200
390
  ),
201
391
  /* @__PURE__ */ e(
202
392
  "button",
203
393
  {
204
- onClick: U,
205
- disabled: b || !C.trim() || !f,
394
+ onClick: () => q.current?.click(),
395
+ disabled: !u || g || D,
396
+ className: "knest-attach-btn",
397
+ type: "button",
398
+ title: u ? "Attach file" : "Send a message first to enable attachments",
399
+ "aria-label": "Attach file",
400
+ children: /* @__PURE__ */ e(
401
+ "svg",
402
+ {
403
+ className: "knest-attach-icon",
404
+ fill: "none",
405
+ stroke: "currentColor",
406
+ viewBox: "0 0 24 24",
407
+ children: /* @__PURE__ */ e(
408
+ "path",
409
+ {
410
+ strokeLinecap: "round",
411
+ strokeLinejoin: "round",
412
+ strokeWidth: "2",
413
+ 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"
414
+ }
415
+ )
416
+ }
417
+ )
418
+ }
419
+ ),
420
+ /* @__PURE__ */ e(
421
+ "button",
422
+ {
423
+ onClick: () => G(),
424
+ disabled: g || D || !l.trim() || !N,
206
425
  className: "knest-send-btn",
207
426
  "aria-label": "Send message",
208
427
  children: /* @__PURE__ */ e("svg", { className: "knest-send-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e(
@@ -217,7 +436,8 @@ function ae({
217
436
  }
218
437
  )
219
438
  ] }),
220
- /* @__PURE__ */ e("div", { className: "knest-footer", children: /* @__PURE__ */ s(
439
+ m.length > 1 && !g && /* @__PURE__ */ e("div", { className: "knest-reset-row", children: /* @__PURE__ */ e("button", { onClick: ie, className: "knest-reset-btn", children: "Clear chat" }) }),
440
+ /* @__PURE__ */ e("div", { className: "knest-footer", children: /* @__PURE__ */ o(
221
441
  "a",
222
442
  {
223
443
  href: "https://useknest.com",
@@ -226,7 +446,7 @@ function ae({
226
446
  className: "knest-powered-by",
227
447
  children: [
228
448
  /* @__PURE__ */ e("span", { children: "Powered by" }),
229
- /* @__PURE__ */ s(
449
+ /* @__PURE__ */ o(
230
450
  "svg",
231
451
  {
232
452
  width: "14",
@@ -293,86 +513,114 @@ function ae({
293
513
  ) })
294
514
  ] })
295
515
  ] });
296
- if (L === "inline")
297
- return S;
298
- const Q = i ? "#9ca3af" : M;
299
- return /* @__PURE__ */ s("div", { className: "knest-bubble-container", children: [
300
- N && /* @__PURE__ */ e("div", { className: "knest-bubble-panel", children: S }),
301
- /* @__PURE__ */ e(
302
- "button",
303
- {
304
- className: ["knest-bubble-button", i && "knest-bubble-loading"].filter(Boolean).join(" "),
305
- onClick: () => P(!N),
306
- "aria-label": i ? "Loading chat" : N ? "Close chat" : "Open chat",
307
- style: { backgroundColor: Q },
308
- children: i ? /* @__PURE__ */ s(
309
- "svg",
310
- {
311
- width: "24",
312
- height: "24",
313
- viewBox: "0 0 24 24",
314
- fill: "none",
315
- className: "knest-bubble-spinner",
316
- children: [
317
- /* @__PURE__ */ e(
318
- "circle",
319
- {
320
- cx: "12",
321
- cy: "12",
322
- r: "9",
323
- stroke: "currentColor",
324
- strokeOpacity: "0.25",
325
- strokeWidth: "3",
326
- fill: "none"
327
- }
328
- ),
329
- /* @__PURE__ */ e(
330
- "path",
516
+ if (_ === "inline")
517
+ return Y;
518
+ const ue = p ? "#9ca3af" : H;
519
+ return /* @__PURE__ */ o(
520
+ "div",
521
+ {
522
+ className: ["knest-bubble-container", E && "knest-bubble-open"].filter(Boolean).join(" "),
523
+ children: [
524
+ E && /* @__PURE__ */ o("div", { className: "knest-bubble-panel", children: [
525
+ /* @__PURE__ */ e(
526
+ "button",
527
+ {
528
+ className: "knest-bubble-close-btn",
529
+ onClick: () => V(!1),
530
+ "aria-label": "Close chat",
531
+ children: /* @__PURE__ */ e(
532
+ "svg",
331
533
  {
332
- d: "M12 3a9 9 0 0 1 9 9",
534
+ width: "20",
535
+ height: "20",
536
+ viewBox: "0 0 24 24",
537
+ fill: "none",
333
538
  stroke: "currentColor",
334
- strokeWidth: "3",
335
- strokeLinecap: "round",
336
- fill: "none"
539
+ strokeWidth: "2",
540
+ children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
337
541
  }
338
542
  )
339
- ]
340
- }
341
- ) : N ? /* @__PURE__ */ e(
342
- "svg",
343
- {
344
- width: "24",
345
- height: "24",
346
- viewBox: "0 0 24 24",
347
- fill: "none",
348
- stroke: "currentColor",
349
- strokeWidth: "2",
350
- children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
351
- }
352
- ) : /* @__PURE__ */ e(
353
- "svg",
543
+ }
544
+ ),
545
+ Y
546
+ ] }),
547
+ /* @__PURE__ */ e(
548
+ "button",
354
549
  {
355
- width: "24",
356
- height: "24",
357
- viewBox: "0 0 24 24",
358
- fill: "none",
359
- stroke: "currentColor",
360
- strokeWidth: "2",
361
- children: /* @__PURE__ */ e(
362
- "path",
550
+ className: ["knest-bubble-button", p && "knest-bubble-loading"].filter(Boolean).join(" "),
551
+ onClick: () => V(!E),
552
+ "aria-label": p ? "Loading chat" : E ? "Close chat" : "Open chat",
553
+ style: { backgroundColor: ue },
554
+ children: p ? /* @__PURE__ */ o(
555
+ "svg",
363
556
  {
364
- strokeLinecap: "round",
365
- strokeLinejoin: "round",
366
- d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
557
+ width: "24",
558
+ height: "24",
559
+ viewBox: "0 0 24 24",
560
+ fill: "none",
561
+ className: "knest-bubble-spinner",
562
+ children: [
563
+ /* @__PURE__ */ e(
564
+ "circle",
565
+ {
566
+ cx: "12",
567
+ cy: "12",
568
+ r: "9",
569
+ stroke: "currentColor",
570
+ strokeOpacity: "0.25",
571
+ strokeWidth: "3",
572
+ fill: "none"
573
+ }
574
+ ),
575
+ /* @__PURE__ */ e(
576
+ "path",
577
+ {
578
+ d: "M12 3a9 9 0 0 1 9 9",
579
+ stroke: "currentColor",
580
+ strokeWidth: "3",
581
+ strokeLinecap: "round",
582
+ fill: "none"
583
+ }
584
+ )
585
+ ]
586
+ }
587
+ ) : E ? /* @__PURE__ */ e(
588
+ "svg",
589
+ {
590
+ width: "24",
591
+ height: "24",
592
+ viewBox: "0 0 24 24",
593
+ fill: "none",
594
+ stroke: "currentColor",
595
+ strokeWidth: "2",
596
+ children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
597
+ }
598
+ ) : /* @__PURE__ */ e(
599
+ "svg",
600
+ {
601
+ width: "24",
602
+ height: "24",
603
+ viewBox: "0 0 24 24",
604
+ fill: "none",
605
+ stroke: "currentColor",
606
+ strokeWidth: "2",
607
+ children: /* @__PURE__ */ e(
608
+ "path",
609
+ {
610
+ strokeLinecap: "round",
611
+ strokeLinejoin: "round",
612
+ d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
613
+ }
614
+ )
367
615
  }
368
616
  )
369
617
  }
370
618
  )
371
- }
372
- )
373
- ] });
619
+ ]
620
+ }
621
+ );
374
622
  }
375
623
  export {
376
- ne as ChatMessage,
377
- ae as ChatWidget
624
+ Re as ChatMessage,
625
+ Fe as ChatWidget
378
626
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useknest/widget-react",
3
- "version": "0.1.0-beta.9",
3
+ "version": "0.1.0",
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.9"
25
+ "@useknest/widget-core": "0.1.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/react": "^18.3.3",