@aslaluroba/help-center-react 3.0.3 → 3.0.5
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 +28 -33
- package/dist/components/shared/Button/button.d.ts +1 -2
- package/dist/components/ui/agent-response/agent-response.d.ts +1 -2
- package/dist/components/ui/header.d.ts +1 -2
- package/dist/index.css +1 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.esm.js +36039 -11175
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +35997 -11135
- package/dist/index.js.map +1 -1
- package/dist/ui/chatbot-popup/chat-window-screen/footer.d.ts +0 -2
- package/dist/ui/chatbot-popup/chat-window-screen/header.d.ts +1 -1
- package/dist/ui/chatbot-popup/chat-window-screen/index.d.ts +1 -1
- package/dist/ui/chatbot-popup/error-screen/index.d.ts +0 -1
- package/dist/ui/chatbot-popup/home-screen/card.d.ts +0 -1
- package/dist/ui/chatbot-popup/home-screen/chat-now-card.d.ts +0 -1
- package/dist/ui/chatbot-popup/home-screen/index.d.ts +0 -1
- package/dist/ui/chatbot-popup/loading-screen/index.d.ts +0 -1
- package/dist/ui/chatbot-popup/options-list-screen/expanded-option.d.ts +0 -1
- package/dist/ui/chatbot-popup/options-list-screen/header.d.ts +0 -1
- package/dist/ui/chatbot-popup/options-list-screen/index.d.ts +0 -1
- package/dist/ui/chatbot-popup/options-list-screen/option-card.d.ts +0 -1
- package/dist/ui/confirmation-modal/index.d.ts +1 -2
- package/dist/ui/floating-message.d.ts +1 -2
- package/dist/ui/help-button.d.ts +1 -2
- package/dist/ui/help-center.d.ts +1 -2
- package/dist/ui/help-popup.d.ts +1 -2
- package/dist/ui/review-dialog/index.d.ts +0 -1
- package/package.json +25 -25
- package/src/components/shared/Button/button.tsx +0 -1
- package/src/components/ui/agent-response/agent-response.tsx +0 -1
- package/src/components/ui/header.tsx +0 -1
- package/src/globals.css +1 -1
- package/src/index.ts +1 -3
- package/src/types/svg.d.ts +4 -4
- package/src/ui/chatbot-popup/chat-window-screen/footer.tsx +1 -3
- package/src/ui/chatbot-popup/chat-window-screen/header.tsx +42 -26
- package/src/ui/chatbot-popup/chat-window-screen/index.tsx +96 -99
- package/src/ui/chatbot-popup/error-screen/index.tsx +0 -1
- package/src/ui/chatbot-popup/home-screen/card.tsx +25 -25
- package/src/ui/chatbot-popup/home-screen/chat-now-card.tsx +0 -2
- package/src/ui/chatbot-popup/home-screen/index.tsx +0 -1
- package/src/ui/chatbot-popup/loading-screen/index.tsx +0 -2
- package/src/ui/chatbot-popup/options-list-screen/expanded-option.tsx +0 -1
- package/src/ui/chatbot-popup/options-list-screen/header.tsx +14 -12
- package/src/ui/chatbot-popup/options-list-screen/index.tsx +0 -1
- package/src/ui/chatbot-popup/options-list-screen/option-card.tsx +26 -19
- package/src/ui/confirmation-modal/index.tsx +0 -1
- package/src/ui/floating-message.tsx +0 -1
- package/src/ui/help-button.tsx +0 -1
- package/src/ui/help-center.tsx +29 -67
- package/src/ui/help-popup.tsx +4 -4
- package/src/ui/review-dialog/index.tsx +4 -4
- package/src/useLocalTranslation.ts +5 -5
- package/tsconfig.json +19 -8
- package/src/.DS_Store +0 -0
- package/src/styles/tailwind.css +0 -4
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
interface ChatWindowFooterProps {
|
|
3
2
|
inputMessage: string;
|
|
4
3
|
setInputMessage: (e: string) => void;
|
|
5
4
|
handleKeyDown: (e: React.KeyboardEvent) => void;
|
|
6
5
|
handleSendMessage: () => void;
|
|
7
6
|
isLoading: boolean;
|
|
8
|
-
isAblyConnected: boolean;
|
|
9
7
|
}
|
|
10
8
|
declare const ChatWindowFooter: React.FC<ChatWindowFooterProps>;
|
|
11
9
|
export default ChatWindowFooter;
|
|
@@ -7,5 +7,5 @@ interface ChatWindowProps {
|
|
|
7
7
|
needsAgent: boolean;
|
|
8
8
|
isAblyConnected: boolean;
|
|
9
9
|
}
|
|
10
|
-
export declare const ChatWindow: React.MemoExoticComponent<({ onSendMessage, messages, assistantStatus
|
|
10
|
+
export declare const ChatWindow: React.MemoExoticComponent<({ onSendMessage, messages, assistantStatus }: ChatWindowProps) => import("react/jsx-runtime").JSX.Element>;
|
|
11
11
|
export {};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
interface ConfirmationModalProps {
|
|
3
2
|
title: string;
|
|
4
3
|
message: string;
|
|
5
4
|
onCancel: () => void;
|
|
6
5
|
onConfirm: () => void;
|
|
7
6
|
}
|
|
8
|
-
declare const ConfirmationModal: ({ title, message, onCancel, onConfirm, }: ConfirmationModalProps) =>
|
|
7
|
+
declare const ConfirmationModal: ({ title, message, onCancel, onConfirm, }: ConfirmationModalProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
8
|
export default ConfirmationModal;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
interface FloatingMessageProps {
|
|
3
2
|
message: string;
|
|
4
3
|
onClose: () => void;
|
|
5
4
|
}
|
|
6
|
-
export declare function FloatingMessage({ message, onClose }: FloatingMessageProps):
|
|
5
|
+
export declare function FloatingMessage({ message, onClose }: FloatingMessageProps): import("react/jsx-runtime").JSX.Element;
|
|
7
6
|
export {};
|
package/dist/ui/help-button.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
interface HelpButtonProps {
|
|
3
2
|
onClick: () => void;
|
|
4
3
|
}
|
|
5
|
-
export declare function HelpButton({ onClick }: HelpButtonProps):
|
|
4
|
+
export declare function HelpButton({ onClick }: HelpButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
6
5
|
export {};
|
package/dist/ui/help-center.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import '../globals.css';
|
|
3
2
|
interface HelpCenterProps {
|
|
4
3
|
helpScreenId: string;
|
|
@@ -13,5 +12,5 @@ interface HelpCenterProps {
|
|
|
13
12
|
messageLabel?: string | null;
|
|
14
13
|
showHelpScreen?: boolean;
|
|
15
14
|
}
|
|
16
|
-
export declare function HelpCenter({ helpScreenId, user, showArrow, language, messageLabel, showHelpScreen, }: HelpCenterProps):
|
|
15
|
+
export declare function HelpCenter({ helpScreenId, user, showArrow, language, messageLabel, showHelpScreen, }: HelpCenterProps): import("react/jsx-runtime").JSX.Element;
|
|
17
16
|
export {};
|
package/dist/ui/help-popup.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { HelpScreenData, Message, Option } from '@/lib/types';
|
|
3
2
|
type HelpPopupProps = {
|
|
4
3
|
isOpen: boolean;
|
|
@@ -20,5 +19,5 @@ type HelpPopupProps = {
|
|
|
20
19
|
setSelectedOption: (option: Option | null) => void;
|
|
21
20
|
showHelpScreen: boolean;
|
|
22
21
|
};
|
|
23
|
-
export declare function HelpPopup({ onClose, helpScreen, status, error, onStartChat, onSendMessage, onEndChat, messages, assistantStatus, needsAgent, sessionId, selectedOption, setSelectedOption, showHelpScreen, isAblyConnected, }: HelpPopupProps):
|
|
22
|
+
export declare function HelpPopup({ onClose, helpScreen, status, error, onStartChat, onSendMessage, onEndChat, messages, assistantStatus, needsAgent, sessionId, selectedOption, setSelectedOption, showHelpScreen, isAblyConnected, }: HelpPopupProps): import("react/jsx-runtime").JSX.Element;
|
|
24
23
|
export {};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"main": "dist/index.js",
|
|
4
4
|
"module": "dist/index.esm.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
|
-
"version": "3.0.
|
|
6
|
+
"version": "3.0.5",
|
|
7
7
|
"description": "BabylAI Help Center Widget for React and Next.js",
|
|
8
8
|
"private": false,
|
|
9
9
|
"exports": {
|
|
@@ -12,15 +12,12 @@
|
|
|
12
12
|
"require": "./dist/index.js",
|
|
13
13
|
"types": "./dist/index.d.ts"
|
|
14
14
|
},
|
|
15
|
-
"./
|
|
16
|
-
"
|
|
17
|
-
"require": "./dist/react.js",
|
|
18
|
-
"types": "./dist/react.d.ts"
|
|
15
|
+
"./style.css": {
|
|
16
|
+
"default": "./dist/index.css"
|
|
19
17
|
}
|
|
20
18
|
},
|
|
21
19
|
"scripts": {
|
|
22
20
|
"build": "rollup -c",
|
|
23
|
-
"build:prod": "production rollup -c",
|
|
24
21
|
"dev": "rollup --watch --config rollup.dev.config.js",
|
|
25
22
|
"test": "jest",
|
|
26
23
|
"clean": "rimraf dist",
|
|
@@ -51,26 +48,29 @@
|
|
|
51
48
|
],
|
|
52
49
|
"author": "BabylAI",
|
|
53
50
|
"license": "MIT",
|
|
51
|
+
"sideEffects": [
|
|
52
|
+
"dist/index.css"
|
|
53
|
+
],
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@tabler/icons-react": "^3.34.0",
|
|
56
|
-
"clsx": "^2.0.0",
|
|
57
55
|
"i18next": "^23.0.0 || ^25.0.0",
|
|
58
|
-
"react": "
|
|
59
|
-
"react-dom": "
|
|
60
|
-
"react-i18next": "^13.0.0 || ^15.0.0"
|
|
61
|
-
"react-markdown": "^10.0.0",
|
|
62
|
-
"tailwind-merge": "^3.0.0"
|
|
56
|
+
"react": "^18 || ^19",
|
|
57
|
+
"react-dom": "^18 || ^19",
|
|
58
|
+
"react-i18next": "^13.0.0 || ^15.0.0"
|
|
63
59
|
},
|
|
64
60
|
"dependencies": {
|
|
65
61
|
"@ably/chat": "^0.8.0",
|
|
66
62
|
"@microsoft/signalr": "^7.0.14",
|
|
67
|
-
"
|
|
68
|
-
"
|
|
63
|
+
"@tabler/icons-react": "^3.34.1",
|
|
64
|
+
"clsx": "^2.1.1",
|
|
65
|
+
"tailwind-merge": "^3.3.1",
|
|
66
|
+
"react-markdown": "^10.1.0",
|
|
67
|
+
"ably": "^2.12.0",
|
|
68
|
+
"axios": "^1.11.0",
|
|
69
69
|
"class-variance-authority": "^0.7.1"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@babel/core": "^7.
|
|
73
|
-
"@babel/preset-env": "^7.
|
|
72
|
+
"@babel/core": "^7.28.3",
|
|
73
|
+
"@babel/preset-env": "^7.28.3",
|
|
74
74
|
"@babel/preset-react": "^7.27.1",
|
|
75
75
|
"@rollup/plugin-alias": "^5.1.1",
|
|
76
76
|
"@rollup/plugin-babel": "^6.0.4",
|
|
@@ -81,28 +81,28 @@
|
|
|
81
81
|
"@rollup/plugin-typescript": "^8.5.0",
|
|
82
82
|
"@rollup/plugin-url": "^8.0.2",
|
|
83
83
|
"@svgr/rollup": "^8.1.0",
|
|
84
|
-
"@tabler/icons-react": "^3.34.
|
|
84
|
+
"@tabler/icons-react": "^3.34.1",
|
|
85
85
|
"@types/hast": "^3.0.4",
|
|
86
86
|
"@types/node": "^16.18.126",
|
|
87
|
-
"@types/react": "^
|
|
87
|
+
"@types/react": "^18.3.0",
|
|
88
|
+
"@types/react-dom": "^18.3.0",
|
|
88
89
|
"autoprefixer": "^10.4.21",
|
|
89
90
|
"babel-loader": "^10.0.0",
|
|
90
91
|
"clsx": "^2.1.1",
|
|
91
|
-
"concurrently": "^9.
|
|
92
|
-
"i18next": "^25.2
|
|
92
|
+
"concurrently": "^9.2.0",
|
|
93
|
+
"i18next": "^25.4.2",
|
|
93
94
|
"postcss": "^8.5.6",
|
|
94
|
-
"react-i18next": "^15.
|
|
95
|
+
"react-i18next": "^15.7.2",
|
|
95
96
|
"react-markdown": "^10.1.0",
|
|
96
97
|
"rimraf": "^6.0.1",
|
|
97
98
|
"rollup": "^2.79.2",
|
|
98
99
|
"rollup-plugin-postcss": "^4.0.2",
|
|
99
|
-
"tailwind-merge": "^3.3.1",
|
|
100
100
|
"tailwindcss": "^3.3.2",
|
|
101
101
|
"tailwindcss-animate": "^1.0.7",
|
|
102
102
|
"tailwindcss-rtl": "^0.9.0",
|
|
103
103
|
"tslib": "^2.8.1",
|
|
104
|
-
"typescript": "^5.
|
|
105
|
-
"webpack": "^5.
|
|
104
|
+
"typescript": "^5.9.2",
|
|
105
|
+
"webpack": "^5.101.3"
|
|
106
106
|
},
|
|
107
107
|
"publishConfig": {
|
|
108
108
|
"access": "public"
|
package/src/globals.css
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { configService } from './lib/config';
|
|
2
|
-
import { HelpCenter } from './ui/help-center';
|
|
3
2
|
import { TokenResponse } from './lib/types';
|
|
4
3
|
|
|
5
4
|
export type HelpCenterConfig = {
|
|
@@ -12,11 +11,10 @@ export function initializeHelpCenter(config: HelpCenterConfig) {
|
|
|
12
11
|
configService.initialize(config);
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
export { HelpCenter };
|
|
14
|
+
export { HelpCenter } from './ui/help-center';
|
|
16
15
|
|
|
17
16
|
export * from './lib/types';
|
|
18
17
|
export * from './core/ApiService';
|
|
19
18
|
export * from './core/AblyService';
|
|
20
|
-
// export * from './globals.css'
|
|
21
19
|
|
|
22
20
|
export { TokenService } from './core/token-service';
|
package/src/types/svg.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
declare module
|
|
2
|
-
import
|
|
3
|
-
const SVG:
|
|
4
|
-
export default SVG
|
|
1
|
+
declare module "*.svg" {
|
|
2
|
+
import type { FC, SVGProps } from "react";
|
|
3
|
+
const SVG: FC<SVGProps<SVGSVGElement> & { title?: string }>;
|
|
4
|
+
export default SVG;
|
|
5
5
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Button } from '@/components';
|
|
2
|
-
import React from 'react';
|
|
3
2
|
import EnvelopeIcon from './../../../assets/icons/envelope.svg';
|
|
4
3
|
import { useLocalTranslation } from '../../../useLocalTranslation';
|
|
5
4
|
|
|
@@ -9,7 +8,6 @@ interface ChatWindowFooterProps {
|
|
|
9
8
|
handleKeyDown: (e: React.KeyboardEvent) => void;
|
|
10
9
|
handleSendMessage: () => void;
|
|
11
10
|
isLoading: boolean;
|
|
12
|
-
isAblyConnected: boolean;
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
const ChatWindowFooter: React.FC<ChatWindowFooterProps> = (props) => {
|
|
@@ -28,7 +26,7 @@ const ChatWindowFooter: React.FC<ChatWindowFooterProps> = (props) => {
|
|
|
28
26
|
variant='default'
|
|
29
27
|
size='icon'
|
|
30
28
|
onClick={props.handleSendMessage}
|
|
31
|
-
disabled={props?.isLoading
|
|
29
|
+
disabled={props?.isLoading}
|
|
32
30
|
className='babylai-rounded-full babylai-bg-purple-500 babylai-hover:babylai-bg-purple-600 babylai-w-8 babylai-h-8 babylai-disabled:babylai-opacity-50'
|
|
33
31
|
>
|
|
34
32
|
<EnvelopeIcon className={`babylai-w-4 babylai-h-4 ${dir === 'rtl' ? 'babylai-rotate-270' : ''}`} />
|
|
@@ -1,48 +1,64 @@
|
|
|
1
|
-
import Logo from
|
|
2
|
-
import { Button } from
|
|
3
|
-
import React, { useState } from
|
|
4
|
-
import ArrowRight from
|
|
5
|
-
import ThreeDots from
|
|
6
|
-
import { useLocalTranslation } from
|
|
1
|
+
import Logo from "../../../assets/logo_ai.svg";
|
|
2
|
+
import { Button } from "@/components";
|
|
3
|
+
import React, { useState } from "react";
|
|
4
|
+
import ArrowRight from "./../../../assets/icons/arrowRight.svg";
|
|
5
|
+
import ThreeDots from "./../../../assets/icons/threeDots.svg";
|
|
6
|
+
import { useLocalTranslation } from "../../../useLocalTranslation";
|
|
7
7
|
|
|
8
8
|
interface ChatWindowHeaderProps {
|
|
9
|
-
isShowList: boolean
|
|
10
|
-
setIsShowList?: (isShowList: boolean) => void
|
|
11
|
-
showChat: boolean
|
|
12
|
-
onClose: () => void
|
|
13
|
-
handleBack: () => void
|
|
14
|
-
handleEndChat: () => void
|
|
9
|
+
isShowList: boolean;
|
|
10
|
+
setIsShowList?: (isShowList: boolean) => void;
|
|
11
|
+
showChat: boolean;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
handleBack: () => void;
|
|
14
|
+
handleEndChat: () => void;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const ChatWindowHeader: React.FC<ChatWindowHeaderProps> = (props) => {
|
|
18
|
-
const [showMenu, setShowMenu] = useState(false)
|
|
19
|
-
const { t,
|
|
20
|
-
const isRTL =
|
|
18
|
+
const [showMenu, setShowMenu] = useState(false);
|
|
19
|
+
const { t, dir } = useLocalTranslation();
|
|
20
|
+
const isRTL = dir === "rtl";
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
23
|
<header className="babylai-flex babylai-w-full babylai-items-center babylai-py-[18px] babylai-px-[18px] babylai-justify-between babylai-relative babylai-bg-black-white-50 dark:!babylai-bg-storm-dust-900 babylai-rounded-t-3xl">
|
|
24
24
|
<div className="babylai-flex babylai-items-center babylai-gap-2">
|
|
25
|
-
<Button
|
|
26
|
-
|
|
25
|
+
<Button
|
|
26
|
+
variant="rounded-icon"
|
|
27
|
+
size="icon"
|
|
28
|
+
className="babylai-bg-primary-500/10 dark:babylai-bg-storm-dust-950"
|
|
29
|
+
onClick={props.handleBack}
|
|
30
|
+
>
|
|
31
|
+
<ArrowRight
|
|
32
|
+
className={`!babylai-w-[12px] babylai-h-[12px] ${isRTL ? "" : "babylai-rotate-180"} babylai-text-primary-500 dark:babylai-text-white`}
|
|
33
|
+
/>{" "}
|
|
27
34
|
</Button>
|
|
28
35
|
<div className="babylai-relative babylai-mr-2">
|
|
29
|
-
<Button
|
|
36
|
+
<Button
|
|
37
|
+
variant="rounded-icon"
|
|
38
|
+
size="icon"
|
|
39
|
+
className="babylai-bg-primary-500/10 dark:babylai-bg-storm-dust-950"
|
|
40
|
+
onClick={() => setShowMenu(!showMenu)}
|
|
41
|
+
>
|
|
30
42
|
<ThreeDots className="babylai-w-[14px] babylai-h-[4px] babylai-text-primary-500 dark:babylai-text-white" />
|
|
31
43
|
</Button>
|
|
32
44
|
|
|
33
45
|
{showMenu && (
|
|
34
46
|
<div className="babylai-absolute babylai-top-10 babylai-start-0 babylai-w-48 babylai-rounded-md babylai-shadow-lg babylai-bg-white dark:!babylai-bg-storm-dust-950 babylai-ring-1 babylai-ring-black babylai-ring-opacity-5 babylai-z-10">
|
|
35
|
-
<div
|
|
47
|
+
<div
|
|
48
|
+
className="babylai-py-1"
|
|
49
|
+
role="menu"
|
|
50
|
+
aria-orientation="vertical"
|
|
51
|
+
>
|
|
36
52
|
<button
|
|
37
53
|
className="babylai-block babylai-px-4 babylai-py-2 babylai-text-sm babylai-text-gray-700 dark:babylai-text-white babylai-hover:babylai-bg-gray-100 babylai-w-full babylai-text-left"
|
|
38
54
|
role="menuitem"
|
|
39
55
|
onClick={(e) => {
|
|
40
|
-
e.stopPropagation()
|
|
41
|
-
props.handleEndChat()
|
|
42
|
-
setShowMenu(false)
|
|
56
|
+
e.stopPropagation();
|
|
57
|
+
props.handleEndChat();
|
|
58
|
+
setShowMenu(false);
|
|
43
59
|
}}
|
|
44
60
|
>
|
|
45
|
-
{t(
|
|
61
|
+
{t("homeSdk.endChat")}
|
|
46
62
|
</button>
|
|
47
63
|
</div>
|
|
48
64
|
</div>
|
|
@@ -53,6 +69,6 @@ const ChatWindowHeader: React.FC<ChatWindowHeaderProps> = (props) => {
|
|
|
53
69
|
<Logo className="babylai-w-[124px] babylai-h-auto dark:babylai-text-white" />
|
|
54
70
|
</div>
|
|
55
71
|
</header>
|
|
56
|
-
)
|
|
57
|
-
}
|
|
58
|
-
export default ChatWindowHeader
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
export default ChatWindowHeader;
|
|
@@ -93,114 +93,111 @@ const TypingIndicator = React.memo(({ firstHumanAgentIndex }: { firstHumanAgentI
|
|
|
93
93
|
|
|
94
94
|
TypingIndicator.displayName = 'TypingIndicator';
|
|
95
95
|
|
|
96
|
-
export const ChatWindow = React.memo(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
96
|
+
export const ChatWindow = React.memo(({ onSendMessage, messages, assistantStatus = 'loading' }: ChatWindowProps) => {
|
|
97
|
+
const [inputMessage, setInputMessage] = useState('');
|
|
98
|
+
const messagesEndRef = useRef<HTMLDivElement>(null);
|
|
99
|
+
const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
100
|
+
const lastMessageCountRef = useRef(messages.length);
|
|
101
|
+
|
|
102
|
+
// Debounced scroll to bottom function
|
|
103
|
+
const scrollToBottom = useCallback(() => {
|
|
104
|
+
if (scrollTimeoutRef.current) {
|
|
105
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
scrollTimeoutRef.current = setTimeout(() => {
|
|
109
|
+
messagesEndRef.current?.scrollIntoView({
|
|
110
|
+
behavior: 'smooth',
|
|
111
|
+
block: 'end',
|
|
112
|
+
});
|
|
113
|
+
}, 100);
|
|
114
|
+
}, []);
|
|
115
|
+
|
|
116
|
+
// Only scroll when new messages are added or status changes
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (messages.length !== lastMessageCountRef.current || assistantStatus === 'typing') {
|
|
119
|
+
lastMessageCountRef.current = messages.length;
|
|
120
|
+
scrollToBottom();
|
|
121
|
+
}
|
|
122
|
+
}, [messages.length, assistantStatus, scrollToBottom]);
|
|
123
|
+
|
|
124
|
+
// Cleanup timeout on unmount
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
return () => {
|
|
105
127
|
if (scrollTimeoutRef.current) {
|
|
106
128
|
clearTimeout(scrollTimeoutRef.current);
|
|
107
129
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
// Cleanup timeout on unmount
|
|
126
|
-
useEffect(() => {
|
|
127
|
-
return () => {
|
|
128
|
-
if (scrollTimeoutRef.current) {
|
|
129
|
-
clearTimeout(scrollTimeoutRef.current);
|
|
130
|
+
};
|
|
131
|
+
}, []);
|
|
132
|
+
|
|
133
|
+
const handleSendMessage = useCallback(() => {
|
|
134
|
+
if (inputMessage.trim()) {
|
|
135
|
+
onSendMessage(inputMessage);
|
|
136
|
+
setInputMessage('');
|
|
137
|
+
}
|
|
138
|
+
}, [inputMessage, onSendMessage]);
|
|
139
|
+
|
|
140
|
+
const handleKeyDown = useCallback(
|
|
141
|
+
(e: React.KeyboardEvent) => {
|
|
142
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
143
|
+
e.preventDefault();
|
|
144
|
+
if (inputMessage.trim() && assistantStatus !== 'typing') {
|
|
145
|
+
onSendMessage(inputMessage);
|
|
146
|
+
setInputMessage('');
|
|
130
147
|
}
|
|
131
|
-
};
|
|
132
|
-
}, []);
|
|
133
|
-
|
|
134
|
-
const handleSendMessage = useCallback(() => {
|
|
135
|
-
if (inputMessage.trim()) {
|
|
136
|
-
onSendMessage(inputMessage);
|
|
137
|
-
setInputMessage('');
|
|
138
148
|
}
|
|
139
|
-
},
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
(e: React.KeyboardEvent) => {
|
|
143
|
-
if (e.key === 'Enter' && !e.shiftKey && isAblyConnected) {
|
|
144
|
-
e.preventDefault();
|
|
145
|
-
if (inputMessage.trim() && assistantStatus !== 'typing') {
|
|
146
|
-
onSendMessage(inputMessage);
|
|
147
|
-
setInputMessage('');
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
[inputMessage, onSendMessage, assistantStatus, isAblyConnected]
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
// Memoize the first human agent index calculation
|
|
155
|
-
const firstHumanAgentIndex = useMemo(() => {
|
|
156
|
-
return messages.findIndex((message) => message.senderType === 2);
|
|
157
|
-
}, [messages]);
|
|
158
|
-
|
|
159
|
-
// Memoize the message list to prevent unnecessary re-renders
|
|
160
|
-
const messagesList = useMemo(() => {
|
|
161
|
-
return messages.map((message, index) => (
|
|
162
|
-
<MessageComponent
|
|
163
|
-
key={`${message.id}-${index}`}
|
|
164
|
-
message={message}
|
|
165
|
-
index={index}
|
|
166
|
-
messages={messages}
|
|
167
|
-
firstHumanAgentIndex={firstHumanAgentIndex}
|
|
168
|
-
onType={scrollToBottom}
|
|
169
|
-
/>
|
|
170
|
-
));
|
|
171
|
-
}, [messages, firstHumanAgentIndex, scrollToBottom]);
|
|
172
|
-
|
|
173
|
-
// Memoize loading state check
|
|
174
|
-
const isLoading = useMemo(() => {
|
|
175
|
-
return (
|
|
176
|
-
assistantStatus === 'typing' ||
|
|
177
|
-
assistantStatus === 'loading' ||
|
|
178
|
-
assistantStatus === 'error' ||
|
|
179
|
-
inputMessage.trim() === ''
|
|
180
|
-
);
|
|
181
|
-
}, [assistantStatus, inputMessage]);
|
|
149
|
+
},
|
|
150
|
+
[inputMessage, onSendMessage, assistantStatus]
|
|
151
|
+
);
|
|
182
152
|
|
|
153
|
+
// Memoize the first human agent index calculation
|
|
154
|
+
const firstHumanAgentIndex = useMemo(() => {
|
|
155
|
+
return messages.findIndex((message) => message.senderType === 2);
|
|
156
|
+
}, [messages]);
|
|
157
|
+
|
|
158
|
+
// Memoize the message list to prevent unnecessary re-renders
|
|
159
|
+
const messagesList = useMemo(() => {
|
|
160
|
+
return messages.map((message, index) => (
|
|
161
|
+
<MessageComponent
|
|
162
|
+
key={`${message.id}-${index}`}
|
|
163
|
+
message={message}
|
|
164
|
+
index={index}
|
|
165
|
+
messages={messages}
|
|
166
|
+
firstHumanAgentIndex={firstHumanAgentIndex}
|
|
167
|
+
onType={scrollToBottom}
|
|
168
|
+
/>
|
|
169
|
+
));
|
|
170
|
+
}, [messages, firstHumanAgentIndex, scrollToBottom]);
|
|
171
|
+
|
|
172
|
+
// Memoize loading state check
|
|
173
|
+
const isLoading = useMemo(() => {
|
|
183
174
|
return (
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
175
|
+
assistantStatus === 'typing' ||
|
|
176
|
+
assistantStatus === 'loading' ||
|
|
177
|
+
assistantStatus === 'error' ||
|
|
178
|
+
inputMessage.trim() === ''
|
|
179
|
+
);
|
|
180
|
+
}, [assistantStatus, inputMessage]);
|
|
187
181
|
|
|
188
|
-
|
|
182
|
+
return (
|
|
183
|
+
<>
|
|
184
|
+
<div className='babylai-flex-1 babylai-overflow-y-auto babylai-p-4 babylai-h-full'>
|
|
185
|
+
{messagesList}
|
|
189
186
|
|
|
190
|
-
|
|
191
|
-
</div>
|
|
187
|
+
{assistantStatus === 'typing' && <TypingIndicator firstHumanAgentIndex={firstHumanAgentIndex} />}
|
|
192
188
|
|
|
193
|
-
<
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
);
|
|
189
|
+
<div ref={messagesEndRef} />
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
<ChatWindowFooter
|
|
193
|
+
inputMessage={inputMessage}
|
|
194
|
+
handleKeyDown={handleKeyDown}
|
|
195
|
+
handleSendMessage={handleSendMessage}
|
|
196
|
+
setInputMessage={setInputMessage}
|
|
197
|
+
isLoading={isLoading}
|
|
198
|
+
/>
|
|
199
|
+
</>
|
|
200
|
+
);
|
|
201
|
+
});
|
|
205
202
|
|
|
206
203
|
ChatWindow.displayName = 'ChatWindow';
|