@aslaluroba/help-center-react 3.2.5 → 3.2.6

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 (97) hide show
  1. package/README.md +0 -3
  2. package/dist/components/shared/Button/button.d.ts +3 -3
  3. package/dist/components/ui/index.d.ts +0 -1
  4. package/dist/core/api.d.ts +4 -4
  5. package/dist/index.css +1 -1
  6. package/dist/index.esm.js +15543 -15136
  7. package/dist/index.esm.js.map +1 -1
  8. package/dist/index.js +15546 -15145
  9. package/dist/index.js.map +1 -1
  10. package/dist/lib/theme-utils.d.ts +0 -9
  11. package/dist/lib/types.d.ts +6 -3
  12. package/dist/services.esm.js +9474 -9222
  13. package/dist/services.esm.js.map +1 -1
  14. package/dist/services.js +9472 -9222
  15. package/dist/services.js.map +1 -1
  16. package/dist/ui/chatbot-popup/active-chat-actions.d.ts +7 -0
  17. package/dist/ui/chatbot-popup/chat-window-screen/action-button.d.ts +10 -0
  18. package/dist/ui/chatbot-popup/chat-window-screen/footer.d.ts +1 -0
  19. package/dist/ui/chatbot-popup/chat-window-screen/header.d.ts +2 -5
  20. package/dist/ui/chatbot-popup/chat-window-screen/in-chat-review.d.ts +9 -0
  21. package/dist/ui/chatbot-popup/chat-window-screen/index.d.ts +7 -3
  22. package/dist/ui/chatbot-popup/chat-window-screen/typing-indicator.d.ts +6 -0
  23. package/dist/ui/chatbot-popup/error-screen/index.d.ts +0 -1
  24. package/dist/ui/chatbot-popup/loading-screen/index.d.ts +0 -2
  25. package/dist/ui/chatbot-popup/options-list-screen/company-card.d.ts +9 -0
  26. package/dist/ui/chatbot-popup/options-list-screen/header.d.ts +1 -2
  27. package/dist/ui/chatbot-popup/options-list-screen/helpscreen-intro.d.ts +6 -0
  28. package/dist/ui/chatbot-popup/options-list-screen/helpscreen-list.d.ts +10 -0
  29. package/dist/ui/chatbot-popup/options-list-screen/helpscreen-option.d.ts +9 -0
  30. package/dist/ui/chatbot-popup/options-list-screen/index.d.ts +1 -4
  31. package/dist/ui/help-center.d.ts +2 -5
  32. package/dist/ui/help-popup.d.ts +16 -7
  33. package/dist/ui/review-dialog/index.d.ts +2 -1
  34. package/package.json +35 -29
  35. package/src/components/shared/Button/button.tsx +11 -18
  36. package/src/components/shared/Card/card.tsx +8 -8
  37. package/src/components/ui/agent-response/agent-response.tsx +4 -4
  38. package/src/components/ui/image-attachment.tsx +8 -8
  39. package/src/components/ui/image-preview-dialog.tsx +41 -41
  40. package/src/components/ui/index.ts +0 -1
  41. package/src/core/AblyService.ts +22 -17
  42. package/src/core/api.ts +9 -7
  43. package/src/globals.css +216 -50
  44. package/src/lib/theme-utils.ts +1 -33
  45. package/src/lib/types.ts +7 -4
  46. package/src/locales/ar.json +16 -6
  47. package/src/locales/en.json +16 -6
  48. package/src/types/icons.d.ts +6 -0
  49. package/src/ui/chatbot-popup/active-chat-actions.tsx +39 -0
  50. package/src/ui/chatbot-popup/chat-window-screen/action-button.tsx +37 -0
  51. package/src/ui/chatbot-popup/chat-window-screen/footer.tsx +42 -43
  52. package/src/ui/chatbot-popup/chat-window-screen/header.tsx +34 -67
  53. package/src/ui/chatbot-popup/chat-window-screen/in-chat-review.tsx +83 -0
  54. package/src/ui/chatbot-popup/chat-window-screen/index.tsx +49 -42
  55. package/src/ui/chatbot-popup/chat-window-screen/typing-indicator.tsx +27 -0
  56. package/src/ui/chatbot-popup/error-screen/index.tsx +7 -7
  57. package/src/ui/chatbot-popup/loading-screen/index.tsx +6 -17
  58. package/src/ui/chatbot-popup/options-list-screen/company-card.tsx +37 -0
  59. package/src/ui/chatbot-popup/options-list-screen/header.tsx +12 -31
  60. package/src/ui/chatbot-popup/options-list-screen/helpscreen-intro.tsx +32 -0
  61. package/src/ui/chatbot-popup/options-list-screen/helpscreen-list.tsx +48 -0
  62. package/src/ui/chatbot-popup/options-list-screen/helpscreen-option.tsx +38 -0
  63. package/src/ui/chatbot-popup/options-list-screen/index.tsx +44 -38
  64. package/src/ui/confirmation-modal/index.tsx +27 -12
  65. package/src/ui/floating-message.tsx +8 -7
  66. package/src/ui/help-button.tsx +5 -5
  67. package/src/ui/help-center.tsx +71 -59
  68. package/src/ui/help-popup.tsx +114 -91
  69. package/src/ui/powered-by.tsx +49 -7
  70. package/src/ui/review-dialog/index.tsx +48 -65
  71. package/src/ui/review-dialog/rating.tsx +7 -7
  72. package/dist/components/ui/header.d.ts +0 -6
  73. package/dist/ui/chatbot-popup/home-screen/card.d.ts +0 -6
  74. package/dist/ui/chatbot-popup/home-screen/chat-now-card.d.ts +0 -5
  75. package/dist/ui/chatbot-popup/home-screen/index.d.ts +0 -7
  76. package/dist/ui/chatbot-popup/options-list-screen/expanded-option.d.ts +0 -7
  77. package/dist/ui/chatbot-popup/options-list-screen/option-card.d.ts +0 -5
  78. package/src/assets/icons/arrowRight.svg +0 -3
  79. package/src/assets/icons/chat.svg +0 -4
  80. package/src/assets/icons/close.svg +0 -1
  81. package/src/assets/icons/closeCircle.svg +0 -3
  82. package/src/assets/icons/closeCirclePrimary.svg +0 -4
  83. package/src/assets/icons/envelope.svg +0 -3
  84. package/src/assets/icons/paperclip.svg +0 -3
  85. package/src/assets/icons/threeDots.svg +0 -3
  86. package/src/assets/icons/user.svg +0 -3
  87. package/src/assets/icons/x.svg +0 -4
  88. package/src/assets/logoColors.svg +0 -5
  89. package/src/assets/logo_ai.svg +0 -14
  90. package/src/assets/thinking-logo.svg +0 -3
  91. package/src/components/ui/header.tsx +0 -22
  92. package/src/ui/chatbot-popup/home-screen/card.tsx +0 -33
  93. package/src/ui/chatbot-popup/home-screen/chat-now-card.tsx +0 -36
  94. package/src/ui/chatbot-popup/home-screen/index.tsx +0 -44
  95. package/src/ui/chatbot-popup/options-list-screen/expanded-option.tsx +0 -37
  96. package/src/ui/chatbot-popup/options-list-screen/option-card.tsx +0 -31
  97. /package/src/assets/{icons/seperator.svg → seperator.svg} +0 -0
