@xcelsior/ui-chat 2.0.3 → 2.0.4

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.
Files changed (28) hide show
  1. package/.storybook/preview.tsx +2 -1
  2. package/dist/index.js +38 -53
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +66 -81
  5. package/dist/index.mjs.map +1 -1
  6. package/package.json +3 -2
  7. package/src/components/Chat.tsx +35 -74
  8. package/src/components/ChatWidget.tsx +0 -1
  9. package/src/hooks/useMessages.ts +22 -1
  10. package/storybook-static/assets/Chat.stories-BkbpOOSG.js +830 -0
  11. package/storybook-static/assets/{Color-YHDXOIA2-BMnd3YrF.js → Color-YHDXOIA2-CSuNIR0a.js} +1 -1
  12. package/storybook-static/assets/{DocsRenderer-CFRXHY34-i_W8iCu9.js → DocsRenderer-CFRXHY34-dpuOKTQp.js} +3 -3
  13. package/storybook-static/assets/{MessageItem-DAaKZ9s9.js → MessageItem-Dlb6dSKL.js} +9 -9
  14. package/storybook-static/assets/MessageItem.stories-CsxqSqu-.js +422 -0
  15. package/storybook-static/assets/{entry-preview-oDnntGcx.js → entry-preview-C_-WO6GJ.js} +1 -1
  16. package/storybook-static/assets/{iframe-CGBtu2Se.js → iframe-BXTccXxS.js} +2 -2
  17. package/storybook-static/assets/preview-B8y-wc-n.css +1 -0
  18. package/storybook-static/assets/preview-CC4t7T7W.js +1 -0
  19. package/storybook-static/assets/{preview-BRpahs9B.js → preview-Cyx3pE7Q.js} +2 -2
  20. package/storybook-static/iframe.html +1 -1
  21. package/storybook-static/index.json +1 -1
  22. package/storybook-static/project.json +1 -1
  23. package/tsconfig.json +4 -0
  24. package/storybook-static/assets/Chat.stories-J_Yp51wU.js +0 -803
  25. package/storybook-static/assets/MessageItem.stories-Ckr1_scc.js +0 -255
  26. package/storybook-static/assets/ToastContext-Bty1K7ya.js +0 -1
  27. package/storybook-static/assets/preview-DUOvJmsz.js +0 -1
  28. package/storybook-static/assets/preview-DcGwT3kv.css +0 -1
@@ -1,8 +1,9 @@
1
1
  import '@xcelsior/design-system/styles';
2
- import type { Preview } from '@storybook/react';
2
+
3
3
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4
4
  import { ToastContainer } from '@xcelsior/design-system';
5
5
 
