@useknest/widget-react 0.1.0-beta.1 → 0.1.0-beta.10

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
@@ -22,7 +22,7 @@ import { ChatWidget } from '@useknest/widget-react';
22
22
  function App() {
23
23
  return (
24
24
  <div>
25
- <ChatWidget publishableApiKey="pk_your_key_here" />
25
+ <ChatWidget publishableApiKey="pk_your_public_key_here" />
26
26
  </div>
27
27
  );
28
28
  }
@@ -34,9 +34,11 @@ function App() {
34
34
 
35
35
  ### ChatWidget
36
36
 
37
- | Prop | Type | Required | Description |
38
- | ------------------- | -------- | -------- | ---------------------------------- |
39
- | `publishableApiKey` | `string` | Yes | Your project's publishable API key |
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) |
40
42
 
41
43
  ## Features
42
44
 
@@ -44,7 +46,7 @@ function App() {
44
46
  - ✅ **Streaming Support** - Real-time message streaming via Server-Sent Events (SSE)
45
47
  - ✅ **TypeScript** - Full TypeScript support with exported types
46
48
  - ✅ **Customizable** - Fetches branding (avatar, colors, welcome message) from your project config
47
- - ✅ **Lightweight** - ~28KB minified (~8.5KB gzipped)
49
+ - ✅ **Lightweight** - ~17KB minified (~4.4KB gzipped)
48
50
  - ✅ **Framework-Agnostic Core** - Shares business logic with other platform packages
49
51
 
50
52
  ## TypeScript
@@ -57,7 +59,7 @@ import { ChatWidget, type ChatWidgetProps, type Message } from '@useknest/widget
57
59
 
58
60
  ## Customization
59
61
 
60
- The widget automatically loads customization from your project's configuration:
62
+ The widget automatically loads customization from your project's configuration at useknest.com:
61
63
 
62
64
  - Avatar image
63
65
  - Brand color
@@ -89,12 +91,11 @@ This package uses `@useknest/widget-core` for all business logic (API calls, str
89
91
 
90
92
  ```tsx
91
93
  import { ChatWidget } from '@useknest/widget-react';
92
- import '@useknest/widget-react/dist/widget-react.css';
93
94
 
94
95
  function FullPageChat() {
95
96
  return (
96
97
  <div style={{ height: '100vh', width: '100vw' }}>
97
- <ChatWidget publishableApiKey="pk_your_key_here" />
98
+ <ChatWidget publishableApiKey="pk_your_public_key_here" />
98
99
  </div>
99
100
  );
100
101
  }
@@ -104,35 +105,40 @@ function FullPageChat() {
104
105
 
105
106
  ```tsx
106
107
  import { ChatWidget } from '@useknest/widget-react';
107
- import '@useknest/widget-react/dist/widget-react.css';
108
108
 
109
109
  function ChatContainer() {
110
110
  return (
111
111
  <div style={{ maxWidth: '900px', height: '600px', margin: '0 auto' }}>
112
- <ChatWidget publishableApiKey="pk_your_key_here" />
112
+ <ChatWidget publishableApiKey="pk_your_public_key_here" />
113
113
  </div>
114
114
  );
115
115
  }
116
116
  ```
117
117
 
118
- ## Troubleshooting
118
+ ### Floating Bubble Mode
119
119
 
120
- ### Streaming not working
120
+ ```tsx
121
+ import { ChatWidget } from '@useknest/widget-react';
121
122
 
122
- **Solution:** Check that your backend API is running and accessible. The widget defaults to `http://localhost:5173/api/v1` for local development.
123
+ function App() {
124
+ return <ChatWidget publishableApiKey="pk_your_public_key_here" mode="bubble" />;
125
+ }
126
+ ```
123
127
 
124
- ### TypeScript errors
128
+ ### Bubble Mode (Auto-Open)
125
129
 
126
- **Solution:** Make sure you have React types installed:
130
+ ```tsx
131
+ import { ChatWidget } from '@useknest/widget-react';
127
132
 
128
- ```bash
129
- npm install --save-dev @types/react @types/react-dom
133
+ function App() {
134
+ return <ChatWidget publishableApiKey="pk_your_public_key_here" mode="bubble" defaultOpen />;
135
+ }
130
136
  ```
131
137
 
132
138
  ## License
133
139
 
134
- MIT
140
+ Proprietary - All rights reserved. This software is for use by authorized Knest customers only.
135
141
 
136
142
  ## Support
137
143
 
138
- For issues and questions, please visit [GitHub Issues](https://github.com/your-repo/issues).
144
+ For issues and questions, please email us at useknest@gmail.com
@@ -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,UAAsB,EACtB,UAAiB,EACjB,EAAE,gBAAgB,2CAoFlB"}
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,7 +1,18 @@
1
+ import { WidgetMode } from '@useknest/widget-core';
2
+ /** Internal config for testing/development - not part of the public API. */
3
+ export interface InternalConfig {
4
+ baseUrl?: string;
5
+ supabaseUrl?: string;
6
+ supabaseAnonKey?: string;
7
+ }
1
8
  export interface ChatWidgetProps {
2
9
  publishableApiKey: string;
3
- /** Base URL for the API. Defaults to https://useknest.com. Pass empty string for relative paths. */
4
- baseUrl?: string;
10
+ /** Display mode: 'inline' renders in place, 'bubble' shows floating button. Defaults to 'inline'. */
11
+ mode?: WidgetMode;
12
+ /** Whether to auto-open the chat in bubble mode. Defaults to false. */
13
+ defaultOpen?: boolean;
14
+ /** Internal config for testing/development - not part of the public API. */
15
+ _internal?: InternalConfig;
5
16
  }
6
- export declare function ChatWidget({ publishableApiKey, baseUrl }: ChatWidgetProps): import("react/jsx-runtime").JSX.Element;
17
+ export declare function ChatWidget({ publishableApiKey, mode, defaultOpen, _internal }: ChatWidgetProps): import("react/jsx-runtime").JSX.Element;
7
18
  //# sourceMappingURL=ChatWidget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../src/ChatWidget.tsx"],"names":[],"mappings":"AAkBA,MAAM,WAAW,eAAe;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oGAAoG;IACpG,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,UAAU,CAAC,EAAE,iBAAiB,EAAE,OAAO,EAAE,EAAE,eAAe,2CA+RzE"}
1
+ {"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../src/ChatWidget.tsx"],"names":[],"mappings":"AAgBA,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,2CAyYjB"}
package/dist/index.js CHANGED
@@ -1,39 +1,39 @@
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;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:#0d7a7f;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:flex-start}.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:#374151;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}.knest-message-content a{color:#374151;text-decoration:underline}.knest-message-content ul,.knest-message-content ol{margin:8px 0;padding-left:24px}.knest-message-content li{margin:4px 0}.knest-message-content strong{font-weight:600;color:#111827}.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}")),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 c, useRef as D, useEffect as _ } from "react";
4
- import { formatContent as O, DEFAULT_AVATAR_URL as j, DEFAULT_EXAMPLE_QUESTIONS as B, DEFAULT_BRAND_COLOR as F, initWidgetSentry as P, AUTH_ERROR_MESSAGE as Q, fetchWidgetConfig as K, initWidgetAuth as z, DEFAULT_WELCOME_MESSAGE as G, streamChatMessage as H, captureWidgetException as V } from "@useknest/widget-core";
5
- function X({
6
- message: r,
7
- isLoading: d = !1,
8
- avatarUrl: m = "/default-avatar.svg",
9
- brandColor: g = "#0d7a7f",
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 r } from "react/jsx-runtime";
3
+ import { useState as c, useRef as z, useEffect as I } from "react";
4
+ import { formatContent as G, DEFAULT_BRAND_COLOR as T, 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, subscribeToThread as $, AUTH_ERROR_MESSAGE as J, fetchWidgetConfig as Z, DEFAULT_WELCOME_MESSAGE as ee, streamChatMessage as te, captureWidgetException as ne } from "@useknest/widget-core";
5
+ function se({
6
+ message: o,
7
+ isLoading: y = !1,
8
+ avatarUrl: E = "/default-avatar.svg",
9
+ brandColor: i = T,
10
10
  showAvatar: v = !0
11
11
  }) {
12
- const [p, x] = c(!1), E = () => {
13
- x(!0);
14
- }, f = r.content ? O(r.content) : [];
15
- return /* @__PURE__ */ e("div", { className: "knest-message-wrapper", children: /* @__PURE__ */ s("div", { className: "knest-message", children: [
16
- v && /* @__PURE__ */ e("div", { className: "knest-message-avatar", children: r.role === "assistant" ? p ? /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: g }, children: "AI" }) : /* @__PURE__ */ e(
12
+ const [p, u] = c(!1), C = () => {
13
+ u(!0);
14
+ }, w = o.content ? G(o.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: o.role === "assistant" ? p ? /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: i }, children: "AI" }) : /* @__PURE__ */ e(
17
17
  "img",
18
18
  {
19
- src: m,
19
+ src: E,
20
20
  alt: "Avatar",
21
21
  className: "knest-avatar-img",
22
- onError: E
22
+ onError: C
23
23
  }
24
- ) : /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: g }, children: "U" }) }),
25
- /* @__PURE__ */ s("div", { className: "knest-message-content", children: [
26
- !r.content && d && r.role === "assistant" ? /* @__PURE__ */ s("div", { className: "knest-loading", children: [
24
+ ) : /* @__PURE__ */ e("div", { className: "knest-user-avatar", style: { backgroundColor: i }, children: "U" }) }),
25
+ /* @__PURE__ */ r("div", { className: "knest-message-content", children: [
26
+ !o.content && y && o.role === "assistant" ? /* @__PURE__ */ r("div", { className: "knest-loading", children: [
27
27
  /* @__PURE__ */ e("div", { className: "knest-dot" }),
28
28
  /* @__PURE__ */ e("div", { className: "knest-dot" }),
29
29
  /* @__PURE__ */ e("div", { className: "knest-dot" })
30
- ] }) : f.map((i, o) => /* @__PURE__ */ e("p", { dangerouslySetInnerHTML: { __html: i.html } }, o)),
31
- r.sources && r.sources.length > 0 && /* @__PURE__ */ s("div", { className: "knest-sources", children: [
30
+ ] }) : /* @__PURE__ */ e("div", { dangerouslySetInnerHTML: { __html: w } }),
31
+ o.sources && o.sources.length > 0 && /* @__PURE__ */ r("div", { className: "knest-sources", children: [
32
32
  /* @__PURE__ */ e("div", { className: "knest-sources-label", children: "Sources" }),
33
- r.sources.slice(0, 1).map((i, o) => /* @__PURE__ */ s(
33
+ o.sources.slice(0, 1).map((m, k) => /* @__PURE__ */ r(
34
34
  "a",
35
35
  {
36
- href: i.url,
36
+ href: m.url,
37
37
  target: "_blank",
38
38
  rel: "noopener noreferrer",
39
39
  className: "knest-source-item",
@@ -56,146 +56,163 @@ function X({
56
56
  )
57
57
  }
58
58
  ),
59
- /* @__PURE__ */ s("div", { className: "knest-source-text", children: [
60
- i.breadcrumb && /* @__PURE__ */ e("div", { className: "knest-source-breadcrumb", children: i.breadcrumb }),
61
- /* @__PURE__ */ e("div", { className: "knest-source-title", children: i.title })
59
+ /* @__PURE__ */ r("div", { className: "knest-source-text", children: [
60
+ m.breadcrumb && /* @__PURE__ */ e("div", { className: "knest-source-breadcrumb", children: m.breadcrumb }),
61
+ /* @__PURE__ */ e("div", { className: "knest-source-title", children: m.title })
62
62
  ] })
63
63
  ]
64
64
  },
65
- o
65
+ k
66
66
  ))
67
67
  ] })
68
68
  ] })
69
69
  ] }) });
70
70
  }
71
- function Z({ publishableApiKey: r, baseUrl: d }) {
72
- const [m, g] = c(null), [v, p] = c(!0), [x, E] = c(null), [f, i] = c(!1), [o, u] = c([]), [C, A] = c(""), [N, M] = c(!1), [y, S] = c(void 0), L = D(null), I = m?.avatarUrl || j, R = m?.exampleQuestions || B, b = m?.brandColor || F;
73
- _(() => {
74
- P(), (async () => {
75
- const n = await K(r, d);
71
+ function le({
72
+ publishableApiKey: o,
73
+ mode: y = "inline",
74
+ defaultOpen: E = !1,
75
+ _internal: i
76
+ }) {
77
+ const [v, p] = c(null), [u, C] = c(!0), [w, m] = c(null), [k, R] = c(!1), [f, h] = c([]), [N, A] = c(""), [L, S] = c(!1), [g, O] = c(void 0), [x, P] = c(E), M = z(null), j = v?.avatarUrl || H, D = v?.exampleQuestions || V, U = v?.brandColor || T;
78
+ I(() => {
79
+ typeof requestIdleCallback < "u" ? requestIdleCallback(() => _()) : setTimeout(() => _(), 0);
80
+ const t = i?.supabaseUrl || q, s = i?.supabaseAnonKey || X, d = Y(t, s);
81
+ (async () => {
82
+ const n = await Z(
83
+ o,
84
+ i?.baseUrl,
85
+ (l) => {
86
+ p(l);
87
+ }
88
+ );
76
89
  if (n.error) {
77
- E(n.error), p(!1);
90
+ m(n.error), C(!1);
78
91
  return;
79
92
  }
80
- if (g(n.config), n.config) {
81
- const h = await z(
82
- n.config.supabaseUrl,
83
- n.config.supabaseAnonKey
84
- );
85
- h || console.warn("Widget auth initialization failed"), i(h);
86
- }
87
- p(!1), u([
93
+ p(n.config), C(!1), h([
88
94
  {
89
95
  role: "assistant",
90
- content: n.config?.welcomeMessage || G
96
+ content: n.config?.welcomeMessage || ee
91
97
  }
92
98
  ]);
99
+ const a = await d;
100
+ a || console.warn("Widget auth initialization failed"), R(a);
93
101
  })();
94
- }, [r, d]), _(() => {
95
- o.length > 0 && L.current && L.current.scrollIntoView({ behavior: "smooth" });
96
- }, [o]);
97
- const w = async () => {
98
- if (!C.trim() || N || !f) return;
99
- const t = C.trim();
100
- A(""), M(!0), u((a) => [...a, { role: "user", content: t }]);
101
- const n = o.length + 1;
102
- u((a) => [...a, { role: "assistant", content: "" }]);
103
- let h = "", W = [];
104
- await H({
105
- publishableApiKey: r,
102
+ }, [o, i]), I(() => {
103
+ f.length > 0 && M.current && M.current.scrollIntoView({ behavior: "smooth" });
104
+ }, [f]), I(() => !g || !k ? void 0 : $(g, (s) => {
105
+ s.role === "human" && h(
106
+ (d) => d.some((b) => b.id === s.id) ? d : [...d, { id: s.id, role: "assistant", content: s.content }]
107
+ );
108
+ }), [g, k]);
109
+ const W = async () => {
110
+ if (!N.trim() || L || !k) return;
111
+ const t = N.trim();
112
+ A(""), S(!0), h((n) => [...n, { role: "user", content: t }]);
113
+ const s = f.length + 1;
114
+ h((n) => [...n, { role: "assistant", content: "" }]);
115
+ let d = "", b = [];
116
+ await te({
117
+ publishableApiKey: o,
106
118
  content: t,
107
- threadId: y,
108
- baseUrl: d,
119
+ threadId: g,
120
+ baseUrl: i?.baseUrl,
109
121
  callbacks: {
110
- onInit: (a) => {
111
- y || S(a);
122
+ onInit: (n) => {
123
+ g || O(n);
112
124
  },
113
- onContent: (a) => {
114
- h += a, u((k) => {
115
- const l = [...k];
116
- return l[n] = {
125
+ onContent: (n) => {
126
+ d += n, h((a) => {
127
+ const l = [...a];
128
+ return l[s] = {
117
129
  role: "assistant",
118
- content: h
130
+ content: d
119
131
  }, l;
120
132
  });
121
133
  },
122
- onComplete: (a) => {
123
- W = a, u((k) => {
124
- const l = [...k];
125
- return l[n] = {
134
+ onComplete: (n) => {
135
+ b = n, h((a) => {
136
+ const l = [...a];
137
+ return l[s] = {
126
138
  role: "assistant",
127
- content: h,
128
- sources: W
139
+ content: d,
140
+ sources: b
129
141
  }, l;
130
142
  });
131
143
  },
132
- onError: (a) => {
133
- V(a, { userMessage: t, threadId: y, baseUrl: d }), u((k) => {
134
- const l = [...k];
135
- return l[n] = {
144
+ onDone: ({ humanTakeover: n }) => {
145
+ n && h((a) => [
146
+ ...a.slice(0, s),
147
+ ...a.slice(s + 1)
148
+ ]);
149
+ },
150
+ onError: (n) => {
151
+ ne(n, { userMessage: t, threadId: g, baseUrl: i?.baseUrl }), h((a) => {
152
+ const l = [...a];
153
+ return l[s] = {
136
154
  role: "assistant",
137
- content: `Error: ${a}`
155
+ content: `Error: ${n}`
138
156
  }, l;
139
157
  });
140
158
  }
141
159
  }
142
- }), M(!1);
143
- }, T = (t) => {
144
- t.key === "Enter" && !t.shiftKey && (t.preventDefault(), w());
145
- }, U = async (t) => {
146
- A(t), setTimeout(() => w(), 0);
147
- };
148
- return v ? /* @__PURE__ */ e("div", { className: "knest-chat-card", children: /* @__PURE__ */ e("div", { className: "knest-loading-container", children: /* @__PURE__ */ s("div", { className: "knest-loading-content", children: [
160
+ }), S(!1);
161
+ }, K = (t) => {
162
+ t.key === "Enter" && !t.shiftKey && (t.preventDefault(), W());
163
+ }, F = async (t) => {
164
+ A(t), setTimeout(() => W(), 0);
165
+ }, B = u ? /* @__PURE__ */ e("div", { className: "knest-chat-card", children: /* @__PURE__ */ e("div", { className: "knest-loading-container", children: /* @__PURE__ */ r("div", { className: "knest-loading-content", children: [
149
166
  /* @__PURE__ */ e("div", { className: "knest-spinner-ring" }),
150
167
  /* @__PURE__ */ e("p", { className: "knest-loading-text", children: "Loading chat..." })
151
- ] }) }) }) : x === "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: Q }) }) }) }) : /* @__PURE__ */ s("div", { className: "knest-chat-card", children: [
152
- /* @__PURE__ */ s("div", { className: "knest-messages-container", children: [
153
- o.map((t, n) => /* @__PURE__ */ s("div", { children: [
168
+ ] }) }) }) : w === "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: J }) }) }) }) : /* @__PURE__ */ r("div", { className: "knest-chat-card", children: [
169
+ /* @__PURE__ */ r("div", { className: "knest-messages-container", children: [
170
+ f.map((t, s) => /* @__PURE__ */ r("div", { children: [
154
171
  /* @__PURE__ */ e(
155
- X,
172
+ se,
156
173
  {
157
174
  message: t,
158
- isLoading: !t.content && N && t.role === "assistant",
159
- avatarUrl: I,
160
- brandColor: b
175
+ isLoading: !t.content && L && t.role === "assistant",
176
+ avatarUrl: j,
177
+ brandColor: U
161
178
  }
162
179
  ),
163
- n < o.length - 1 && /* @__PURE__ */ e("div", { className: "knest-separator" })
164
- ] }, n)),
165
- o.length === 1 && !v && /* @__PURE__ */ s("div", { className: "knest-examples", children: [
180
+ s < f.length - 1 && /* @__PURE__ */ e("div", { className: "knest-separator" })
181
+ ] }, s)),
182
+ f.length === 1 && !u && /* @__PURE__ */ r("div", { className: "knest-examples", children: [
166
183
  /* @__PURE__ */ e("h3", { children: "Example Questions" }),
167
- R.map((t, n) => /* @__PURE__ */ e(
184
+ D.map((t, s) => /* @__PURE__ */ e(
168
185
  "button",
169
186
  {
170
- onClick: () => U(t),
187
+ onClick: () => F(t),
171
188
  className: "knest-example-btn",
172
- style: n === 0 ? { borderColor: b, borderWidth: "2px" } : {},
189
+ style: s === 0 ? { borderColor: U, borderWidth: "2px" } : {},
173
190
  children: t
174
191
  },
175
- n
192
+ s
176
193
  ))
177
194
  ] }),
178
- /* @__PURE__ */ e("div", { ref: L })
195
+ /* @__PURE__ */ e("div", { ref: M })
179
196
  ] }),
180
- /* @__PURE__ */ s("div", { className: "knest-input-section", children: [
181
- /* @__PURE__ */ s("div", { className: "knest-input-wrapper", children: [
197
+ /* @__PURE__ */ r("div", { className: "knest-input-section", children: [
198
+ /* @__PURE__ */ r("div", { className: "knest-input-wrapper", children: [
182
199
  /* @__PURE__ */ e(
183
200
  "input",
184
201
  {
185
202
  type: "text",
186
- value: C,
203
+ value: N,
187
204
  onChange: (t) => A(t.target.value),
188
- onKeyPress: T,
205
+ onKeyPress: K,
189
206
  placeholder: "Ask me anything...",
190
- disabled: N || !f,
207
+ disabled: L || !k,
191
208
  className: "knest-input-field"
192
209
  }
193
210
  ),
194
211
  /* @__PURE__ */ e(
195
212
  "button",
196
213
  {
197
- onClick: w,
198
- disabled: N || !C.trim() || !f,
214
+ onClick: W,
215
+ disabled: L || !N.trim() || !k,
199
216
  className: "knest-send-btn",
200
217
  "aria-label": "Send message",
201
218
  children: /* @__PURE__ */ e("svg", { className: "knest-send-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e(
@@ -210,7 +227,7 @@ function Z({ publishableApiKey: r, baseUrl: d }) {
210
227
  }
211
228
  )
212
229
  ] }),
213
- /* @__PURE__ */ e("div", { className: "knest-footer", children: /* @__PURE__ */ s(
230
+ /* @__PURE__ */ e("div", { className: "knest-footer", children: /* @__PURE__ */ r(
214
231
  "a",
215
232
  {
216
233
  href: "https://useknest.com",
@@ -219,7 +236,7 @@ function Z({ publishableApiKey: r, baseUrl: d }) {
219
236
  className: "knest-powered-by",
220
237
  children: [
221
238
  /* @__PURE__ */ e("span", { children: "Powered by" }),
222
- /* @__PURE__ */ s(
239
+ /* @__PURE__ */ r(
223
240
  "svg",
224
241
  {
225
242
  width: "14",
@@ -286,8 +303,86 @@ function Z({ publishableApiKey: r, baseUrl: d }) {
286
303
  ) })
287
304
  ] })
288
305
  ] });
306
+ if (y === "inline")
307
+ return B;
308
+ const Q = u ? "#9ca3af" : U;
309
+ return /* @__PURE__ */ r("div", { className: "knest-bubble-container", children: [
310
+ x && /* @__PURE__ */ e("div", { className: "knest-bubble-panel", children: B }),
311
+ /* @__PURE__ */ e(
312
+ "button",
313
+ {
314
+ className: ["knest-bubble-button", u && "knest-bubble-loading"].filter(Boolean).join(" "),
315
+ onClick: () => P(!x),
316
+ "aria-label": u ? "Loading chat" : x ? "Close chat" : "Open chat",
317
+ style: { backgroundColor: Q },
318
+ children: u ? /* @__PURE__ */ r(
319
+ "svg",
320
+ {
321
+ width: "24",
322
+ height: "24",
323
+ viewBox: "0 0 24 24",
324
+ fill: "none",
325
+ className: "knest-bubble-spinner",
326
+ children: [
327
+ /* @__PURE__ */ e(
328
+ "circle",
329
+ {
330
+ cx: "12",
331
+ cy: "12",
332
+ r: "9",
333
+ stroke: "currentColor",
334
+ strokeOpacity: "0.25",
335
+ strokeWidth: "3",
336
+ fill: "none"
337
+ }
338
+ ),
339
+ /* @__PURE__ */ e(
340
+ "path",
341
+ {
342
+ d: "M12 3a9 9 0 0 1 9 9",
343
+ stroke: "currentColor",
344
+ strokeWidth: "3",
345
+ strokeLinecap: "round",
346
+ fill: "none"
347
+ }
348
+ )
349
+ ]
350
+ }
351
+ ) : x ? /* @__PURE__ */ e(
352
+ "svg",
353
+ {
354
+ width: "24",
355
+ height: "24",
356
+ viewBox: "0 0 24 24",
357
+ fill: "none",
358
+ stroke: "currentColor",
359
+ strokeWidth: "2",
360
+ children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" })
361
+ }
362
+ ) : /* @__PURE__ */ e(
363
+ "svg",
364
+ {
365
+ width: "24",
366
+ height: "24",
367
+ viewBox: "0 0 24 24",
368
+ fill: "none",
369
+ stroke: "currentColor",
370
+ strokeWidth: "2",
371
+ children: /* @__PURE__ */ e(
372
+ "path",
373
+ {
374
+ strokeLinecap: "round",
375
+ strokeLinejoin: "round",
376
+ 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"
377
+ }
378
+ )
379
+ }
380
+ )
381
+ }
382
+ )
383
+ ] });
289
384
  }
290
385
  export {
291
- X as ChatMessage,
292
- Z as ChatWidget
386
+ se as ChatMessage,
387
+ le as ChatWidget
293
388
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useknest/widget-react",
3
- "version": "0.1.0-beta.1",
3
+ "version": "0.1.0-beta.10",
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.1"
25
+ "@useknest/widget-core": "0.1.0-beta.10"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/react": "^18.3.3",