@kite-copilot/chat-panel 0.2.46 → 0.2.48

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
@@ -47,12 +47,11 @@ import '@kite-copilot/chat-panel/style.css';
47
47
  // Create the chat instance
48
48
  const chat = createKiteChat({
49
49
  userId: 'user-123',
50
- orgId: 'org-456',
50
+ orgId: 'org-456', // Organization ID for multi-tenant data isolation
51
51
  agentUrl: 'https://your-api.example.com',
52
52
  // Optional: Pass user info for session tracking in control center
53
53
  userName: 'John Doe',
54
54
  userEmail: 'john@example.com',
55
- userOrganization: 'Acme Inc',
56
55
  onNavigate: (page, subtab) => {
57
56
  router.push(`/${page}${subtab ? `?tab=${subtab}` : ''}`);
58
57
  },
@@ -139,7 +138,6 @@ const router = useRouter();
139
138
 
140
139
  const { open, close, toggle, setCurrentPage } = useKiteChat({
141
140
  userId: 'user-123',
142
- orgId: 'org-456',
143
141
  agentUrl: 'https://your-api.example.com',
144
142
  onNavigate: (page, subtab) => {
145
143
  router.push(`/${page}${subtab ? `?tab=${subtab}` : ''}`);
@@ -178,7 +176,6 @@ app.mount('#app');
178
176
  // Initialize chat after Vue app is mounted
179
177
  const chat = createKiteChat({
180
178
  userId: 'user-123',
181
- orgId: 'org-456',
182
179
  agentUrl: 'https://your-api.example.com',
183
180
  onNavigate: (page) => router.push(`/${page}`),
184
181
  });
@@ -204,10 +201,8 @@ function App() {
204
201
  <ChatPanelWithToggle
205
202
  agentUrl="https://your-api.example.com"
206
203
  userId="user-123"
207
- orgId="org-456"
208
204
  userName="John Doe"
209
205
  userEmail="john@example.com"
210
- userOrganization="Acme Inc"
211
206
  onNavigate={(page) => router.push(`/${page}`)}
212
207
  />
213
208
  </>
@@ -264,7 +259,6 @@ The panel shows suggested questions when empty. These can be customized per-user
264
259
  // Option 1: Pass questions directly
265
260
  const chat = createKiteChat({
266
261
  userId: 'user-123',
267
- orgId: 'org-456',
268
262
  startingQuestions: [
269
263
  { id: '1', label: 'Changing layouts', prompt: 'How do I customize the layout?' },
270
264
  { id: '2', label: 'Bulk uploads', prompt: 'How do I upload data in bulk?' },
@@ -275,7 +269,6 @@ const chat = createKiteChat({
275
269
  // Option 2: Fetch from backend (per-user)
276
270
  const chat = createKiteChat({
277
271
  userId: 'user-123',
278
- orgId: 'org-456',
279
272
  startingQuestionsEndpoint: '/api/user/starting-questions',
280
273
  });
281
274
  ```
@@ -295,11 +288,9 @@ Pass user information to enable session tracking in the control center. This all
295
288
  ```ts
296
289
  const chat = createKiteChat({
297
290
  userId: 'user-123',
298
- orgId: 'org-456',
299
291
  // Optional user info for control center display
300
292
  userName: 'John Doe',
301
293
  userEmail: 'john@example.com',
302
- userOrganization: 'Acme Inc',
303
294
  });
304
295
  ```
305
296
 
@@ -307,9 +298,8 @@ const chat = createKiteChat({
307
298
  |-------|-------------|
308
299
  | `userName` | Displayed in conversations list and live chat |
309
300
  | `userEmail` | Shown in user details panel |
310
- | `userOrganization` | Helps support agents identify the customer's company |
311
301
 
312
- **Note:** If user info is not provided, placeholder values ("Anonymous User", "Not provided", "Unknown") will be displayed in the control center.
302
+ **Note:** If user info is not provided, placeholder values ("Anonymous User", "Not provided") will be displayed in the control center.
313
303
 
314
304
  ## API Reference
315
305
 
@@ -322,12 +312,11 @@ Creates a new chat instance with explicit lifecycle control.
322
312
  | Property | Type | Required | Description |
323
313
  |----------|------|----------|-------------|
324
314
  | `userId` | `string` | Yes | Unique identifier for the current user |
325
- | `orgId` | `string` | Yes | Organization identifier |
315
+ | `orgId` | `string` | No | Organization ID for multi-tenant data isolation |
326
316
  | `agentUrl` | `string` | No | Backend agent API URL |
327
317
  | `currentPage` | `string` | No | Current page context |
328
318
  | `userName` | `string` | No | User's display name (for control center) |
329
319
  | `userEmail` | `string` | No | User's email address (for control center) |
330
- | `userOrganization` | `string` | No | User's organization name (for control center) |
331
320
  | `theme` | `'light' \| 'dark' \| 'system'` | No | Theme preference |
332
321
  | `startingQuestions` | `StartingQuestion[]` | No | Custom starting questions |
333
322
  | `startingQuestionsEndpoint` | `string` | No | URL to fetch per-user questions |
@@ -363,10 +352,9 @@ import { ChatPanelWithToggle } from '@kite-copilot/chat-panel';
363
352
  | `agentUrl` | `string` | `localhost:5002` | Backend agent URL |
364
353
  | `currentPage` | `string` | - | Current page for context |
365
354
  | `userId` | `string` | - | Unique user identifier |
366
- | `orgId` | `string` | - | Organization identifier |
355
+ | `orgId` | `string` | - | Organization ID for multi-tenant data isolation |
367
356
  | `userName` | `string` | - | User's display name (for control center) |
368
357
  | `userEmail` | `string` | - | User's email address (for control center) |
369
- | `userOrganization` | `string` | - | User's organization name (for control center) |
370
358
  | `defaultOpen` | `boolean` | `false` | Initial open state (uncontrolled) |
371
359
  | `isOpen` | `boolean` | - | Controlled open state |
372
360
  | `onOpenChange` | `(isOpen: boolean) => void` | - | Called when open state changes |
@@ -463,8 +451,7 @@ Main chat endpoint for streaming responses.
463
451
  "message": "user message",
464
452
  "current_page": "dashboard",
465
453
  "user_name": "John Doe",
466
- "user_email": "john@example.com",
467
- "user_organization": "Acme Inc"
454
+ "user_email": "john@example.com"
468
455
  }
469
456
  ```
470
457
 
package/dist/auto.cjs CHANGED
@@ -175,6 +175,7 @@ function ScrollBar({
175
175
 
176
176
  // src/ChatPanel.tsx
177
177
  var import_lucide_react4 = require("lucide-react");
178
+ var import_framer_motion2 = require("framer-motion");
178
179
 
179
180
  // src/components/AssistantActivity.tsx
180
181
  var import_lucide_react = require("lucide-react");
@@ -1023,9 +1024,10 @@ function TypingIndicator({ className = "" }) {
1023
1024
 
1024
1025
  // src/ChatPanel.tsx
1025
1026
  var import_jsx_runtime10 = require("react/jsx-runtime");
1026
- var CHAT_PANEL_VERSION = true ? "0.2.46" : "dev";
1027
+ var CHAT_PANEL_VERSION = true ? "0.2.48" : "dev";
1027
1028
  var DEFAULT_AGENT_URL = "http://localhost:5002";
1028
- var PANEL_WIDTH = 340;
1029
+ var PANEL_WIDTH = 400;
1030
+ var PANEL_HEIGHT = 600;
1029
1031
  function unescapeJsonString(str) {
1030
1032
  return str.replace(/\\\\n/g, "\n").replace(/\\\\t/g, " ").replace(/\\\\"/g, '"').replace(/\\\\\\\\/g, "\\").replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
1031
1033
  }
@@ -1482,14 +1484,30 @@ function ChatPanel({
1482
1484
  orgId,
1483
1485
  userName,
1484
1486
  userEmail,
1485
- userOrganization,
1486
1487
  supabaseUrl,
1487
1488
  supabaseAnonKey,
1489
+ initialCorner = "bottom-left",
1490
+ onCornerChange,
1488
1491
  productBackendUrl
1489
1492
  } = {}) {
1490
1493
  const [messages, setMessages] = React6.useState(initialMessages);
1491
1494
  const [input, setInput] = React6.useState("");
1495
+ const [corner, setCorner] = React6.useState(initialCorner);
1496
+ const [isDragging, setIsDragging] = React6.useState(false);
1497
+ const dragControls = (0, import_framer_motion2.useAnimationControls)();
1498
+ const handleDragEnd = React6.useCallback((_event, info) => {
1499
+ dragControls.set({ x: 0, y: 0 });
1500
+ setIsDragging(false);
1501
+ const viewportWidth = window.innerWidth;
1502
+ const pointerX = info.point.x;
1503
+ const newCorner = pointerX < viewportWidth / 2 ? "bottom-left" : "bottom-right";
1504
+ if (newCorner !== corner) {
1505
+ setCorner(newCorner);
1506
+ onCornerChange?.(newCorner);
1507
+ }
1508
+ }, [corner, onCornerChange, dragControls]);
1492
1509
  const [sessionId, setSessionId] = React6.useState(() => crypto.randomUUID());
1510
+ const [sessionUser, setSessionUser] = React6.useState(null);
1493
1511
  const orgConfigState = useOrgConfig({ agentUrl, orgId: orgId || "" });
1494
1512
  const effectiveProductBackendUrl = orgConfigState.config?.productBackendUrl || productBackendUrl;
1495
1513
  const { authState, retry: retryAuth } = useUserAuth({
@@ -1530,6 +1548,9 @@ function ChatPanel({
1530
1548
  testProductBackendEndpoint();
1531
1549
  }, [effectiveProductBackendUrl, orgConfigState.status]);
1532
1550
  const effectiveUser = React6.useMemo(() => {
1551
+ if (sessionUser) {
1552
+ return sessionUser;
1553
+ }
1533
1554
  if (authState.status === "authenticated") {
1534
1555
  return {
1535
1556
  userId: authState.user.id,
@@ -1546,7 +1567,23 @@ function ChatPanel({
1546
1567
  userRole: void 0,
1547
1568
  isInternal: false
1548
1569
  };
1549
- }, [authState, userId, userName, userEmail]);
1570
+ }, [sessionUser, authState, userId, userName, userEmail]);
1571
+ React6.useEffect(() => {
1572
+ if (authState.status === "authenticated" && sessionUser === null) {
1573
+ setSessionUser({
1574
+ userId: authState.user.id,
1575
+ userName: authState.user.name,
1576
+ userEmail: authState.user.email,
1577
+ userRole: authState.user.role,
1578
+ isInternal: authState.user.isInternal
1579
+ });
1580
+ console.log("[ChatPanel] Session user captured:", authState.user.id);
1581
+ }
1582
+ }, [authState, sessionUser]);
1583
+ const isWaitingForAuth = React6.useMemo(() => {
1584
+ if (!effectiveProductBackendUrl) return false;
1585
+ return authState.status === "loading" || authState.status === "idle";
1586
+ }, [effectiveProductBackendUrl, authState.status]);
1550
1587
  const [isEscalated, setIsEscalated] = React6.useState(false);
1551
1588
  const escalationWsRef = React6.useRef(null);
1552
1589
  const [agentIsTyping, setAgentIsTyping] = React6.useState(false);
@@ -1574,6 +1611,7 @@ function ChatPanel({
1574
1611
  } else {
1575
1612
  console.log("[KiteChat] Skipping disconnect update - conditions not met");
1576
1613
  }
1614
+ setSessionUser(null);
1577
1615
  setSessionId(crypto.randomUUID());
1578
1616
  setIsEscalated(false);
1579
1617
  if (escalationWsRef.current) {
@@ -2276,7 +2314,6 @@ function ChatPanel({
2276
2314
  console.log("[ChatPanel] user_id:", effectiveUser.userId);
2277
2315
  console.log("[ChatPanel] user_name:", effectiveUser.userName);
2278
2316
  console.log("[ChatPanel] user_email:", effectiveUser.userEmail);
2279
- console.log("[ChatPanel] user_organization:", userOrganization);
2280
2317
  console.log("[ChatPanel] org_id:", orgId);
2281
2318
  console.log("[ChatPanel] authState.status:", authState.status);
2282
2319
  const response = await fetch(`${agentUrl}/chat/stream`, {
@@ -2288,11 +2325,10 @@ function ChatPanel({
2288
2325
  session_id: sessionId,
2289
2326
  message: userText,
2290
2327
  current_page: currentPage || "dashboard",
2291
- user_id: effectiveUser.userId,
2292
- user_name: effectiveUser.userName,
2293
- user_email: effectiveUser.userEmail,
2294
- user_organization: userOrganization,
2295
- org_id: orgId
2328
+ user_id: userId,
2329
+ org_id: orgId,
2330
+ user_name: userName,
2331
+ user_email: userEmail
2296
2332
  }),
2297
2333
  signal: controller.signal
2298
2334
  });
@@ -3323,12 +3359,21 @@ ${userText}`
3323
3359
  }
3324
3360
  }
3325
3361
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3326
- "section",
3362
+ import_framer_motion2.motion.section,
3327
3363
  {
3328
- className: `fixed top-0 right-0 z-40 flex flex-col bg-white border-l border-gray-200 h-full overflow-hidden transition-transform duration-300 ${isOpen ? "translate-x-0" : "translate-x-full"}`,
3329
- style: { width: `${PANEL_WIDTH}px` },
3364
+ drag: true,
3365
+ dragMomentum: false,
3366
+ dragElastic: 0,
3367
+ animate: dragControls,
3368
+ onDragStart: () => setIsDragging(true),
3369
+ onDragEnd: handleDragEnd,
3370
+ className: `fixed bottom-4 z-40 flex flex-col bg-white border border-gray-200 rounded-2xl overflow-hidden shadow-2xl ${isDragging ? "cursor-grabbing" : ""} ${corner === "bottom-left" ? "left-4" : "right-4"} ${isOpen ? "opacity-100 scale-100" : "opacity-0 scale-95 pointer-events-none"}`,
3371
+ style: {
3372
+ width: `${PANEL_WIDTH}px`,
3373
+ height: `${PANEL_HEIGHT}px`
3374
+ },
3330
3375
  children: [
3331
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between px-4 py-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white shrink-0", children: [
3376
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between px-4 py-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white shrink-0 cursor-grab active:cursor-grabbing", children: [
3332
3377
  /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2.5", children: [
3333
3378
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.Sparkles, { className: "h-3.5 w-3.5 text-black", fill: "currentColor" }),
3334
3379
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: "text-sm font-semibold text-gray-800", children: "Copilot" })
@@ -3461,12 +3506,12 @@ ${userText}`
3461
3506
  return null;
3462
3507
  }
3463
3508
  if (isUser) {
3464
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `flex justify-end ${isRoleChange ? "mt-3" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "max-w-[260px] rounded-2xl rounded-br-md bg-gray-900 px-3 py-2 text-xs text-white shadow-sm", children: message.content }) }, message.id);
3509
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `flex justify-end ${isRoleChange ? "mt-3" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "max-w-[260px] rounded-2xl rounded-br-md bg-gray-900 px-3 py-2 text-sm text-white shadow-sm", children: message.content }) }, message.id);
3465
3510
  }
3466
3511
  if (message.role === "agent") {
3467
3512
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: `flex flex-col items-start ${isRoleChange ? "mt-3" : ""}`, children: [
3468
3513
  isRoleChange && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-[10px] text-gray-500 mb-1 ml-1", children: "Agent" }),
3469
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "max-w-[260px] rounded-2xl rounded-bl-md bg-white border border-gray-200 px-3 py-2 text-xs text-gray-800 shadow-sm", children: message.content })
3514
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "max-w-[300px] rounded-2xl rounded-bl-md bg-gray-100 px-4 py-3 text-sm text-gray-700", children: message.content })
3470
3515
  ] }, message.id);
3471
3516
  }
3472
3517
  if (message.kind === "searchSummary") {
@@ -4524,7 +4569,7 @@ ${userText}`
4524
4569
  ] }) }) }) })
4525
4570
  }
4526
4571
  ),
4527
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "px-4 py-3 border-t border-gray-100 bg-gray-50/50 shrink-0", children: [
4572
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "px-4 py-3 bg-white shrink-0", children: [
4528
4573
  pendingFile && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mb-2 flex items-center gap-2 rounded-xl bg-blue-50 border border-blue-200 px-3 py-2", children: [
4529
4574
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.FileSpreadsheet, { className: "h-4 w-4 text-blue-600" }),
4530
4575
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs text-blue-700 flex-1 truncate", children: pendingFile.name }),
@@ -4636,7 +4681,7 @@ ${userText}`
4636
4681
  {
4637
4682
  type: "submit",
4638
4683
  size: "icon",
4639
- disabled: !input.trim() && !pendingFile,
4684
+ disabled: !input.trim() && !pendingFile || isWaitingForAuth,
4640
4685
  className: "h-6 w-6 rounded-full bg-gray-900 hover:bg-gray-800 disabled:bg-gray-300",
4641
4686
  children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.ArrowUp, { className: "h-2.5 w-2.5" })
4642
4687
  }
@@ -4671,9 +4716,10 @@ function ChatPanelWithToggle({
4671
4716
  orgId,
4672
4717
  userName,
4673
4718
  userEmail,
4674
- userOrganization,
4675
4719
  supabaseUrl,
4676
4720
  supabaseAnonKey,
4721
+ initialCorner,
4722
+ onCornerChange,
4677
4723
  productBackendUrl
4678
4724
  }) {
4679
4725
  const [internalIsOpen, setInternalIsOpen] = React6.useState(defaultOpen);
@@ -4684,16 +4730,6 @@ function ChatPanelWithToggle({
4684
4730
  }
4685
4731
  onOpenChange?.(open);
4686
4732
  };
4687
- React6.useEffect(() => {
4688
- const originalPadding = document.body.style.paddingRight;
4689
- const originalTransition = document.body.style.transition;
4690
- document.body.style.transition = "padding-right 0.3s ease";
4691
- document.body.style.paddingRight = isOpen ? `${PANEL_WIDTH}px` : "0px";
4692
- return () => {
4693
- document.body.style.paddingRight = originalPadding;
4694
- document.body.style.transition = originalTransition;
4695
- };
4696
- }, [isOpen]);
4697
4733
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4698
4734
  ChatPanel,
4699
4735
  {
@@ -4710,9 +4746,10 @@ function ChatPanelWithToggle({
4710
4746
  orgId,
4711
4747
  userName,
4712
4748
  userEmail,
4713
- userOrganization,
4714
4749
  supabaseUrl,
4715
4750
  supabaseAnonKey,
4751
+ initialCorner,
4752
+ onCornerChange,
4716
4753
  productBackendUrl
4717
4754
  }
4718
4755
  );
@@ -4771,7 +4808,6 @@ function KiteChatWrapper({
4771
4808
  orgId: config.orgId,
4772
4809
  userName: config.userName,
4773
4810
  userEmail: config.userEmail,
4774
- userOrganization: config.userOrganization,
4775
4811
  supabaseUrl: config.supabaseUrl,
4776
4812
  supabaseAnonKey: config.supabaseAnonKey,
4777
4813
  productBackendUrl: config.productBackendUrl
package/dist/auto.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { K as KiteChatConfig, a as KiteChatInstance } from './createKiteChat-o5u-5Sor.cjs';
1
+ import { K as KiteChatConfig, a as KiteChatInstance } from './createKiteChat-e6BnJS6T.cjs';
2
2
  import 'react/jsx-runtime';
3
3
 
4
4
  /**
@@ -15,7 +15,6 @@ import 'react/jsx-runtime';
15
15
  * const chat = mountKiteChat({
16
16
  * container: '#chat-container',
17
17
  * userId: 'user-123',
18
- * orgId: 'org-456',
19
18
  * });
20
19
  *
21
20
  * // Later, if needed:
@@ -45,13 +44,11 @@ interface MountKiteChatConfig extends KiteChatConfig {
45
44
  * const chat = mountKiteChat({
46
45
  * container: '#my-chat',
47
46
  * userId: 'user-123',
48
- * orgId: 'org-456',
49
47
  * });
50
48
  *
51
49
  * // Or let it create a container automatically
52
50
  * const chat = mountKiteChat({
53
51
  * userId: 'user-123',
54
- * orgId: 'org-456',
55
52
  * });
56
53
  * ```
57
54
  */
package/dist/auto.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { K as KiteChatConfig, a as KiteChatInstance } from './createKiteChat-o5u-5Sor.js';
1
+ import { K as KiteChatConfig, a as KiteChatInstance } from './createKiteChat-e6BnJS6T.js';
2
2
  import 'react/jsx-runtime';
3
3
 
4
4
  /**
@@ -15,7 +15,6 @@ import 'react/jsx-runtime';
15
15
  * const chat = mountKiteChat({
16
16
  * container: '#chat-container',
17
17
  * userId: 'user-123',
18
- * orgId: 'org-456',
19
18
  * });
20
19
  *
21
20
  * // Later, if needed:
@@ -45,13 +44,11 @@ interface MountKiteChatConfig extends KiteChatConfig {
45
44
  * const chat = mountKiteChat({
46
45
  * container: '#my-chat',
47
46
  * userId: 'user-123',
48
- * orgId: 'org-456',
49
47
  * });
50
48
  *
51
49
  * // Or let it create a container automatically
52
50
  * const chat = mountKiteChat({
53
51
  * userId: 'user-123',
54
- * orgId: 'org-456',
55
52
  * });
56
53
  * ```
57
54
  */
package/dist/auto.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createKiteChat
3
- } from "./chunk-4HIWUL6E.js";
3
+ } from "./chunk-LOTJ3U5L.js";
4
4
 
5
5
  // src/auto.ts
6
6
  function mountKiteChat(config) {
@@ -885,6 +885,7 @@ function DataRenderer({ type, data }) {
885
885
  import * as React6 from "react";
886
886
  import { createClient } from "@supabase/supabase-js";
887
887
  import { ArrowLeft, ArrowUp, Command, CornerDownLeft, CheckCircle2 as CheckCircle23, SquarePen, Paperclip, X, FileSpreadsheet, Loader2 as Loader22, ChevronLeft, ChevronRight, Sparkles, Minus } from "lucide-react";
888
+ import { motion as motion2, useAnimationControls } from "framer-motion";
888
889
 
889
890
  // src/hooks/useUserAuth.ts
890
891
  import * as React4 from "react";
@@ -1024,9 +1025,10 @@ function TypingIndicator({ className = "" }) {
1024
1025
 
1025
1026
  // src/ChatPanel.tsx
1026
1027
  import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1027
- var CHAT_PANEL_VERSION = true ? "0.2.46" : "dev";
1028
+ var CHAT_PANEL_VERSION = true ? "0.2.48" : "dev";
1028
1029
  var DEFAULT_AGENT_URL = "http://localhost:5002";
1029
- var PANEL_WIDTH = 340;
1030
+ var PANEL_WIDTH = 400;
1031
+ var PANEL_HEIGHT = 600;
1030
1032
  function unescapeJsonString(str) {
1031
1033
  return str.replace(/\\\\n/g, "\n").replace(/\\\\t/g, " ").replace(/\\\\"/g, '"').replace(/\\\\\\\\/g, "\\").replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
1032
1034
  }
@@ -1483,14 +1485,30 @@ function ChatPanel({
1483
1485
  orgId,
1484
1486
  userName,
1485
1487
  userEmail,
1486
- userOrganization,
1487
1488
  supabaseUrl,
1488
1489
  supabaseAnonKey,
1490
+ initialCorner = "bottom-left",
1491
+ onCornerChange,
1489
1492
  productBackendUrl
1490
1493
  } = {}) {
1491
1494
  const [messages, setMessages] = React6.useState(initialMessages);
1492
1495
  const [input, setInput] = React6.useState("");
1496
+ const [corner, setCorner] = React6.useState(initialCorner);
1497
+ const [isDragging, setIsDragging] = React6.useState(false);
1498
+ const dragControls = useAnimationControls();
1499
+ const handleDragEnd = React6.useCallback((_event, info) => {
1500
+ dragControls.set({ x: 0, y: 0 });
1501
+ setIsDragging(false);
1502
+ const viewportWidth = window.innerWidth;
1503
+ const pointerX = info.point.x;
1504
+ const newCorner = pointerX < viewportWidth / 2 ? "bottom-left" : "bottom-right";
1505
+ if (newCorner !== corner) {
1506
+ setCorner(newCorner);
1507
+ onCornerChange?.(newCorner);
1508
+ }
1509
+ }, [corner, onCornerChange, dragControls]);
1493
1510
  const [sessionId, setSessionId] = React6.useState(() => crypto.randomUUID());
1511
+ const [sessionUser, setSessionUser] = React6.useState(null);
1494
1512
  const orgConfigState = useOrgConfig({ agentUrl, orgId: orgId || "" });
1495
1513
  const effectiveProductBackendUrl = orgConfigState.config?.productBackendUrl || productBackendUrl;
1496
1514
  const { authState, retry: retryAuth } = useUserAuth({
@@ -1531,6 +1549,9 @@ function ChatPanel({
1531
1549
  testProductBackendEndpoint();
1532
1550
  }, [effectiveProductBackendUrl, orgConfigState.status]);
1533
1551
  const effectiveUser = React6.useMemo(() => {
1552
+ if (sessionUser) {
1553
+ return sessionUser;
1554
+ }
1534
1555
  if (authState.status === "authenticated") {
1535
1556
  return {
1536
1557
  userId: authState.user.id,
@@ -1547,7 +1568,23 @@ function ChatPanel({
1547
1568
  userRole: void 0,
1548
1569
  isInternal: false
1549
1570
  };
1550
- }, [authState, userId, userName, userEmail]);
1571
+ }, [sessionUser, authState, userId, userName, userEmail]);
1572
+ React6.useEffect(() => {
1573
+ if (authState.status === "authenticated" && sessionUser === null) {
1574
+ setSessionUser({
1575
+ userId: authState.user.id,
1576
+ userName: authState.user.name,
1577
+ userEmail: authState.user.email,
1578
+ userRole: authState.user.role,
1579
+ isInternal: authState.user.isInternal
1580
+ });
1581
+ console.log("[ChatPanel] Session user captured:", authState.user.id);
1582
+ }
1583
+ }, [authState, sessionUser]);
1584
+ const isWaitingForAuth = React6.useMemo(() => {
1585
+ if (!effectiveProductBackendUrl) return false;
1586
+ return authState.status === "loading" || authState.status === "idle";
1587
+ }, [effectiveProductBackendUrl, authState.status]);
1551
1588
  const [isEscalated, setIsEscalated] = React6.useState(false);
1552
1589
  const escalationWsRef = React6.useRef(null);
1553
1590
  const [agentIsTyping, setAgentIsTyping] = React6.useState(false);
@@ -1575,6 +1612,7 @@ function ChatPanel({
1575
1612
  } else {
1576
1613
  console.log("[KiteChat] Skipping disconnect update - conditions not met");
1577
1614
  }
1615
+ setSessionUser(null);
1578
1616
  setSessionId(crypto.randomUUID());
1579
1617
  setIsEscalated(false);
1580
1618
  if (escalationWsRef.current) {
@@ -2277,7 +2315,6 @@ function ChatPanel({
2277
2315
  console.log("[ChatPanel] user_id:", effectiveUser.userId);
2278
2316
  console.log("[ChatPanel] user_name:", effectiveUser.userName);
2279
2317
  console.log("[ChatPanel] user_email:", effectiveUser.userEmail);
2280
- console.log("[ChatPanel] user_organization:", userOrganization);
2281
2318
  console.log("[ChatPanel] org_id:", orgId);
2282
2319
  console.log("[ChatPanel] authState.status:", authState.status);
2283
2320
  const response = await fetch(`${agentUrl}/chat/stream`, {
@@ -2289,11 +2326,10 @@ function ChatPanel({
2289
2326
  session_id: sessionId,
2290
2327
  message: userText,
2291
2328
  current_page: currentPage || "dashboard",
2292
- user_id: effectiveUser.userId,
2293
- user_name: effectiveUser.userName,
2294
- user_email: effectiveUser.userEmail,
2295
- user_organization: userOrganization,
2296
- org_id: orgId
2329
+ user_id: userId,
2330
+ org_id: orgId,
2331
+ user_name: userName,
2332
+ user_email: userEmail
2297
2333
  }),
2298
2334
  signal: controller.signal
2299
2335
  });
@@ -3324,12 +3360,21 @@ ${userText}`
3324
3360
  }
3325
3361
  }
3326
3362
  return /* @__PURE__ */ jsxs6(
3327
- "section",
3363
+ motion2.section,
3328
3364
  {
3329
- className: `fixed top-0 right-0 z-40 flex flex-col bg-white border-l border-gray-200 h-full overflow-hidden transition-transform duration-300 ${isOpen ? "translate-x-0" : "translate-x-full"}`,
3330
- style: { width: `${PANEL_WIDTH}px` },
3365
+ drag: true,
3366
+ dragMomentum: false,
3367
+ dragElastic: 0,
3368
+ animate: dragControls,
3369
+ onDragStart: () => setIsDragging(true),
3370
+ onDragEnd: handleDragEnd,
3371
+ className: `fixed bottom-4 z-40 flex flex-col bg-white border border-gray-200 rounded-2xl overflow-hidden shadow-2xl ${isDragging ? "cursor-grabbing" : ""} ${corner === "bottom-left" ? "left-4" : "right-4"} ${isOpen ? "opacity-100 scale-100" : "opacity-0 scale-95 pointer-events-none"}`,
3372
+ style: {
3373
+ width: `${PANEL_WIDTH}px`,
3374
+ height: `${PANEL_HEIGHT}px`
3375
+ },
3331
3376
  children: [
3332
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between px-4 py-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white shrink-0", children: [
3377
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between px-4 py-3 border-b border-gray-100 bg-gradient-to-r from-gray-50 to-white shrink-0 cursor-grab active:cursor-grabbing", children: [
3333
3378
  /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2.5", children: [
3334
3379
  /* @__PURE__ */ jsx10(Sparkles, { className: "h-3.5 w-3.5 text-black", fill: "currentColor" }),
3335
3380
  /* @__PURE__ */ jsx10("h3", { className: "text-sm font-semibold text-gray-800", children: "Copilot" })
@@ -3462,12 +3507,12 @@ ${userText}`
3462
3507
  return null;
3463
3508
  }
3464
3509
  if (isUser) {
3465
- return /* @__PURE__ */ jsx10("div", { className: `flex justify-end ${isRoleChange ? "mt-3" : ""}`, children: /* @__PURE__ */ jsx10("div", { className: "max-w-[260px] rounded-2xl rounded-br-md bg-gray-900 px-3 py-2 text-xs text-white shadow-sm", children: message.content }) }, message.id);
3510
+ return /* @__PURE__ */ jsx10("div", { className: `flex justify-end ${isRoleChange ? "mt-3" : ""}`, children: /* @__PURE__ */ jsx10("div", { className: "max-w-[260px] rounded-2xl rounded-br-md bg-gray-900 px-3 py-2 text-sm text-white shadow-sm", children: message.content }) }, message.id);
3466
3511
  }
3467
3512
  if (message.role === "agent") {
3468
3513
  return /* @__PURE__ */ jsxs6("div", { className: `flex flex-col items-start ${isRoleChange ? "mt-3" : ""}`, children: [
3469
3514
  isRoleChange && /* @__PURE__ */ jsx10("span", { className: "text-[10px] text-gray-500 mb-1 ml-1", children: "Agent" }),
3470
- /* @__PURE__ */ jsx10("div", { className: "max-w-[260px] rounded-2xl rounded-bl-md bg-white border border-gray-200 px-3 py-2 text-xs text-gray-800 shadow-sm", children: message.content })
3515
+ /* @__PURE__ */ jsx10("div", { className: "max-w-[300px] rounded-2xl rounded-bl-md bg-gray-100 px-4 py-3 text-sm text-gray-700", children: message.content })
3471
3516
  ] }, message.id);
3472
3517
  }
3473
3518
  if (message.kind === "searchSummary") {
@@ -4525,7 +4570,7 @@ ${userText}`
4525
4570
  ] }) }) }) })
4526
4571
  }
4527
4572
  ),
4528
- /* @__PURE__ */ jsxs6("div", { className: "px-4 py-3 border-t border-gray-100 bg-gray-50/50 shrink-0", children: [
4573
+ /* @__PURE__ */ jsxs6("div", { className: "px-4 py-3 bg-white shrink-0", children: [
4529
4574
  pendingFile && /* @__PURE__ */ jsxs6("div", { className: "mb-2 flex items-center gap-2 rounded-xl bg-blue-50 border border-blue-200 px-3 py-2", children: [
4530
4575
  /* @__PURE__ */ jsx10(FileSpreadsheet, { className: "h-4 w-4 text-blue-600" }),
4531
4576
  /* @__PURE__ */ jsx10("span", { className: "text-xs text-blue-700 flex-1 truncate", children: pendingFile.name }),
@@ -4637,7 +4682,7 @@ ${userText}`
4637
4682
  {
4638
4683
  type: "submit",
4639
4684
  size: "icon",
4640
- disabled: !input.trim() && !pendingFile,
4685
+ disabled: !input.trim() && !pendingFile || isWaitingForAuth,
4641
4686
  className: "h-6 w-6 rounded-full bg-gray-900 hover:bg-gray-800 disabled:bg-gray-300",
4642
4687
  children: /* @__PURE__ */ jsx10(ArrowUp, { className: "h-2.5 w-2.5" })
4643
4688
  }
@@ -4692,9 +4737,10 @@ function ChatPanelWithToggle({
4692
4737
  orgId,
4693
4738
  userName,
4694
4739
  userEmail,
4695
- userOrganization,
4696
4740
  supabaseUrl,
4697
4741
  supabaseAnonKey,
4742
+ initialCorner,
4743
+ onCornerChange,
4698
4744
  productBackendUrl
4699
4745
  }) {
4700
4746
  const [internalIsOpen, setInternalIsOpen] = React6.useState(defaultOpen);
@@ -4705,16 +4751,6 @@ function ChatPanelWithToggle({
4705
4751
  }
4706
4752
  onOpenChange?.(open);
4707
4753
  };
4708
- React6.useEffect(() => {
4709
- const originalPadding = document.body.style.paddingRight;
4710
- const originalTransition = document.body.style.transition;
4711
- document.body.style.transition = "padding-right 0.3s ease";
4712
- document.body.style.paddingRight = isOpen ? `${PANEL_WIDTH}px` : "0px";
4713
- return () => {
4714
- document.body.style.paddingRight = originalPadding;
4715
- document.body.style.transition = originalTransition;
4716
- };
4717
- }, [isOpen]);
4718
4754
  return /* @__PURE__ */ jsx10(
4719
4755
  ChatPanel,
4720
4756
  {
@@ -4731,9 +4767,10 @@ function ChatPanelWithToggle({
4731
4767
  orgId,
4732
4768
  userName,
4733
4769
  userEmail,
4734
- userOrganization,
4735
4770
  supabaseUrl,
4736
4771
  supabaseAnonKey,
4772
+ initialCorner,
4773
+ onCornerChange,
4737
4774
  productBackendUrl
4738
4775
  }
4739
4776
  );
@@ -4806,7 +4843,6 @@ function KiteChatWrapper({
4806
4843
  orgId: config.orgId,
4807
4844
  userName: config.userName,
4808
4845
  userEmail: config.userEmail,
4809
- userOrganization: config.userOrganization,
4810
4846
  supabaseUrl: config.supabaseUrl,
4811
4847
  supabaseAnonKey: config.supabaseAnonKey,
4812
4848
  productBackendUrl: config.productBackendUrl