@@ -1,17 +1,14 @@
1
- import { cn } from '@/lib';
2
1
  import { ChatWindow } from '@/ui/chatbot-popup/chat-window-screen';
3
2
  import ChatWindowHeader from '@/ui/chatbot-popup/chat-window-screen/header';
4
3
  import ChatBotErrorScreen from '@/ui/chatbot-popup/error-screen';
5
- import HomeScreen from '@/ui/chatbot-popup/home-screen';
6
4
  import ChatBotLoadingScreen from '@/ui/chatbot-popup/loading-screen';
7
5
  import OptionsListScreen from '@/ui/chatbot-popup/options-list-screen';
6
+ import { ActiveChatActions } from '@/ui/chatbot-popup/active-chat-actions';
8
7
  import { useEffect, useRef, useState, useCallback, useMemo } from 'react';
9
- import ChatIcon from '../assets/icons/chat.svg';
10
- import { Button } from '@/components';
11
- import { HelpScreenData, Message, Option } from '@/lib/types';
8
+ import { HelpScreenData, Message, Option, ReviewProps } from '@/lib/types';
12
9
  import { useLocalTranslation } from '../useLocalTranslation';
13
10
  import ConfirmationModal from './confirmation-modal';
14
- import PoweredBy from './powered-by';
11
+ import ReviewDialog from './review-dialog';
15
12
 
