@aslaluroba/help-center-react 3.2.17 → 3.2.18

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 (101) hide show
  1. package/dist/components/shared/Button/button.d.ts +1 -1
  2. package/dist/components/shared/Card/card.d.ts +1 -4
  3. package/dist/components/ui/agent-response/agent-response.d.ts +2 -1
  4. package/dist/index.css +1424 -1
  5. package/dist/index.d.ts +3 -3
  6. package/dist/index.esm.js +19194 -38923
  7. package/dist/index.esm.js.map +1 -1
  8. package/dist/index.js +19198 -38927
  9. package/dist/index.js.map +1 -1
  10. package/dist/lib/LanguageContext.d.ts +1 -1
  11. package/dist/lib/custom-hooks/useAblyConnection.d.ts +25 -0
  12. package/dist/lib/custom-hooks/useActionHandler.d.ts +1 -7
  13. package/dist/lib/custom-hooks/useChatSession.d.ts +37 -0
  14. package/dist/lib/custom-hooks/useMessageQueue.d.ts +16 -0
  15. package/dist/lib/custom-hooks/useReview.d.ts +14 -0
  16. package/dist/lib/index.d.ts +1 -2
  17. package/dist/services.d.ts +9 -6
  18. package/dist/services.esm.js +1 -14348
  19. package/dist/services.esm.js.map +1 -1
  20. package/dist/services.js +19 -14344
  21. package/dist/services.js.map +1 -1
  22. package/dist/ui/chatbot-popup/chat-window-screen/footer.d.ts +1 -1
  23. package/dist/ui/chatbot-popup/chat-window-screen/in-chat-review.d.ts +1 -1
  24. package/dist/ui/chatbot-popup/chat-window-screen/index.d.ts +2 -2
  25. package/dist/ui/chatbot-popup/options-list-screen/helpscreen-list.d.ts +1 -1
  26. package/dist/ui/chatbot-popup/options-list-screen/helpscreen-option.d.ts +1 -1
  27. package/dist/ui/chatbot-popup/options-list-screen/index.d.ts +1 -1
  28. package/dist/ui/help-center.d.ts +1 -1
  29. package/dist/ui/help-popup.d.ts +4 -27
  30. package/dist/ui/review-dialog/index.d.ts +1 -1
  31. package/package.json +12 -26
  32. package/postcss.config.js +5 -0
  33. package/rollup.config.mjs +34 -0
  34. package/dist/core/AblyService.d.ts +0 -16
  35. package/dist/core/ApiService.d.ts +0 -16
  36. package/dist/core/api.d.ts +0 -10
  37. package/dist/core/token-service.d.ts +0 -10
  38. package/dist/i18n.d.ts +0 -3
  39. package/dist/lib/config.d.ts +0 -18
  40. package/dist/lib/theme-utils.d.ts +0 -10
  41. package/dist/lib/types.d.ts +0 -145
  42. package/dist/lib/utils.d.ts +0 -2
  43. package/src/assets/animatedLogo.gif +0 -0
  44. package/src/assets/logo.svg +0 -5
  45. package/src/assets/seperator.svg +0 -5
  46. package/src/components/index.ts +0 -1
  47. package/src/components/shared/Button/button.tsx +0 -38
  48. package/src/components/shared/Button/index.ts +0 -1
  49. package/src/components/shared/Card/card.tsx +0 -44
  50. package/src/components/shared/Card/index.ts +0 -1
  51. package/src/components/shared/index.ts +0 -2
  52. package/src/components/ui/agent-response/agent-response.tsx +0 -57
  53. package/src/components/ui/agent-response/doc.md +0 -88
  54. package/src/components/ui/image-attachment.tsx +0 -119
  55. package/src/components/ui/image-preview-dialog.tsx +0 -400
  56. package/src/components/ui/index.ts +0 -3
  57. package/src/core/AblyService.ts +0 -243
  58. package/src/core/ApiService.ts +0 -116
  59. package/src/core/api.ts +0 -278
  60. package/src/core/token-service.ts +0 -35
  61. package/src/globals.css +0 -268
  62. package/src/i18n.ts +0 -21
  63. package/src/index.ts +0 -19
  64. package/src/lib/LanguageContext.tsx +0 -28
  65. package/src/lib/config.ts +0 -52
  66. package/src/lib/custom-hooks/useActionHandler.ts +0 -102
  67. package/src/lib/custom-hooks/useTypewriter.ts +0 -26
  68. package/src/lib/index.ts +0 -4
  69. package/src/lib/theme-utils.ts +0 -56
  70. package/src/lib/types.ts +0 -158
  71. package/src/lib/utils.ts +0 -6
  72. package/src/locales/ar.json +0 -45
  73. package/src/locales/en.json +0 -45
  74. package/src/services.ts +0 -14
  75. package/src/types/icons.d.ts +0 -6
  76. package/src/types/svg.d.ts +0 -5
  77. package/src/types.d.ts +0 -9
  78. package/src/ui/chatbot-popup/active-chat-actions.tsx +0 -39
  79. package/src/ui/chatbot-popup/chat-window-screen/action-button.tsx +0 -37
  80. package/src/ui/chatbot-popup/chat-window-screen/footer.tsx +0 -313
  81. package/src/ui/chatbot-popup/chat-window-screen/header.tsx +0 -53
  82. package/src/ui/chatbot-popup/chat-window-screen/in-chat-review.tsx +0 -116
  83. package/src/ui/chatbot-popup/chat-window-screen/index.tsx +0 -366
  84. package/src/ui/chatbot-popup/chat-window-screen/typing-indicator.tsx +0 -31
  85. package/src/ui/chatbot-popup/error-screen/index.tsx +0 -22
  86. package/src/ui/chatbot-popup/loading-screen/index.tsx +0 -21
  87. package/src/ui/chatbot-popup/options-list-screen/company-card.tsx +0 -39
  88. package/src/ui/chatbot-popup/options-list-screen/header.tsx +0 -23
  89. package/src/ui/chatbot-popup/options-list-screen/helpscreen-intro.tsx +0 -32
  90. package/src/ui/chatbot-popup/options-list-screen/helpscreen-list.tsx +0 -57
  91. package/src/ui/chatbot-popup/options-list-screen/helpscreen-option.tsx +0 -56
  92. package/src/ui/chatbot-popup/options-list-screen/index.tsx +0 -70
  93. package/src/ui/confirmation-modal/index.tsx +0 -62
  94. package/src/ui/floating-message.tsx +0 -29
  95. package/src/ui/help-button.tsx +0 -25
  96. package/src/ui/help-center.tsx +0 -448
  97. package/src/ui/help-popup.tsx +0 -367
  98. package/src/ui/powered-by.tsx +0 -62
  99. package/src/ui/review-dialog/index.tsx +0 -149
  100. package/src/ui/review-dialog/rating.tsx +0 -79
  101. package/src/useLocalTranslation.ts +0 -15