6
+ import type { Preview } from '@storybook/react';
6
7
  const queryClient = new QueryClient({
7
8
  defaultOptions: {
8
9
  queries: {
package/dist/index.js CHANGED
@@ -251,6 +251,7 @@ async function fetchMessages(baseUrl, params, headers) {
251
251
  }
252
252
 
253
253
  // src/hooks/useMessages.ts
254
+ var BOT_THINKING_TIMEOUT = 45e3;
254
255
  function useMessages(websocket, config) {
255
256
  const [messages, setMessages] = (0, import_react2.useState)([]);
256
257
  const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
@@ -259,6 +260,7 @@ function useMessages(websocket, config) {
259
260
  const [hasMore, setHasMore] = (0, import_react2.useState)(true);
260
261
  const [isLoadingMore, setIsLoadingMore] = (0, import_react2.useState)(false);
261
262
  const [isBotThinking, setIsBotThinking] = (0, import_react2.useState)(false);
263
+ const botThinkingTimerRef = (0, import_react2.useRef)(null);
262
264
  const { httpApiUrl, conversationId, headers, onError, toast } = config;
263
265
  const headersWithApiKey = (0, import_react2.useMemo)(
264
266
  () => ({
@@ -309,6 +311,10 @@ function useMessages(websocket, config) {
309
311
  });
310
312
  if (newMessage.senderType === "bot" || newMessage.senderType === "system") {
311
313
  setIsBotThinking(false);
314
+ if (botThinkingTimerRef.current) {
315
+ clearTimeout(botThinkingTimerRef.current);
316
+ botThinkingTimerRef.current = null;
317
+ }
312
318
  }
313
319
  onMessageReceived?.(newMessage);
314
320
  }
@@ -322,6 +328,10 @@ function useMessages(websocket, config) {
322
328
  });
323
329
  if (message.senderType === "customer") {
324
330
  setIsBotThinking(true);
331
+ if (botThinkingTimerRef.current) clearTimeout(botThinkingTimerRef.current);
332
+ botThinkingTimerRef.current = setTimeout(() => {
333
+ setIsBotThinking(false);
334
+ }, BOT_THINKING_TIMEOUT);
325
335
  }
326
336
  }, []);
327
337
  const updateMessageStatus = (0, import_react2.useCallback)((messageId, status) => {
@@ -365,6 +375,11 @@ function useMessages(websocket, config) {
365
375
  headersWithApiKey,
366
376
  onError
367
377
  ]);
378
+ (0, import_react2.useEffect)(() => {
379
+ return () => {
380
+ if (botThinkingTimerRef.current) clearTimeout(botThinkingTimerRef.current);
381
+ };
382
+ }, []);
368
383
  return {
369
384
  messages,
370
385
  addMessage,
@@ -2640,7 +2655,6 @@ function ChatWidget({
2640
2655
  })();
2641
2656
  const positionClass = resolvedPosition === "left" ? "left-4" : "right-4";
2642
2657
  const containerStyle = isFullPage ? { backgroundColor: bgColor, color: textColor } : {
2643
- position: "relative",
2644
2658
  width,
2645
2659
  height,
2646
2660
  maxHeight: "calc(100vh - 100px)",
@@ -3357,59 +3371,36 @@ function Chat({
3357
3371
  const [userInfo, setUserInfo] = (0, import_react14.useState)(null);
3358
3372
  const [conversationId, setConversationId] = (0, import_react14.useState)("");
3359
3373
  const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
3360
- const [isAnimating, setIsAnimating] = (0, import_react14.useState)(false);
3361
- const [showWidget, setShowWidget] = (0, import_react14.useState)(false);
3362
3374
  const identityMode = config.identityCollection || "progressive";
3363
3375
  const { position, isDragging, showHint, handlers } = useDraggablePosition(config.position);
3364
- const { currentState, setState: setStateRaw } = useChatWidgetState({
3376
+ const sessionInitializedRef = (0, import_react14.useRef)(false);
3377
+ const { currentState, setState } = useChatWidgetState({
3365
3378
  state,
3366
3379
  defaultState,
3367
3380
  onStateChange
3368
3381
  });
3369
- const setState = (0, import_react14.useCallback)(
3370
- (newState) => {
3371
- if (newState === "open" && currentState === "minimized") {
3372
- setShowWidget(true);
3373
- setIsAnimating(true);
3374
- setStateRaw(newState);
3375
- requestAnimationFrame(() => {
3376
- requestAnimationFrame(() => {
3377
- setIsAnimating(false);
3378
- });
3379
- });
3380
- } else if ((newState === "minimized" || newState === "closed") && currentState === "open") {
3381
- setIsAnimating(true);
3382
- setTimeout(() => {
3383
- setShowWidget(false);
3384
- setIsAnimating(false);
3385
- setStateRaw(newState);
3386
- }, 200);
3387
- } else {
3388
- setStateRaw(newState);
3389
- }
3390
- },
3391
- [currentState, setStateRaw]
3392
- );
3393
- (0, import_react14.useEffect)(() => {
3394
- if (currentState === "open") {
3395
- setShowWidget(true);
3396
- }
3397
- }, [currentState]);
3382
+ const configConversationId = config.conversationId;
3383
+ const configUserEmail = config.currentUser?.email;
3384
+ const configUserName = config.currentUser?.name;
3385
+ const configUserAvatar = config.currentUser?.avatar;
3386
+ const configUserStatus = config.currentUser?.status;
3398
3387
  (0, import_react14.useEffect)(() => {
3388
+ if (sessionInitializedRef.current) return;
3399
3389
  const initializeSession = () => {
3400
3390
  try {
3401
- if (config.currentUser?.email && config.currentUser?.name) {
3402
- const convId2 = config.conversationId || generateSessionId();
3391
+ if (configUserEmail && configUserName) {
3392
+ const convId2 = configConversationId || generateSessionId();
3403
3393
  const user = {
3404
- name: config.currentUser.name,
3405
- email: config.currentUser.email,
3406
- avatar: config.currentUser.avatar,
3394
+ name: configUserName,
3395
+ email: configUserEmail,
3396
+ avatar: configUserAvatar,
3407
3397
  type: "customer",
3408
- status: config.currentUser.status
3398
+ status: configUserStatus
3409
3399
  };
3410
3400
  setUserInfo(user);
3411
3401
  setConversationId(convId2);
3412
3402
  setIsLoading(false);
3403
+ sessionInitializedRef.current = true;
3413
3404
  return;
3414
3405
  }
3415
3406
  const storedDataJson = localStorage.getItem(`${storageKeyPrefix}_user`);
@@ -3426,23 +3417,26 @@ function Chat({
3426
3417
  setUserInfo(user);
3427
3418
  setConversationId(storedData.conversationId);
3428
3419
  setIsLoading(false);
3420
+ sessionInitializedRef.current = true;
3429
3421
  return;
3430
3422
  }
3431
3423
  }
3432
- const convId = config.conversationId || generateSessionId();
3424
+ const convId = configConversationId || generateSessionId();
3433
3425
  setConversationId(convId);
3434
3426
  if (identityMode === "progressive" || identityMode === "none") {
3435
3427
  setUserInfo(null);
3436
3428
  }
3429
+ sessionInitializedRef.current = true;
3437
3430
  } catch (error) {
3438
3431
  console.error("Error initializing chat session:", error);
3439
- setConversationId(config.conversationId || generateSessionId());
3432
+ setConversationId(configConversationId || generateSessionId());
3433
+ sessionInitializedRef.current = true;
3440
3434
  } finally {
3441
3435
  setIsLoading(false);
3442
3436
  }
3443
3437
  };
3444
3438
  initializeSession();
3445
- }, [config, storageKeyPrefix, identityMode]);
3439
+ }, [configConversationId, configUserEmail, configUserName, configUserAvatar, configUserStatus, storageKeyPrefix, identityMode]);
3446
3440
  const handlePreChatSubmit = (0, import_react14.useCallback)(
3447
3441
  (name, email) => {
3448
3442
  const convId = conversationId || generateSessionId();
@@ -3528,16 +3522,7 @@ function Chat({
3528
3522
  conversationId,
3529
3523
  currentUser: userInfo || void 0
3530
3524
  };
3531
- const widgetAnimationStyle = showWidget && !isAnimating ? {
3532
- opacity: 1,
3533
- transform: "translateY(0) scale(1)",
3534
- transition: "opacity 0.25s ease-out, transform 0.25s ease-out"
3535
- } : {
3536
- opacity: 0,
3537
- transform: "translateY(12px) scale(0.97)",
3538
- transition: "opacity 0.2s ease-in, transform 0.2s ease-in"
3539
- };
3540
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: widgetAnimationStyle, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3525
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3541
3526
  ChatWidget,
3542
3527
  {
3543
3528
  config: fullConfig,
@@ -3546,7 +3531,7 @@ function Chat({
3546
3531
  onMinimize: () => setState("minimized"),
3547
3532
  resolvedPosition: position
3548
3533
  }
3549
- ) });
3534
+ );
3550
3535
  }
3551
3536
 
3552
3537
  // src/components/TypingIndicator.tsx