16
13
  type HelpPopupProps = {
17
14
  isOpen: boolean;
@@ -19,24 +16,32 @@ type HelpPopupProps = {
19
16
  helpScreen: HelpScreenData | null;
20
17
  status: string;
21
18
  error: string | null;
22
- user: any;
19
+ user: unknown;
23
20
  onStartChat: (option: Option) => void;
24
21
  onSendMessage: (message: string, attachmentIds: string[]) => void;
25
22
  onEnsureSession: () => Promise<string>;
26
- onEndChat: (option?: Option) => void;
23
+ onEndChat: (options?: { fromChatScreen?: boolean }) => void | Promise<void>;
27
24
  messages: Message[];
28
25
  needsAgent: boolean;
29
26
  assistantStatus: string;
30
27
  sessionId: string | null;
31
28
  isChatClosed: boolean;
32
- isAblyConnected: boolean;
33
29
  selectedOption: Option | null;
34
30
  setSelectedOption: (option: Option | null) => void;
35
- showHelpScreen: boolean;
36
- logoUrl?: string;
31
+ inChatReviewSessionId?: string | null;
32
+ onInChatReviewSubmit?: (payload: ReviewProps) => void | Promise<void>;
33
+ onInChatReviewDone?: () => void;
34
+ navigateToOptionsListAfterReview?: boolean;
35
+ onNavigatedToOptionsList?: () => void;
36
+ isReviewDialogOpen?: boolean;
37
+ reviewSessionId?: string | null;
38
+ isSubmittingReview?: boolean;
39
+ onReviewDialogSubmit?: (payload: ReviewProps) => void | Promise<void>;
40
+ onReviewDialogClose?: () => void;
37
41
  };
38
42
 
39
43
  const HelpPopup = ({
44
+ isOpen,
40
45
  onClose,
41
46
  helpScreen,
42
47
  status,
@@ -49,21 +54,28 @@ const HelpPopup = ({
49
54
  assistantStatus,
50
55
  needsAgent,
51
56
  sessionId,
57
+ isChatClosed,
52
58
  selectedOption,
53
59
  setSelectedOption,
54
- showHelpScreen,
55
- isAblyConnected,
56
- logoUrl,
60
+ inChatReviewSessionId = null,
61
+ onInChatReviewSubmit,
62
+ onInChatReviewDone,
63
+ navigateToOptionsListAfterReview = false,
64
+ onNavigatedToOptionsList,
65
+ isReviewDialogOpen = false,
66
+ reviewSessionId = null,
67
+ isSubmittingReview = false,
68
+ onReviewDialogSubmit,
69
+ onReviewDialogClose,
57
70
  }: HelpPopupProps) => {
58
71
  // ALL HOOKS MUST BE CALLED FIRST - BEFORE ANY EARLY RETURNS
59
72
  const [showChat, setShowChat] = useState(false);
60
- const [isShowList, setIsShowList] = useState<boolean>(!showHelpScreen || false);
61
- const [expandedOption, setExpandedOption] = useState<Option | null>(null);
62
73
  const [endChatConfirmation, setEndChatConfirmation] = useState<boolean>(false);
63
74
  const [startNewChatConfirmation, setStartNewChatConfirmation] = useState<boolean>(false);
64
75
  const [tempSelectedOption, setTempSelectedOption] = useState<Option | null>(null);
65
76
 
66
77
  const chatBoxRef = useRef<HTMLDivElement>(null);
78
+ const prevIsOpenRef = useRef(false);
67
79
  const { t } = useLocalTranslation();
68
80
  const messagesRef = useRef<Message[]>([]);
69
81
 
@@ -92,8 +104,6 @@ const HelpPopup = ({
92
104
  // onEndChat()
93
105
  } else if (selectedOption) {
94
106
  setSelectedOption(null);
95
- } else {
96
- setIsShowList(false);
97
107
  }
98
108
  }, [showChat, selectedOption, setSelectedOption]);
99
109
 
@@ -131,29 +141,34 @@ const HelpPopup = ({
131
141
  if (tempSelectedOption) {
132
142
  setStartNewChatConfirmation(false);
133
143
 
134
- await handleEndChat()
135
- .then(() => {
136
- setShowChat(true);
137
- onStartChat(tempSelectedOption);
138
- setSelectedOption(tempSelectedOption);
139
- })
140
- .finally(() => {
141
- setTempSelectedOption(null);
142
- });
144
+ await onEndChat();
145
+ setShowChat(true);
146
+ onStartChat(tempSelectedOption);
147
+ setSelectedOption(tempSelectedOption);
148
+ setTempSelectedOption(null);
143
149
  }
144
150
  };
145
151
 
146
- const handleEndChat = async () => {
152
+ const handleEndChatFromChatScreen = useCallback(async () => {
147
153
  setEndChatConfirmation(false);
148
- await onEndChat();
149
- setShowChat(false);
150
- setSelectedOption(null);
151
- };
154
+ await onEndChat({ fromChatScreen: true });
155
+ // Keep showChat and selectedOption so chat screen stays open with in-chat review
156
+ }, [onEndChat]);
157
+
158
+ const handleMinimize = useCallback(() => {
159
+ onClose();
160
+ }, [onClose]);
152
161
 
153
162
  const handleShowActiveChat = useCallback(() => {
154
163
  setShowChat(true);
155
164
  }, []);
156
165
 
166
+ const handleEndChatFromActiveActions = useCallback(async () => {
167
+ await onEndChat();
168
+ setShowChat(false);
169
+ setSelectedOption(null);
170
+ }, [onEndChat, setSelectedOption]);
171
+
157
172
  // Memoize render content function
158
173
  const renderContent = useCallback(() => {
159
174
  if (showChat && selectedOption) {
@@ -162,11 +177,8 @@ const HelpPopup = ({
162
177
  <ChatWindowHeader
163
178
  handleBack={handleBack}
164
179
  handleEndChat={showEndChatConfirmation}
165
- onClose={onClose}
166
- isShowList={isShowList}
167
- showChat={showChat}
168
- setIsShowList={setIsShowList}
169
- logoUrl={logoUrl}
180
+ handleMinimize={handleMinimize}
181
+ optionTitle={selectedOption?.title}
170
182
  />
171
183
  <ChatWindow
172
184
  onSendMessage={handleSendMessage}
@@ -174,49 +186,46 @@ const HelpPopup = ({
174
186
  messages={memoizedMessages}
175
187
  assistantStatus={assistantStatus}
176
188
  needsAgent={needsAgent}
177
- isAblyConnected={isAblyConnected}
178
189
  sessionId={sessionId}
190
+ isChatClosed={isChatClosed}
191
+ inChatReviewSessionId={inChatReviewSessionId ?? undefined}
192
+ isSubmittingReview={isSubmittingReview}
193
+ onInChatReviewSubmit={onInChatReviewSubmit}
194
+ onInChatReviewDone={onInChatReviewDone}
179
195
  />
180
196
  </>
181
197
  );
182
198
  }
183
199
 
184
- if (isShowList) {
185
- return (
186
- <OptionsListScreen
187
- helpScreen={helpScreen}
188
- expandedOption={expandedOption}
189
- setExpandedOption={setExpandedOption}
190
- handleStartChat={handleStartChat}
191
- handleBack={showHelpScreen ? handleBack : onClose}
192
- showHelpScreen={showHelpScreen}
193
- />
194
- );
195
- }
196
- return <HomeScreen setIsShowList={setIsShowList} onClose={onClose} logoUrl={logoUrl} />;
200
+ return (
201
+ <OptionsListScreen
202
+ helpScreen={helpScreen}
203
+ handleStartChat={handleStartChat}
204
+ handleMinimize={handleMinimize}
205
+ />
206
+ );
197
207
  }, [
198
208
  showChat,
199
209
  selectedOption,
200
210
  handleBack,
201
211
  showEndChatConfirmation,
202
- onClose,
203
- isShowList,
204
- setIsShowList,
205
212
  handleSendMessage,
206
213
  onEnsureSession,
207
214
  memoizedMessages,
208
215
  assistantStatus,
209
216
  needsAgent,
210
217
  helpScreen,
211
- expandedOption,
212
- setExpandedOption,
213
218
  handleStartChat,
214
- showHelpScreen,
215
- isAblyConnected,
216
- logoUrl,
219
+ handleMinimize,
220
+ sessionId,
221
+ isChatClosed,
222
+ inChatReviewSessionId,
223
+ isSubmittingReview,
224
+ onInChatReviewSubmit,
225
+ onInChatReviewDone,
217
226
  ]);
218
227
 
219
- // Memoize confirmation modal
228
+ // Memoize confirmation modal (End Chat from chat screen → keep chat open, show in-chat review)
220
229
  const confirmationModal = useMemo(() => {
221
230
  if (!endChatConfirmation) return null;
222
231
 
@@ -225,26 +234,40 @@ const HelpPopup = ({
225
234
  title={t('homeSdk.ConfirmationModal.title')}
226
235
  message={t('homeSdk.ConfirmationModal.message')}
227
236
  onCancel={hideEndChatConfirmation}
228
- onConfirm={handleEndChat}
237
+ onConfirm={handleEndChatFromChatScreen}
229
238
  />
230
239
  );
231
- }, [endChatConfirmation, t, hideEndChatConfirmation, handleEndChat]);
240
+ }, [endChatConfirmation, t, hideEndChatConfirmation, handleEndChatFromChatScreen]);
232
241
 
233
242
  // Memoize active chat button
234
243
  const activeChatButton = useMemo(() => {
235
244
  if (!sessionId || showChat) return null;
236
245
 
237
246
  return (
238
- <Button
239
- variant='rounded-icon'
240
- size='icon'
241
- className='!babylai-bg-primary-500 babylai-absolute babylai-bottom-4 babylai-right-3 babylai-z-20 !babylai-w-10 !babylai-h-10 babylai-p-2'
242
- onClick={handleShowActiveChat}
243
- >
244
- <ChatIcon className='babylai-w-5 babylai-h-5 babylai-text-black-white-50' />
245
- </Button>
247
+ <ActiveChatActions
248
+ onConfirm={handleEndChatFromActiveActions}
249
+ onCancel={handleShowActiveChat}
250
+ />
246
251
  );
247
- }, [sessionId, showChat, handleShowActiveChat]);
252
+ }, [sessionId, showChat, handleShowActiveChat, handleEndChatFromActiveActions]);
253
+
254
+ // Restore chat view only when popup reopens (not when user clicks back)
255
+ useEffect(() => {
256
+ const justOpened = isOpen && !prevIsOpenRef.current;
257
+ prevIsOpenRef.current = isOpen;
258
+ if (justOpened && sessionId && selectedOption && !showChat) {
259
+ setShowChat(true);
260
+ }
261
+ }, [isOpen, sessionId, selectedOption, showChat]);
262
+
263
+ // After submitting in-chat review, navigate to options list
264
+ useEffect(() => {
265
+ if (navigateToOptionsListAfterReview) {
266
+ setShowChat(false);
267
+ setSelectedOption(null);
268
+ onNavigatedToOptionsList?.();
269
+ }
270
+ }, [navigateToOptionsListAfterReview, onNavigatedToOptionsList, setSelectedOption]);
248
271
 
249
272
  // Scroll to bottom when new messages arrive - optimize with ref comparison
250
273
  useEffect(() => {
@@ -259,11 +282,11 @@ const HelpPopup = ({
259
282
  if (status === 'loading' && !helpScreen) {
260
283
  return (
261
284
  <div
262
- className='babylai-fixed babylai-inset-0 md:babylai-inset-auto md:babylai-max-w-sm md:babylai-h-[calc(100vh-220px)] babylai-max-h-[800px]
263
- babylai-overflow-auto babylai-w-full babylai-bg-black-white-50 md:babylai-mb-4
264
- md:babylai-bottom-[6rem] md:babylai-right-4 babylai-rounded-none md:babylai-rounded-3xl babylai-shadow-lg babylai-z-50 babylai-flex babylai-flex-col'
285
+ className='babylai:fixed babylai:inset-0 babylai:md:inset-auto babylai:md:max-w-sm babylai:md:h-[calc(100vh-220px)] babylai:max-h-[800px]
286
+ babylai:overflow-auto babylai:w-full babylai:bg-black-white-50 babylai:md:mb-4
287
+ babylai:md:bottom-24 babylai:md:right-4 babylai:rounded-none babylai:md:rounded-3xl babylai:shadow-lg babylai:z-50 babylai:flex babylai:flex-col'
265
288
  >
266
- <ChatBotLoadingScreen isShowList={isShowList} onClose={onClose} logoUrl={logoUrl} />
289
+ <ChatBotLoadingScreen onClose={onClose} />
267
290
  </div>
268
291
  );
269
292
  }
@@ -271,35 +294,27 @@ md:babylai-bottom-[6rem] md:babylai-right-4 babylai-rounded-none md:babylai-roun
271
294
  if (error) {
272
295
  return (
273
296
  <div
274
- className='babylai-fixed babylai-inset-0 md:babylai-inset-auto md:babylai-max-w-sm md:babylai-h-[calc(100vh-220px)] babylai-max-h-[800px]
275
- babylai-overflow-auto babylai-w-full babylai-bg-black-white-50 md:babylai-mb-4
276
- md:babylai-bottom-[6rem] md:babylai-right-4 babylai-rounded-none md:babylai-rounded-3xl babylai-shadow-lg babylai-z-50 babylai-flex babylai-flex-col'
297
+ className='babylai:fixed babylai:inset-0 babylai:md:inset-auto babylai:md:max-w-sm babylai:md:h-[calc(100vh-220px)] babylai:max-h-[800px]
298
+ babylai:overflow-auto babylai:w-full babylai:bg-black-white-50 babylai:md:mb-4
299
+ babylai:md:bottom-24 babylai:md:right-4 babylai:rounded-none babylai:md:rounded-3xl babylai:shadow-lg babylai:z-50 babylai:flex babylai:flex-col'
277
300
  >
278
- <ChatBotErrorScreen onClose={onClose} error={error || ''} logoUrl={logoUrl} />
301
+ <ChatBotErrorScreen onClose={onClose} error={error || ''} />
279
302
  </div>
280
303
  );
281
304
  }
282
305
 
283
306
  return (
284
307
  <div
285
- className='babylai-fixed babylai-inset-0 md:babylai-inset-auto md:babylai-max-w-sm md:babylai-h-[calc(100vh-220px)] babylai-max-h-[800px]
286
- babylai-overflow-auto babylai-w-full babylai-bg-black-white-50 md:babylai-mb-4
287
- md:babylai-bottom-[6rem] md:babylai-right-4 babylai-rounded-none md:babylai-rounded-3xl babylai-shadow-lg babylai-z-50 babylai-flex babylai-flex-col'
308
+ className='babylai:fixed babylai:inset-0 babylai:md:inset-auto babylai:md:max-w-sm babylai:md:h-[calc(100vh-220px)] babylai:max-h-[800px]
309
+ babylai:overflow-auto babylai:w-full babylai:bg-secondary babylai:md:mb-4
310
+ babylai:md:bottom-24 babylai:md:right-4 babylai:rounded-none babylai:md:rounded-3xl babylai:shadow-lg babylai:z-50 babylai:flex babylai:flex-col'
288
311
  >
289
- <div
290
- className={cn(
291
- 'babylai-h-full babylai-rounded-none md:babylai-rounded-3xl babylai-flex babylai-flex-col babylai-relative',
292
- {
293
- 'babylai-bg-linear-to-b': !isShowList,
294
- 'babylai-bg-black-white-100 dark:babylai-bg-storm-dust-950': isShowList,
295
- }
296
- )}
312
+ <div className='babylai:h-full babylai:rounded-none babylai:md:rounded-3xl babylai:flex babylai:flex-col babylai:relative'
297
313
  >
298
314
  {activeChatButton}
299
315
 
300
316
  {/* Content */}
301
317
  {renderContent()}
302
- <PoweredBy />
303
318
 
304
319
  {/* End Chat Confirmation Modal */}
305
320
  {confirmationModal}
@@ -312,6 +327,14 @@ md:babylai-bottom-[6rem] md:babylai-right-4 babylai-rounded-none md:babylai-roun
312
327
  onConfirm={handleEndAndStartNewChat}
313
328
  />
314
329
  )}
330
+
331
+ {!!isReviewDialogOpen && !!reviewSessionId && onReviewDialogSubmit && onReviewDialogClose && (
332
+ <ReviewDialog
333
+ handleSubmit={onReviewDialogSubmit}
334
+ onClose={onReviewDialogClose}
335
+ isSubmitting={isSubmittingReview}
336
+ />
337
+ )}
315
338
  </div>
316
339
  </div>
317
340
  );
@@ -4,16 +4,58 @@ const PoweredBy: React.FC = () => {
4
4
  const { t } = useLocalTranslation();
5
5
 
6
6
  return (
7
- <section className='dark:babylai-text-white babylai-font-bold babylai-text-center babylai-px-8 babylai-py-2 babylai-w-full'>
7
+ <footer className="babylai:flex babylai:items-center babylai:justify-center babylai:p-3 babylai:border-t babylai:border-border">
8
8
  <a
9
- href='https://www.babylai.net/'
10
- target='_blank'
11
- rel='noopener noreferrer'
12
- className='babylai-text-xs babylai-opacity-60 hover:babylai-opacity-100 babylai-transition-all'
9
+ href="https://babylai.net"
10
+ target="_blank"
11
+ dir="auto"
12
+ className="babylai:flex babylai:items-center babylai:justify-center babylai:gap-2 babylai:text-sm babylai:text-card-foreground babylai:no-underline babylai:transition-opacity babylai:duration-200 babylai:hover:opacity-80"
13
13
  >
14
- {t('homeSdk.poweredBy')} BabylAI © 2025
14
+ <span>
15
+ {t('homeSdk.poweredBy')}
16
+ </span>
17
+ <span>|</span>
18
+ <svg viewBox="0 0 54 19" fill="none" className="babylai:w-15">
19
+ <path
20
+ d="M0 4.97873C0 2.22905 2.22908 0 4.97879 0H13.2768C16.0265 0 18.2556 2.22905 18.2556 4.97873V13.2766C18.2556 16.0263 16.0265 18.2554 13.2768 18.2554H0V4.97873Z"
21
+ fill="#606060"
22
+ />
23
+ <path
24
+ d="M5.76107 6.10571C5.76153 6.10407 5.76177 6.10325 5.76187 6.10287C5.83413 5.8495 6.19321 5.8495 6.26546 6.10287C6.26557 6.10325 6.2658 6.10407 6.26627 6.10571C6.26749 6.11004 6.26809 6.1122 6.26867 6.11423C6.60441 7.29978 7.53101 8.22637 8.71657 8.5621C8.7186 8.56268 8.72076 8.56329 8.72509 8.56451C8.72673 8.56497 8.72755 8.5652 8.72793 8.56531C8.98131 8.63756 8.98131 8.99664 8.72793 9.06889C8.72755 9.069 8.72673 9.06923 8.72509 9.0697C8.72076 9.07092 8.7186 9.07153 8.71657 9.0721C7.53101 9.40783 6.60441 10.3344 6.26867 11.52C6.26809 11.522 6.26749 11.5242 6.26627 11.5285C6.2658 11.5301 6.26557 11.531 6.26546 11.5313C6.19321 11.7847 5.83413 11.7847 5.76187 11.5313C5.76177 11.531 5.76153 11.5301 5.76107 11.5285C5.75985 11.5242 5.75924 11.522 5.75867 11.52C5.42293 10.3344 4.49633 9.40783 3.31077 9.0721C3.30874 9.07153 3.30657 9.07092 3.30225 9.0697C3.3006 9.06923 3.29978 9.069 3.2994 9.06889C3.04603 8.99664 3.04603 8.63756 3.2994 8.56531C3.29978 8.5652 3.3006 8.56497 3.30225 8.56451C3.30657 8.56329 3.30874 8.56268 3.31077 8.5621C4.49633 8.22637 5.42293 7.29978 5.75867 6.11423C5.75924 6.1122 5.75985 6.11004 5.76107 6.10571Z"
25
+ fill="white"
26
+ />
27
+ <path
28
+ d="M14.7275 8.76473C14.7275 9.99635 13.7523 10.9948 12.5493 10.9948C11.3463 10.9948 10.3711 9.99635 10.3711 8.76473C10.3711 7.5331 11.3463 6.53467 12.5493 6.53467C13.7523 6.53467 14.7275 7.5331 14.7275 8.76473Z"
29
+ fill="white"
30
+ />
31
+ <path
32
+ d="M51.6133 13.0924V5.27515H53.1931V13.0924H51.6133Z"
33
+ fill="#606060"
34
+ />
35
+ <path
36
+ d="M44.5938 13.0924L46.5857 5.27515H49.3446L51.325 13.0924H49.7452L49.3102 11.513H46.5742L46.1621 13.0924H44.5938ZM46.8261 10.2425H49.0813L48.1998 6.55705H47.719L46.8261 10.2425Z"
37
+ fill="#606060"
38
+ />
39
+ <path d="M42.5703 13.092V5H44.0929V13.092H42.5703Z" fill="#919191" />
40
+ <path
41
+ d="M38.6905 15.5069L39.4231 13.0919H38.1982L36.8359 7.34619H38.4272L39.446 11.7985H39.7437L40.7625 7.34619H42.2965L40.3161 15.5069H38.6905Z"
42
+ fill="#919191"
43
+ />
44
+ <path
45
+ d="M34.008 13.2179C33.8172 13.2179 33.5845 13.2103 33.3097 13.195C33.035 13.1797 32.7526 13.1569 32.4626 13.1263C32.1802 13.0958 31.9284 13.0691 31.707 13.0462V5H33.241V7.52946C33.3555 7.48368 33.4967 7.4379 33.6646 7.39212C33.8325 7.34633 34.008 7.30818 34.1912 7.27766C34.382 7.23951 34.5575 7.22043 34.7178 7.22043C35.252 7.22043 35.6756 7.33107 35.9885 7.55235C36.309 7.766 36.538 8.08648 36.6754 8.51378C36.8127 8.94108 36.8814 9.47902 36.8814 10.1276C36.8814 10.8906 36.7937 11.5011 36.6181 11.9589C36.4502 12.4091 36.1564 12.7334 35.7366 12.9318C35.3169 13.1225 34.7407 13.2179 34.008 13.2179ZM34.0195 11.936C34.3934 11.936 34.672 11.8711 34.8552 11.7414C35.0383 11.6041 35.1604 11.4019 35.2215 11.1348C35.2902 10.8677 35.3245 10.5396 35.3245 10.1505C35.3245 9.75371 35.294 9.43705 35.2329 9.20051C35.1719 8.95634 35.0689 8.78084 34.9238 8.67402C34.7865 8.55956 34.5919 8.50233 34.34 8.50233C34.2179 8.50233 34.0882 8.51759 33.9508 8.54812C33.8134 8.57101 33.6799 8.60153 33.5501 8.63968C33.428 8.6702 33.325 8.70072 33.241 8.73124V11.8902C33.3555 11.8978 33.4891 11.9093 33.6417 11.9245C33.7943 11.9322 33.9203 11.936 34.0195 11.936Z"
46
+ fill="#919191"
47
+ />
48
+ <path
49
+ d="M27.8012 13.2177C27.2059 13.2177 26.7556 13.0689 26.4504 12.7713C26.1527 12.4661 26.0039 12.0083 26.0039 11.3978C26.0039 10.9705 26.0802 10.6386 26.2329 10.4021C26.3855 10.1579 26.6106 9.9824 26.9083 9.87558C27.2136 9.76112 27.5837 9.69245 28.0187 9.66956L29.4153 9.54366V9.20029C29.4153 8.9256 29.3467 8.73484 29.2093 8.62802C29.0719 8.51356 28.8697 8.45633 28.6025 8.45633C28.3889 8.45633 28.1408 8.46396 27.8584 8.47922C27.5837 8.49448 27.309 8.51356 27.0342 8.53645C26.7671 8.55934 26.5343 8.58223 26.3359 8.60512L26.2901 7.52924C26.4885 7.48346 26.7251 7.43768 26.9999 7.3919C27.2822 7.33849 27.5761 7.29652 27.8813 7.266C28.1866 7.23548 28.469 7.22021 28.7285 7.22021C29.2169 7.22021 29.6252 7.28126 29.9534 7.40334C30.2816 7.52543 30.5296 7.72763 30.6975 8.00996C30.8654 8.28465 30.9493 8.65854 30.9493 9.13162V11.7526C30.9646 11.8595 31.0218 11.9434 31.1211 12.0044C31.2203 12.0579 31.3347 12.096 31.4645 12.1189L31.4301 13.1719C31.308 13.1719 31.1859 13.1719 31.0638 13.1719C30.9493 13.1795 30.8387 13.1795 30.7318 13.1719C30.625 13.1719 30.5296 13.1643 30.4456 13.149C30.2701 13.1261 30.1175 13.0803 29.9877 13.0117C29.8656 12.943 29.7664 12.8705 29.6901 12.7942C29.568 12.8476 29.4039 12.9086 29.1978 12.9773C28.9918 13.046 28.7666 13.1032 28.5224 13.149C28.2858 13.1948 28.0454 13.2177 27.8012 13.2177ZM28.1675 12.0846C28.3125 12.0846 28.4652 12.0693 28.6254 12.0388C28.7857 12.0083 28.9345 11.9739 29.0719 11.9358C29.2169 11.89 29.3314 11.848 29.4153 11.8099V10.4936L28.2477 10.5966C27.9958 10.6195 27.8127 10.6958 27.6982 10.8256C27.5913 10.9476 27.5379 11.1231 27.5379 11.3521C27.5379 11.581 27.5875 11.7603 27.6867 11.89C27.7936 12.0197 27.9538 12.0846 28.1675 12.0846Z"
50
+ fill="#919191"
51
+ />
52
+ <path
53
+ d="M19.9531 13.0924V5.27515H23.0669C23.5859 5.27515 24.0323 5.34 24.4063 5.46972C24.7803 5.59944 25.0703 5.80927 25.2763 6.09923C25.49 6.38155 25.5969 6.76307 25.5969 7.24378C25.5969 7.57188 25.5625 7.85039 25.4938 8.0793C25.4328 8.30058 25.3336 8.49134 25.1962 8.65158C25.0665 8.80419 24.8947 8.94535 24.681 9.07506C24.91 9.159 25.1084 9.27345 25.2763 9.41843C25.4519 9.55578 25.5854 9.74272 25.677 9.97926C25.7686 10.2082 25.8144 10.5134 25.8144 10.8949C25.8144 11.3146 25.7495 11.6656 25.6198 11.9479C25.49 12.2302 25.303 12.4553 25.0588 12.6232C24.8222 12.791 24.5437 12.9131 24.2231 12.9894C23.9026 13.0581 23.5515 13.0924 23.1699 13.0924H19.9531ZM21.5329 11.925H23.0555C23.3226 11.925 23.5439 11.8945 23.7194 11.8334C23.9026 11.7648 24.04 11.6465 24.1316 11.4786C24.2308 11.3108 24.2804 11.078 24.2804 10.7804C24.2804 10.5515 24.2422 10.3646 24.1659 10.2196C24.0896 10.0746 23.9904 9.96782 23.8683 9.89914C23.7461 9.82284 23.6088 9.76943 23.4561 9.7389C23.3111 9.70838 23.1661 9.69312 23.0211 9.69312H21.5329V11.925ZM21.5329 8.57146H23.0097C23.2692 8.57146 23.479 8.53331 23.6393 8.457C23.7996 8.37307 23.9179 8.25099 23.9942 8.09075C24.0705 7.92288 24.1087 7.71304 24.1087 7.46124C24.1087 7.10262 24.0133 6.84318 23.8225 6.68295C23.6393 6.52271 23.3493 6.44259 22.9524 6.44259H21.5329V8.57146Z"
54
+ fill="#919191"
55
+ />
56
+ </svg>
15
57
  </a>
16
- </section>
58
+ </footer>
17
59
  );
18
60
  };
19
61
 
@@ -1,29 +1,27 @@
1
1
  import { ReviewProps } from '@/lib/types'
2
2
  import { Rating } from '@/ui/review-dialog/rating'
3
3
  import { useLocalTranslation } from '../../useLocalTranslation'
4
- import CloseCircle from '../../assets/icons/closeCircle.svg'
5
4
  import { useState } from 'react';
5
+ import SolarCloseCircleLineDuotone from '~icons/solar/close-circle-line-duotone'
6
6
  import { Button } from '@/components';
7
7
 
8
8
  interface ReviewDialogProps {
9
- handleSubmit: ({ comment, rating }: ReviewProps) => void;
9
+ handleSubmit: ({ rating }: ReviewProps) => void;
10
10
  onClose: () => void;
11
+ isSubmitting?: boolean;
11
12
  }
12
13
 
13
14
  const ReviewDialog: React.FC<ReviewDialogProps> = (props) => {
14
15
  const { t } = useLocalTranslation()
15
- const [comment, setComment] = useState<string>('')
16
16
  const [rating, setRating] = useState<number>(0)
17
17
  const [error, setError] = useState<{ comment?: string; rating?: string }>({})
18
18
 
19
- const isCommentValid = comment.length >= 10 && comment.length <= 500
19
+
20
20
  const isRatingValid = rating >= 1 && rating <= 5
21
21
 
22
22
  const validateAndSubmit = () => {
23
23
  const newError: typeof error = {}
24
- if (!isCommentValid) {
25
- newError.comment = t('homeSdk.ReviewDialog.comment_error') || 'Comment must be between 10 and 500 characters.'
26
- }
24
+
27
25
  if (!isRatingValid) {
28
26
  newError.rating = t('homeSdk.ReviewDialog.rating_error') || 'Rating must be between 1 and 5.'
29
27
  }
@@ -34,14 +32,7 @@ const ReviewDialog: React.FC<ReviewDialogProps> = (props) => {
34
32
  }
35
33
 
36
34
  setError({})
37
- props.handleSubmit({ comment, rating })
38
- }
39
-
40
- const handleCommentChange = (val: string) => {
41
- setComment(val)
42
- if (error.comment && val.length >= 10 && val.length <= 500) {
43
- setError((prev) => ({ ...prev, comment: undefined }))
44
- }
35
+ props.handleSubmit({ rating })
45
36
  }
46
37
 
47
38
  const handleRatingChange = (val: number) => {
@@ -52,61 +43,53 @@ const ReviewDialog: React.FC<ReviewDialogProps> = (props) => {
52
43
  }
53
44
 
54
45
  return (
55
- <section className="babylai-p-6 babylai-gap-6 babylai-max-w-sm babylai-max-h-[calc(100vh-90px)] babylai-overflow-auto babylai-w-full babylai-bg-black-white-50 dark:babylai-bg-storm-dust-950 babylai-fixed babylai-bottom-20 babylai-right-0 md:babylai-right-4 babylai-rounded-3xl babylai-shadow-lg babylai-z-50 babylai-flex babylai-flex-col">
56
- <header className='babylai-border-t-0 babylai-border-x-0 babylai-border-b babylai-border-solid babylai-border-gray-400 babylai-pb-4 babylai-flex babylai-items-center babylai-justify-between babylai-gap-4'>
57
- <h2 className="babylai-text-lg babylai-font-semibold dark:babylai-text-white babylai-m-0">{t('homeSdk.ReviewDialog.title')}</h2>
58
- <CloseCircle
59
- className="babylai-w-6 babylai-h-6 babylai-cursor-pointer babylai-text-primary-500 dark:babylai-text-white"
46
+ <section className="babylai:absolute babylai:inset-0 babylai:z-50 babylai:flex babylai:items-end babylai:rounded-3xl babylai:overflow-hidden">
47
+ <div className='babylai:absolute babylai:inset-0 babylai:bg-black/60' onClick={props.onClose}></div>
48
+ <div className='babylai:flex babylai:flex-col babylai:bg-card babylai:rounded-2xl babylai:p-6 babylai:pb-5 babylai:w-full babylai:z-50 babylai:shadow-lg'>
49
+ <button className="babylai:cursor-pointer babylai:mb-6 babylai:ms-auto babylai:text-card-foreground"
50
+ type='button'
60
51
  onClick={props.onClose}
61
- />
62
- </header>
63
- <div className="babylai-flex babylai-flex-col babylai-gap-2">
64
- <p className="babylai-text-sm babylai-mb-3 babylai-mt-0 babylai-text-gray-600 dark:babylai-text-white">
52
+ >
53
+ <SolarCloseCircleLineDuotone className="babylai:w-6 babylai:h-6" />
54
+ </button>
55
+
56
+ <section className='babylai:flex babylai:items-center babylai:justify-center babylai:border-b babylai:border-black-white-200 babylai:pb-6 babylai:mb-6'>
57
+ <Rating value={rating} onChange={handleRatingChange} size='lg' />
58
+ </section>
59
+
60
+ <h2 className="babylai:text-2xl babylai:text-center babylai:font-bold babylai:mb-2 babylai:text-card-foreground">{t('homeSdk.ReviewDialog.title')}</h2>
61
+
62
+ <p className="babylai:text-sm babylai:text-center babylai:text-muted-foreground babylai:mb-4">
65
63
  {t('homeSdk.ReviewDialog.description')}
66
64
  </p>
67
65
 
68
- <div className="babylai-flex babylai-flex-col babylai-gap-2">
69
- <div className="babylai-flex babylai-items-center babylai-gap-2">
70
- <span className="babylai-text-base babylai-font-medium dark:babylai-text-white">{t('homeSdk.ReviewDialog.rating_label')}</span>
71
- <Rating value={rating} onChange={handleRatingChange} />
72
- </div>
73
- <span className={`babylai-text-sm babylai-text-red-500 babylai-transition-opacity babylai-duration-300 ${error.rating ? 'babylai-opacity-100' : 'babylai-opacity-0'}`}>
74
- {error.rating}
75
- </span>
76
- </div>
77
-
78
- <div className="babylai-flex babylai-flex-col babylai-gap-2">
79
- <label htmlFor='comment' className="babylai-text-base babylai-font-medium dark:babylai-text-white">{t('homeSdk.ReviewDialog.comment_label')}</label>
80
- <textarea
81
- id='comment'
82
- className="babylai-bg-black-white-100 babylai-p-6 babylai-rounded-xl babylai-resize-none babylai-border-none dark:babylai-bg-storm-dust-900 dark:babylai-text-white"
83
- rows={4}
84
- placeholder={t('homeSdk.ReviewDialog.comment_placeholder')}
85
- value={comment}
86
- onChange={(e) => handleCommentChange(e.target.value)}
87
- />
88
- <span className={`babylai-text-sm babylai-text-red-500 babylai-transition-opacity babylai-duration-300 ${error.comment ? 'babylai-opacity-100' : 'babylai-opacity-0'}`}>
89
- {error.comment}
90
- </span>
91
- </div>
66
+ <footer className="babylai:flex babylai:justify-between babylai:gap-3 babylai:mt-6">
67
+ <Button
68
+ onClick={props.onClose}
69
+ variant='secondary'
70
+ disabled={props.isSubmitting}
71
+ >
72
+ {t('homeSdk.ReviewDialog.skip_button')}
73
+ </Button>
74
+ <Button
75
+ onClick={validateAndSubmit}
76
+ variant='default'
77
+ disabled={props.isSubmitting}
78
+ >
79
+ {props.isSubmitting ? (
80
+ <span className="babylai:inline-flex babylai:items-center babylai:gap-2">
81
+ <span
82
+ className="babylai:inline-block babylai:animate-spin babylai:rounded-full babylai:h-4 babylai:w-4 babylai:border-2 babylai:border-white babylai:border-t-transparent babylai:box-border"
83
+ aria-hidden
84
+ />
85
+ {t('homeSdk.ReviewDialog.submit_button')}
86
+ </span>
87
+ ) : (
88
+ t('homeSdk.ReviewDialog.submit_button')
89
+ )}
90
+ </Button>
91
+ </footer>
92
92
  </div>
93
-
94
- <footer className="babylai-flex babylai-justify-between babylai-gap-4 babylai-border-t babylai-pt-4">
95
- <Button
96
- variant='default'
97
- onClick={validateAndSubmit}
98
- className='babylai-text-sm babylai-w-full !babylai-font-bold'
99
- >
100
- {t('homeSdk.ReviewDialog.submit_button')}
101
- </Button>
102
- <Button
103
- variant='outline'
104
- onClick={props.onClose}
105
- className='babylai-text-sm babylai-w-full babylai-text-primary-500 !babylai-font-bold'
106
- >
107
- {t('homeSdk.ReviewDialog.skip_button')}
108
- </Button>
109
- </footer>
110
93
  </section>
111
94
  )
112
95
  }
@@ -20,9 +20,9 @@ const iconMap = {
20
20
  }
21
21
 
22
22
  const sizeMap = {
23
- sm: 'babylai-w-4 babylai-h-4',
24
- md: 'babylai-w-6 babylai-h-6',
25
- lg: 'babylai-w-8 babylai-h-8'
23
+ sm: 'babylai:w-4 babylai:h-4',
24
+ md: 'babylai:w-7 babylai:h-7',
25
+ lg: 'babylai:w-13 babylai:h-13'
26
26
  }
27
27
 
28
28
  export const Rating = React.forwardRef<HTMLDivElement, RatingProps>(
@@ -47,7 +47,7 @@ export const Rating = React.forwardRef<HTMLDivElement, RatingProps>(
47
47
  }
48
48
 
49
49
  return (
50
- <div ref={ref} className={cn('babylai-flex babylai-items-center', className)} {...props}>
50
+ <div ref={ref} className={cn('babylai:inline-flex babylai:gap-2', className)} {...props}>
51
51
  {[...Array(max)].map((_, index) => {
52
52
  const filled = (hoverValue !== null ? hoverValue : value) > index
53
53
 
@@ -56,9 +56,9 @@ export const Rating = React.forwardRef<HTMLDivElement, RatingProps>(
56
56
  key={index}
57
57
  className={cn(
58
58
  sizeMap[size],
59
- 'babylai-cursor-pointer babylai-transition-colors',
60
- filled ? 'babylai-text-yellow-400 babylai-fill-yellow-400' : 'babylai-text-gray-300',
61
- readOnly && 'babylai-cursor-default'
59
+ 'babylai:cursor-pointer babylai:transition-colors',
60
+ filled ? 'babylai:text-primary-500 babylai:fill-primary-500' : 'babylai:text-gray-300',
61
+ readOnly && 'babylai:cursor-default'
62
62
  )}
63
63
  onMouseEnter={() => handleMouseEnter(index + 1)}
64
64
  onMouseLeave={handleMouseLeave}
@@ -1,6 +0,0 @@
1
- interface HeaderProps {
2
- onClose: () => void;
3
- logoUrl?: string;
4
- }
5
- declare const Header: ({ onClose, logoUrl }: HeaderProps) => import("react/jsx-runtime").JSX.Element;
6
- export default Header;
@@ -1,6 +0,0 @@
1
- interface CardProps {
2
- text: string;
3
- handleClick: () => void;
4
- }
5
- declare const Card: React.FC<CardProps>;
6
- export default Card;
@@ -1,5 +0,0 @@
1
- interface ChatNowCardProps {
2
- setIsShowList: (isShowList: boolean) => void;
3
- }
4
- declare const ChatNowCard: React.FC<ChatNowCardProps>;
5
- export default ChatNowCard;