@@ -1,448 +0,0 @@
1
- import { useCallback, useEffect, useState } from 'react';
2
- import { apiRequest } from '../core/api';
3
- import { ClientAblyService } from '../core/AblyService';
4
- import { useLocalTranslation } from '../useLocalTranslation';
5
- import '../globals.css';
6
- import { HelpScreenData, Message, Option, ReviewProps } from '@/lib/types';
7
- import FloatingMessage from './floating-message';
8
- import HelpButton from './help-button';
9
- import HelpPopup from './help-popup';
10
- import { defaultLanguage } from '@/i18n';
11
- import { LanguageProvider } from '@/lib/LanguageContext';
12
- import { getPrimaryColorStyles } from '@/lib/theme-utils';
13
- import { useActionHandler } from '@/lib/custom-hooks/useActionHandler';
14
-
15
- interface HelpCenterProps {
16
- helpScreenId: string;
17
- language?: 'ar' | 'en';
18
- user?: {
19
- id?: string;
20
- name?: string;
21
- email?: string;
22
- avatar?: string;
23
- };
24
- showArrow?: boolean;
25
- messageLabel?: string | null;
26
- primaryColor?: string;
27
- }
28
-
29
- const HelpCenterContent = ({
30
- helpScreenId,
31
- user,
32
- showArrow = true,
33
- messageLabel = null,
34
- primaryColor,
35
- language = defaultLanguage,
36
- }: HelpCenterProps) => {
37
- const { t } = useLocalTranslation();
38
- const [isOpen, setIsOpen] = useState(false);
39
- const [isClosing, setIsClosing] = useState(false);
40
- const [showArrowAnimation, setShowArrowAnimation] = useState(showArrow);
41
- const [helpScreenData, setHelpScreenData] = useState<HelpScreenData | null>(null);
42
- const [status, setStatus] = useState('idle');
43
- const [error, setError] = useState('');
44
- const [selectedOption, setSelectedOption] = useState<Option | null>(null);
45
-
46
- const [sessionId, setSessionId] = useState<string | null>(null);
47
- const [reviewSessionId, setReviewSessionId] = useState<string | null>(null);
48
- const [inChatReviewSessionId, setInChatReviewSessionId] = useState<string | null>(null);
49
- const [isAblyConnected, setIsAblyConnected] = useState(false);
50
- const [isChatClosed, setIsChatClosed] = useState(false);
51
- const [messages, setMessages] = useState<Message[]>([]);
52
- const [needsAgent, setNeedsAgent] = useState(false);
53
- const [assistantStatus, setAssistantStatus] = useState('idle');
54
- const [isReviewDialogOpen, setIsReviewDialogOpen] = useState(false);
55
- const [isSubmittingReview, setIsSubmittingReview] = useState(false);
56
- const [navigateToOptionsListAfterReview, setNavigateToOptionsListAfterReview] = useState(false);
57
-
58
- const actionHandler = useActionHandler();
59
-
60
- const handleTogglePopup = () => {
61
- if (isOpen) {
62
- setIsClosing(true);
63
- setIsOpen(false);
64
- setShowArrowAnimation(true);
65
- } else {
66
- setIsOpen(true);
67
- setShowArrowAnimation(false);
68
- }
69
- };
70
-
71
- const handleClosePopup = useCallback(() => {
72
- setIsClosing(true);
73
- setIsOpen(false);
74
- }, []);
75
-
76
- const handlePopupCloseAnimationEnd = useCallback(() => {
77
- setIsClosing(false);
78
- }, []);
79
-
80
- const handleCloseArrowAnimation = () => {
81
- setShowArrowAnimation(false);
82
- };
83
-
84
- const handleReceiveMessage = (
85
- message: string,
86
- senderType: number,
87
- needsAgent: boolean,
88
- attachmentUrls: string[] = [],
89
- attachmentIds: string[] = []
90
- ) => {
91
- if (needsAgent) {
92
- setNeedsAgent(true);
93
- }
94
-
95
- setMessages((prevMessages) => {
96
- const newMessage: Message = {
97
- id: Date.now(),
98
- senderType: senderType,
99
- messageContent: message,
100
- sentAt: new Date(),
101
- isSeen: true,
102
- ...(attachmentUrls.length > 0 && { attachmentUrls }),
103
- ...(attachmentIds.length > 0 && { attachmentIds }),
104
- };
105
-
106
- return [...prevMessages, newMessage];
107
- });
108
-
109
- setAssistantStatus('idle');
110
- };
111
-
112
- const handleEndChat = useCallback(
113
- async (options?: { fromChatScreen?: boolean; sessionClosedByServer?: boolean }) => {
114
- if (!sessionId || !selectedOption) return;
115
-
116
- const fromChatScreen = options?.fromChatScreen === true;
117
- // When Ably sends end_session (e.g. admin closed from dashboard), skip close API call
118
- const sessionClosedByServer = options?.sessionClosedByServer === true;
119
-
120
- try {
121
- await ClientAblyService.stopConnection();
122
- setIsAblyConnected(false);
123
- setAssistantStatus('idle');
124
-
125
- if (!sessionClosedByServer) {
126
- const response = await apiRequest(`Client/ClientChatSession/${sessionId}/close`, 'POST', null, {
127
- language: language,
128
- });
129
- if (!response.ok) throw new Error('Failed to close chat session');
130
- }
131
-
132
- setReviewSessionId(sessionId);
133
- setSessionId(null);
134
-
135
- if (fromChatScreen) {
136
- setInChatReviewSessionId(sessionId);
137
- setIsChatClosed(true);
138
- } else {
139
- setSelectedOption(null);
140
- setMessages([]);
141
- setIsReviewDialogOpen(true);
142
- }
143
- } catch (err) {
144
- setError('Failed to end chat session');
145
- setAssistantStatus('idle');
146
- setReviewSessionId(sessionId);
147
- setSessionId(null);
148
- if (!fromChatScreen) {
149
- setSelectedOption(null);
150
- }
151
- }
152
- },
153
- [language, selectedOption, sessionId]
154
- );
155
-
156
- const handleSendChatReview = async ({ comment, rating }: ReviewProps) => {
157
- if (!reviewSessionId) return;
158
-
159
- const payload = { rating, comment };
160
- const wasInChatReview = !!inChatReviewSessionId;
161
-
162
- setIsSubmittingReview(true);
163
- try {
164
- const response = await apiRequest(`Client/ClientChatSession/${reviewSessionId}/review`, 'POST', payload, {
165
- language,
166
- });
167
- if (!response.ok) throw new Error('Failed to send chat review');
168
-
169
- handleCloseChatReview();
170
- if (wasInChatReview) {
171
- setNavigateToOptionsListAfterReview(true);
172
- }
173
- } catch (err) {
174
- setError('Failed to send chat review');
175
- } finally {
176
- setIsSubmittingReview(false);
177
- }
178
- };
179
-
180
- const handleCloseChatReview = () => {
181
- setIsReviewDialogOpen(false);
182
- setReviewSessionId(null);
183
- setInChatReviewSessionId(null);
184
- };
185
-
186
- const handleStartChat = async (option: Option) => {
187
- setInChatReviewSessionId(null);
188
- setMessages([
189
- {
190
- id: Date.now(),
191
- senderType: 3,
192
- messageContent: option?.assistant?.greeting || 'مرحباً! كيف يمكنني مساعدتك اليوم؟',
193
- sentAt: new Date(),
194
- isSeen: true,
195
- },
196
- ]);
197
- setIsChatClosed(false);
198
- setStatus('succeeded');
199
- };
200
-
201
- const startNewChatSession = async (option: Option): Promise<string> => {
202
- try {
203
- setStatus('loading');
204
- setError('');
205
-
206
- const chatSessionCreateDto = {
207
- helpScreenId: helpScreenId,
208
- optionId: option.id,
209
- ...(user && {
210
- user: {
211
- id: user.id,
212
- name: user.name,
213
- email: user.email,
214
- },
215
- }),
216
- };
217
-
218
- const response = await apiRequest('Client/ClientChatSession/create-session', 'POST', chatSessionCreateDto, {
219
- language,
220
- });
221
-
222
- if (!response.ok) {
223
- throw new Error('Failed to create chat session');
224
- }
225
-
226
- const responseData = await response.json();
227
- const newSessionId = responseData.chatSession.id;
228
-
229
- setSessionId(newSessionId);
230
-
231
- await ClientAblyService.startConnection(
232
- newSessionId,
233
- responseData.ablyToken,
234
- handleReceiveMessage,
235
- responseData.chatSession.tenantId,
236
- (actionType, messageData) => {
237
- void actionHandler.handleAction(actionType, messageData);
238
- }
239
- );
240
-
241
- // Verify the connection is actually active
242
- if (!ClientAblyService.isConnectionActive()) {
243
- throw new Error('Ably connection failed to establish properly');
244
- }
245
-
246
- setIsAblyConnected(true);
247
- setIsChatClosed(false);
248
- setStatus('succeeded');
249
-
250
- return newSessionId; // Return the session ID
251
- } catch (error) {
252
- setError(error instanceof Error ? error.message : 'Failed to start chat session');
253
- setStatus('failed');
254
- throw error; // Re-throw to handle in calling function
255
- }
256
- };
257
-
258
- const handleEnsureSession = async (): Promise<string> => {
259
- // If we already have a session ID and connection, return it
260
- // NEVER create a new session if one already exists
261
- if (sessionId) {
262
- return sessionId;
263
- }
264
-
265
- // Only create a new session if we don't have one and have a selected option
266
- if (selectedOption) {
267
- const newSessionId = await startNewChatSession(selectedOption);
268
- return newSessionId;
269
- }
270
-
271
- throw new Error('No option selected');
272
- };
273
-
274
- const handleSendMessage = async (message: string, attachmentIds: string[] = []) => {
275
- // Allow sending if there's text OR attachments
276
- if (message.trim() !== '' || attachmentIds.length > 0) {
277
- try {
278
- setAssistantStatus('typing');
279
-
280
- const userMessage: Message = {
281
- id: Date.now(),
282
- senderType: 1,
283
- messageContent: message || '', // Use empty string if message is empty but attachments exist
284
- sentAt: new Date(),
285
- isSeen: false,
286
- attachmentIds: attachmentIds.length > 0 ? attachmentIds : undefined,
287
- };
288
-
289
- setMessages((prevMessages) => [...prevMessages, userMessage]);
290
-
291
- // Handle session creation if needed - only create if no session exists
292
- let currentSessionId = sessionId;
293
-
294
- // Only create a new session if we don't have one and we have a selected option
295
- // This ensures session is only created once with the first message
296
- if (!currentSessionId && !isAblyConnected && selectedOption) {
297
- currentSessionId = await startNewChatSession(selectedOption);
298
- }
299
-
300
- if (!currentSessionId) {
301
- throw new Error('No active session available');
302
- }
303
-
304
- const messageDto = {
305
- messageContent: message || '', // Use empty string if message is empty but attachments exist
306
- ...(attachmentIds.length > 0 && { attachmentIds }),
307
- };
308
-
309
- const response = await apiRequest(
310
- `Client/ClientChatSession/${currentSessionId}/send-message`,
311
- 'POST',
312
- messageDto,
313
- { language }
314
- );
315
-
316
- if (!response.ok) {
317
- throw new Error('Failed to send message');
318
- }
319
-
320
- setMessages((prevMessages) => {
321
- return prevMessages.map((msg) => (msg.senderType === 1 && !msg.isSeen ? { ...msg, isSeen: true } : msg));
322
- });
323
- } catch (error) {
324
- setAssistantStatus('idle');
325
-
326
- const errorMessage: Message = {
327
- id: Date.now(),
328
- senderType: 3,
329
- messageContent:
330
- 'Failed to send the message. Please try again.\n لم يتم إرسال الرسالة. يرجى المحاولة مرة أخرى.',
331
- sentAt: new Date(),
332
- isSeen: true,
333
- };
334
-
335
- setMessages((prevMessages) => [...prevMessages, errorMessage]);
336
- }
337
- }
338
- };
339
-
340
- // Register known action handlers for realtime messages
341
- useEffect(() => {
342
- // "needs_agent" → trigger handoff / needs agent UI flow
343
- actionHandler.registerHandler('needs_agent', () => {
344
- setNeedsAgent(true);
345
- });
346
-
347
- // "end_session" → session was closed by server (e.g. admin from dashboard); update local state only, do not call close API
348
- actionHandler.registerHandler('end_session', () => {
349
- void handleEndChat({ fromChatScreen: true, sessionClosedByServer: true });
350
- });
351
-
352
- return () => {
353
- actionHandler.unregisterHandler('needs_agent');
354
- actionHandler.unregisterHandler('end_session');
355
- };
356
- }, [actionHandler, handleEndChat]);
357
-
358
- useEffect(() => {
359
- if (isOpen && helpScreenId) {
360
- setStatus('loading');
361
-
362
- apiRequest(`client/clientHelpScreen/${helpScreenId}`, 'GET', null, {
363
- language,
364
- })
365
- .then((res) => res.json())
366
- .then((data) => {
367
- setHelpScreenData(data);
368
- setStatus('succeeded');
369
- setError('');
370
- })
371
- .catch((err) => {
372
- setError(err.message);
373
- setStatus('failed');
374
- });
375
- }
376
- }, [isOpen, helpScreenId]);
377
-
378
- const themeStyles = getPrimaryColorStyles(primaryColor);
379
-
380
- return (
381
- <div className='babylai-theme-root babylai:mb-4' style={themeStyles}>
382
- {showArrowAnimation && !isOpen && !isClosing && (
383
- <FloatingMessage onClose={handleCloseArrowAnimation} message={messageLabel || t('homeSdk.needAssistance')} />
384
- )}
385
-
386
- <HelpButton onClick={handleTogglePopup} />
387
-
388
- {(isOpen || isClosing) && (
389
- <HelpPopup
390
- isOpen={isOpen}
391
- isClosing={isClosing}
392
- onClose={handleClosePopup}
393
- onCloseAnimationEnd={handlePopupCloseAnimationEnd}
394
- helpScreen={helpScreenData}
395
- status={status}
396
- error={error}
397
- user={user}
398
- onStartChat={handleStartChat}
399
- onSendMessage={handleSendMessage}
400
- onEnsureSession={handleEnsureSession}
401
- onEndChat={handleEndChat}
402
- messages={messages}
403
- needsAgent={needsAgent}
404
- assistantStatus={assistantStatus}
405
- sessionId={sessionId}
406
- isChatClosed={isChatClosed}
407
- selectedOption={selectedOption}
408
- setSelectedOption={setSelectedOption}
409
- inChatReviewSessionId={inChatReviewSessionId}
410
- onInChatReviewSubmit={handleSendChatReview}
411
- onInChatReviewDone={handleCloseChatReview}
412
- navigateToOptionsListAfterReview={navigateToOptionsListAfterReview}
413
- onNavigatedToOptionsList={() => setNavigateToOptionsListAfterReview(false)}
414
- isReviewDialogOpen={isReviewDialogOpen}
415
- reviewSessionId={reviewSessionId}
416
- isSubmittingReview={isSubmittingReview}
417
- onReviewDialogSubmit={handleSendChatReview}
418
- onReviewDialogClose={handleCloseChatReview}
419
- />
420
- )}
421
- </div>
422
- );
423
- };
424
-
425
- // Main HelpCenter component that provides the language context
426
- const HelpCenter = ({
427
- helpScreenId,
428
- user,
429
- showArrow = true,
430
- language = defaultLanguage,
431
- messageLabel = null,
432
- primaryColor,
433
- }: HelpCenterProps) => {
434
- return (
435
- <LanguageProvider language={language}>
436
- <HelpCenterContent
437
- language={language}
438
- helpScreenId={helpScreenId}
439
- user={user}
440
- showArrow={showArrow}
441
- messageLabel={messageLabel}
442
- primaryColor={primaryColor}
443
- />
444
- </LanguageProvider>
445
- );
446
- };
447
-
448
- export default HelpCenter;