@aslaluroba/help-center-react 3.2.5 → 3.2.7
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 +0 -3
- package/dist/components/shared/Button/button.d.ts +3 -3
- package/dist/components/ui/index.d.ts +0 -1
- package/dist/core/api.d.ts +4 -4
- package/dist/index.css +1 -1
- package/dist/index.esm.js +15543 -15136
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +15546 -15145
- package/dist/index.js.map +1 -1
- package/dist/lib/theme-utils.d.ts +0 -9
- package/dist/lib/types.d.ts +6 -3
- package/dist/services.esm.js +9474 -9222
- package/dist/services.esm.js.map +1 -1
- package/dist/services.js +9472 -9222
- package/dist/services.js.map +1 -1
- package/dist/ui/chatbot-popup/active-chat-actions.d.ts +7 -0
- package/dist/ui/chatbot-popup/chat-window-screen/action-button.d.ts +10 -0
- package/dist/ui/chatbot-popup/chat-window-screen/footer.d.ts +1 -0
- package/dist/ui/chatbot-popup/chat-window-screen/header.d.ts +2 -5
- package/dist/ui/chatbot-popup/chat-window-screen/in-chat-review.d.ts +9 -0
- package/dist/ui/chatbot-popup/chat-window-screen/index.d.ts +7 -3
- package/dist/ui/chatbot-popup/chat-window-screen/typing-indicator.d.ts +6 -0
- package/dist/ui/chatbot-popup/error-screen/index.d.ts +0 -1
- package/dist/ui/chatbot-popup/loading-screen/index.d.ts +0 -2
- package/dist/ui/chatbot-popup/options-list-screen/company-card.d.ts +9 -0
- package/dist/ui/chatbot-popup/options-list-screen/header.d.ts +1 -2
- package/dist/ui/chatbot-popup/options-list-screen/helpscreen-intro.d.ts +6 -0
- package/dist/ui/chatbot-popup/options-list-screen/helpscreen-list.d.ts +10 -0
- package/dist/ui/chatbot-popup/options-list-screen/helpscreen-option.d.ts +9 -0
- package/dist/ui/chatbot-popup/options-list-screen/index.d.ts +1 -4
- package/dist/ui/help-center.d.ts +2 -5
- package/dist/ui/help-popup.d.ts +16 -7
- package/dist/ui/review-dialog/index.d.ts +2 -1
- package/package.json +35 -29
- package/src/components/shared/Button/button.tsx +11 -18
- package/src/components/shared/Card/card.tsx +8 -8
- package/src/components/ui/agent-response/agent-response.tsx +4 -4
- package/src/components/ui/image-attachment.tsx +8 -8
- package/src/components/ui/image-preview-dialog.tsx +41 -41
- package/src/components/ui/index.ts +0 -1
- package/src/core/AblyService.ts +22 -17
- package/src/core/api.ts +9 -7
- package/src/globals.css +216 -50
- package/src/lib/theme-utils.ts +1 -33
- package/src/lib/types.ts +7 -4
- package/src/locales/ar.json +16 -6
- package/src/locales/en.json +16 -6
- package/src/types/icons.d.ts +6 -0
- package/src/ui/chatbot-popup/active-chat-actions.tsx +39 -0
- package/src/ui/chatbot-popup/chat-window-screen/action-button.tsx +37 -0
- package/src/ui/chatbot-popup/chat-window-screen/footer.tsx +42 -43
- package/src/ui/chatbot-popup/chat-window-screen/header.tsx +34 -67
- package/src/ui/chatbot-popup/chat-window-screen/in-chat-review.tsx +83 -0
- package/src/ui/chatbot-popup/chat-window-screen/index.tsx +49 -42
- package/src/ui/chatbot-popup/chat-window-screen/typing-indicator.tsx +27 -0
- package/src/ui/chatbot-popup/error-screen/index.tsx +7 -7
- package/src/ui/chatbot-popup/loading-screen/index.tsx +6 -17
- package/src/ui/chatbot-popup/options-list-screen/company-card.tsx +37 -0
- package/src/ui/chatbot-popup/options-list-screen/header.tsx +12 -31
- package/src/ui/chatbot-popup/options-list-screen/helpscreen-intro.tsx +32 -0
- package/src/ui/chatbot-popup/options-list-screen/helpscreen-list.tsx +48 -0
- package/src/ui/chatbot-popup/options-list-screen/helpscreen-option.tsx +38 -0
- package/src/ui/chatbot-popup/options-list-screen/index.tsx +44 -38
- package/src/ui/confirmation-modal/index.tsx +27 -12
- package/src/ui/floating-message.tsx +8 -7
- package/src/ui/help-button.tsx +5 -5
- package/src/ui/help-center.tsx +71 -59
- package/src/ui/help-popup.tsx +114 -91
- package/src/ui/powered-by.tsx +49 -7
- package/src/ui/review-dialog/index.tsx +48 -65
- package/src/ui/review-dialog/rating.tsx +7 -7
- package/dist/components/ui/header.d.ts +0 -6
- package/dist/ui/chatbot-popup/home-screen/card.d.ts +0 -6
- package/dist/ui/chatbot-popup/home-screen/chat-now-card.d.ts +0 -5
- package/dist/ui/chatbot-popup/home-screen/index.d.ts +0 -7
- package/dist/ui/chatbot-popup/options-list-screen/expanded-option.d.ts +0 -7
- package/dist/ui/chatbot-popup/options-list-screen/option-card.d.ts +0 -5
- package/src/assets/icons/arrowRight.svg +0 -3
- package/src/assets/icons/chat.svg +0 -4
- package/src/assets/icons/close.svg +0 -1
- package/src/assets/icons/closeCircle.svg +0 -3
- package/src/assets/icons/closeCirclePrimary.svg +0 -4
- package/src/assets/icons/envelope.svg +0 -3
- package/src/assets/icons/paperclip.svg +0 -3
- package/src/assets/icons/threeDots.svg +0 -3
- package/src/assets/icons/user.svg +0 -3
- package/src/assets/icons/x.svg +0 -4
- package/src/assets/logoColors.svg +0 -5
- package/src/assets/logo_ai.svg +0 -14
- package/src/assets/thinking-logo.svg +0 -3
- package/src/components/ui/header.tsx +0 -22
- package/src/ui/chatbot-popup/home-screen/card.tsx +0 -33
- package/src/ui/chatbot-popup/home-screen/chat-now-card.tsx +0 -36
- package/src/ui/chatbot-popup/home-screen/index.tsx +0 -44
- package/src/ui/chatbot-popup/options-list-screen/expanded-option.tsx +0 -37
- package/src/ui/chatbot-popup/options-list-screen/option-card.tsx +0 -31
- /package/src/assets/{icons/seperator.svg → seperator.svg} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { useEffect, useCallback, useRef, useState } from 'react';
|
|
2
2
|
import { cn } from '@/lib/utils';
|
|
3
3
|
import { Button } from '@/components';
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import MaterialSymbolsCloseSmallOutlineRounded from '~icons/material-symbols/close-small-outline-rounded'
|
|
5
|
+
import SolarArrowRightBoldDuotone from '~icons/solar/arrow-right-bold-duotone';
|
|
6
6
|
import { useLocalTranslation } from '../../useLocalTranslation';
|
|
7
7
|
|
|
8
8
|
interface ImagePreviewDialogProps {
|
|
@@ -212,19 +212,19 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
212
212
|
|
|
213
213
|
return (
|
|
214
214
|
<div
|
|
215
|
-
className='babylai
|
|
215
|
+
className='babylai:fixed babylai:inset-0 babylai:z-9999 babylai:flex babylai:items-center babylai:justify-center'
|
|
216
216
|
onClick={handleClose}
|
|
217
217
|
role='dialog'
|
|
218
218
|
aria-modal='true'
|
|
219
219
|
aria-label='Image preview dialog'
|
|
220
220
|
>
|
|
221
221
|
{/* Backdrop */}
|
|
222
|
-
<div className='babylai
|
|
222
|
+
<div className='babylai:absolute babylai:inset-0 babylai:bg-black babylai:bg-opacity-95' />
|
|
223
223
|
|
|
224
224
|
{/* Dialog content */}
|
|
225
225
|
<div
|
|
226
226
|
ref={containerRef}
|
|
227
|
-
className='babylai
|
|
227
|
+
className='babylai:relative babylai:w-full babylai:h-full babylai:flex babylai:items-center babylai:justify-center babylai:overflow-hidden'
|
|
228
228
|
onClick={(e) => e.stopPropagation()}
|
|
229
229
|
onWheel={handleWheel}
|
|
230
230
|
onMouseDown={handleMouseDown}
|
|
@@ -238,15 +238,15 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
238
238
|
size='icon'
|
|
239
239
|
onClick={handleClose}
|
|
240
240
|
className={cn(
|
|
241
|
-
'babylai
|
|
242
|
-
dir === 'rtl' ? 'babylai
|
|
243
|
-
'babylai
|
|
244
|
-
'babylai
|
|
241
|
+
'babylai:absolute babylai:top-4 babylai:z-60',
|
|
242
|
+
dir === 'rtl' ? 'babylai:left-4' : 'babylai:right-4',
|
|
243
|
+
'babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10',
|
|
244
|
+
'babylai:h-10 babylai:w-10 babylai:rounded-full'
|
|
245
245
|
)}
|
|
246
246
|
aria-label='Close preview'
|
|
247
247
|
type='button'
|
|
248
248
|
>
|
|
249
|
-
<
|
|
249
|
+
<MaterialSymbolsCloseSmallOutlineRounded className='babylai:w-6 babylai:h-6' />
|
|
250
250
|
</Button>
|
|
251
251
|
|
|
252
252
|
{/* Navigation Buttons */}
|
|
@@ -258,16 +258,16 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
258
258
|
onClick={dir === 'rtl' ? handleNext : handlePrevious}
|
|
259
259
|
disabled={dir === 'rtl' ? currentIndex === imageUrls.length - 1 : currentIndex === 0}
|
|
260
260
|
className={cn(
|
|
261
|
-
'babylai
|
|
262
|
-
dir === 'rtl' ? 'babylai
|
|
263
|
-
'babylai
|
|
264
|
-
'babylai
|
|
265
|
-
'disabled:
|
|
261
|
+
'babylai:absolute babylai:top-1/2 babylai:-translate-y-1/2 babylai:z-60',
|
|
262
|
+
dir === 'rtl' ? 'babylai:right-4' : 'babylai:left-4',
|
|
263
|
+
'babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10',
|
|
264
|
+
'babylai:h-12 babylai:w-12 babylai:rounded-full',
|
|
265
|
+
'babylai:disabled:opacity-30'
|
|
266
266
|
)}
|
|
267
267
|
aria-label='Previous image'
|
|
268
268
|
type='button'
|
|
269
269
|
>
|
|
270
|
-
<
|
|
270
|
+
<SolarArrowRightBoldDuotone className={cn('babylai:w-8 babylai:h-8', dir === 'rtl' ? '' : 'babylai:rotate-180')} />
|
|
271
271
|
</Button>
|
|
272
272
|
<Button
|
|
273
273
|
variant='ghost'
|
|
@@ -275,16 +275,16 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
275
275
|
onClick={dir === 'rtl' ? handlePrevious : handleNext}
|
|
276
276
|
disabled={dir === 'rtl' ? currentIndex === 0 : currentIndex === imageUrls.length - 1}
|
|
277
277
|
className={cn(
|
|
278
|
-
'babylai
|
|
279
|
-
dir === 'rtl' ? 'babylai
|
|
280
|
-
'babylai
|
|
281
|
-
'babylai
|
|
282
|
-
'disabled:
|
|
278
|
+
'babylai:absolute babylai:top-1/2 babylai:-translate-y-1/2 babylai:z-60',
|
|
279
|
+
dir === 'rtl' ? 'babylai:left-4' : 'babylai:right-4',
|
|
280
|
+
'babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10',
|
|
281
|
+
'babylai:h-12 babylai:w-12 babylai:rounded-full',
|
|
282
|
+
'babylai:disabled:opacity-30'
|
|
283
283
|
)}
|
|
284
284
|
aria-label='Next image'
|
|
285
285
|
type='button'
|
|
286
286
|
>
|
|
287
|
-
<
|
|
287
|
+
<SolarArrowRightBoldDuotone className={cn('babylai:w-8 babylai:h-8', dir === 'rtl' ? 'babylai:rotate-180' : '')} />
|
|
288
288
|
</Button>
|
|
289
289
|
</>
|
|
290
290
|
)}
|
|
@@ -292,10 +292,10 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
292
292
|
{/* Zoom Controls */}
|
|
293
293
|
<div
|
|
294
294
|
className={cn(
|
|
295
|
-
'babylai
|
|
296
|
-
'babylai
|
|
297
|
-
'babylai
|
|
298
|
-
dir === 'rtl' ? 'babylai
|
|
295
|
+
'babylai:absolute babylai:bottom-4 babylai:z-60',
|
|
296
|
+
'babylai:flex babylai:items-center babylai:gap-2',
|
|
297
|
+
'babylai:bg-black/50 babylai:backdrop-blur-sm babylai:rounded-lg babylai:p-2',
|
|
298
|
+
dir === 'rtl' ? 'babylai:right-1/2 babylai:translate-x-1/2' : 'babylai:left-1/2 babylai:-translate-x-1/2'
|
|
299
299
|
)}
|
|
300
300
|
>
|
|
301
301
|
<Button
|
|
@@ -303,15 +303,15 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
303
303
|
size='icon'
|
|
304
304
|
onClick={handleZoomOut}
|
|
305
305
|
disabled={zoomLevel <= 0.5}
|
|
306
|
-
className='babylai
|
|
306
|
+
className='babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10 babylai:h-9 babylai:w-9 babylai:disabled:opacity-30'
|
|
307
307
|
aria-label='Zoom out'
|
|
308
308
|
type='button'
|
|
309
309
|
>
|
|
310
|
-
<svg className='babylai
|
|
310
|
+
<svg className='babylai:w-5 babylai:h-5' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
|
|
311
311
|
<path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM13 10H7' />
|
|
312
312
|
</svg>
|
|
313
313
|
</Button>
|
|
314
|
-
<span className='babylai
|
|
314
|
+
<span className='babylai:text-white babylai:text-sm babylai:font-medium babylai:min-w-12 babylai:text-center'>
|
|
315
315
|
{Math.round(zoomLevel * 100)}%
|
|
316
316
|
</span>
|
|
317
317
|
<Button
|
|
@@ -319,11 +319,11 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
319
319
|
size='icon'
|
|
320
320
|
onClick={handleZoomIn}
|
|
321
321
|
disabled={zoomLevel >= 3}
|
|
322
|
-
className='babylai
|
|
322
|
+
className='babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10 babylai:h-9 babylai:w-9 babylai:disabled:opacity-30'
|
|
323
323
|
aria-label='Zoom in'
|
|
324
324
|
type='button'
|
|
325
325
|
>
|
|
326
|
-
<svg className='babylai
|
|
326
|
+
<svg className='babylai:w-5 babylai:h-5' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
|
|
327
327
|
<path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v6m3-3H7' />
|
|
328
328
|
</svg>
|
|
329
329
|
</Button>
|
|
@@ -332,7 +332,7 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
332
332
|
variant='ghost'
|
|
333
333
|
size='sm'
|
|
334
334
|
onClick={handleResetZoom}
|
|
335
|
-
className='babylai
|
|
335
|
+
className='babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10 babylai:h-9 babylai:px-3 babylai:ml-2'
|
|
336
336
|
aria-label='Reset zoom'
|
|
337
337
|
type='button'
|
|
338
338
|
>
|
|
@@ -340,16 +340,16 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
340
340
|
</Button>
|
|
341
341
|
)}
|
|
342
342
|
{/* Download Button */}
|
|
343
|
-
<div className='babylai
|
|
343
|
+
<div className='babylai:h-9 babylai:w-px babylai:bg-white/20 babylai:mx-1' />
|
|
344
344
|
<Button
|
|
345
345
|
variant='ghost'
|
|
346
346
|
size='icon'
|
|
347
347
|
onClick={handleDownload}
|
|
348
|
-
className='babylai
|
|
348
|
+
className='babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10 babylai:h-9 babylai:w-9'
|
|
349
349
|
aria-label='Download image'
|
|
350
350
|
type='button'
|
|
351
351
|
>
|
|
352
|
-
<svg className='babylai
|
|
352
|
+
<svg className='babylai:w-5 babylai:h-5' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
|
|
353
353
|
<path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4' />
|
|
354
354
|
</svg>
|
|
355
355
|
</Button>
|
|
@@ -359,12 +359,12 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
359
359
|
{hasMultipleImages && (
|
|
360
360
|
<div
|
|
361
361
|
className={cn(
|
|
362
|
-
'babylai
|
|
363
|
-
'babylai
|
|
364
|
-
dir === 'rtl' ? 'babylai
|
|
362
|
+
'babylai:absolute babylai:top-4 babylai:z-60',
|
|
363
|
+
'babylai:bg-black/50 babylai:backdrop-blur-sm babylai:rounded-lg babylai:px-4 babylai:py-2',
|
|
364
|
+
dir === 'rtl' ? 'babylai:right-1/2 babylai:translate-x-1/2' : 'babylai:left-1/2 babylai:-translate-x-1/2'
|
|
365
365
|
)}
|
|
366
366
|
>
|
|
367
|
-
<span className='babylai
|
|
367
|
+
<span className='babylai:text-white babylai:text-sm babylai:font-medium'>
|
|
368
368
|
{currentIndex + 1} / {imageUrls.length}
|
|
369
369
|
</span>
|
|
370
370
|
</div>
|
|
@@ -372,7 +372,7 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
372
372
|
|
|
373
373
|
{/* Image Container */}
|
|
374
374
|
<div
|
|
375
|
-
className='babylai
|
|
375
|
+
className='babylai:flex babylai:items-center babylai:justify-center'
|
|
376
376
|
style={{
|
|
377
377
|
transform: `translate(${imagePosition.x}px, ${imagePosition.y}px)`,
|
|
378
378
|
cursor: zoomLevel > 1 ? (isDragging ? 'grabbing' : 'grab') : 'default',
|
|
@@ -382,7 +382,7 @@ export const ImagePreviewDialog: React.FC<ImagePreviewDialogProps> = ({
|
|
|
382
382
|
ref={imageRef}
|
|
383
383
|
src={currentImageUrl}
|
|
384
384
|
alt={alt}
|
|
385
|
-
className='babylai
|
|
385
|
+
className='babylai:max-w-[90vw] babylai:max-h-[85vh] babylai:object-contain babylai:select-none'
|
|
386
386
|
style={{
|
|
387
387
|
transform: `scale(${zoomLevel})`,
|
|
388
388
|
transformOrigin: 'center center',
|
package/src/core/AblyService.ts
CHANGED
|
@@ -133,23 +133,28 @@ export class ClientAblyService {
|
|
|
133
133
|
| null;
|
|
134
134
|
|
|
135
135
|
// Extract downloadUrl from attachments (Ably now returns downloadUrl directly)
|
|
136
|
-
// Attachments can be: strings (URLs), objects with downloadUrl, or
|
|
137
|
-
const attachmentUrls =
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
} else if (attachment?.url) {
|
|
146
|
-
// Fallback to url property
|
|
147
|
-
return attachment.url;
|
|
136
|
+
// Attachments can be: strings (URLs), objects with downloadUrl, url, or id only
|
|
137
|
+
const attachmentUrls: string[] = [];
|
|
138
|
+
const attachmentIdsFromAttachments: string[] = [];
|
|
139
|
+
for (const attachment of attachments) {
|
|
140
|
+
if (typeof attachment === 'string') {
|
|
141
|
+
if (attachment.startsWith('http://') || attachment.startsWith('https://')) {
|
|
142
|
+
attachmentUrls.push(attachment);
|
|
143
|
+
} else {
|
|
144
|
+
attachmentIdsFromAttachments.push(attachment);
|
|
148
145
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
})
|
|
152
|
-
|
|
146
|
+
} else if (attachment?.downloadUrl) {
|
|
147
|
+
attachmentUrls.push(attachment.downloadUrl);
|
|
148
|
+
} else if (attachment?.url) {
|
|
149
|
+
attachmentUrls.push(attachment.url);
|
|
150
|
+
} else if (attachment?.id && typeof attachment.id === 'string') {
|
|
151
|
+
attachmentIdsFromAttachments.push(attachment.id);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const attachmentIds =
|
|
155
|
+
attachmentIdsFromAttachments.length > 0
|
|
156
|
+
? attachmentIdsFromAttachments
|
|
157
|
+
: (rawData?.attachmentIds as string[] | undefined) || [];
|
|
153
158
|
|
|
154
159
|
// Invoke optional action handler first (non-blocking for message processing)
|
|
155
160
|
if (this.onActionReceived && actionType !== undefined) {
|
|
@@ -164,7 +169,7 @@ export class ClientAblyService {
|
|
|
164
169
|
}
|
|
165
170
|
}
|
|
166
171
|
|
|
167
|
-
onMessageReceived(messageContent, senderType, needsAgent, attachmentUrls);
|
|
172
|
+
onMessageReceived(messageContent, senderType, needsAgent, attachmentUrls, attachmentIds);
|
|
168
173
|
} catch (error) {
|
|
169
174
|
console.error('[AblyService] Error processing message', { error, message });
|
|
170
175
|
}
|
package/src/core/api.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defaultLanguage } from '@/i18n';
|
|
2
|
+
import { TokenResponse, PresignUploadRequestDto, PresignUploadResponse, PresignDownloadResponse } from '@/lib/types';
|
|
2
3
|
|
|
3
4
|
let getTokenFunction: (() => Promise<TokenResponse>) | undefined = undefined;
|
|
4
5
|
let baseUrl: string | null = null;
|
|
@@ -136,16 +137,17 @@ export async function apiRequest(
|
|
|
136
137
|
endpoint: string,
|
|
137
138
|
method = 'GET',
|
|
138
139
|
body: any = null,
|
|
139
|
-
options: { cache?: boolean; timeout?: number; language
|
|
140
|
+
options: { cache?: boolean; timeout?: number; language?: 'ar' | 'en' }
|
|
140
141
|
) {
|
|
141
142
|
if (!baseUrl) throw new Error('API not initialized');
|
|
142
143
|
|
|
143
144
|
const url = `${baseUrl}/${endpoint}`;
|
|
144
145
|
const requestKey = `${method}:${endpoint}:${JSON.stringify(body)}`;
|
|
145
146
|
|
|
146
|
-
// Check for duplicate in-flight requests
|
|
147
|
+
// Check for duplicate in-flight requests (skip for GET: callers receive Response and call .json();
|
|
148
|
+
// sharing the same Response causes "body already consumed" when the second caller parses)
|
|
147
149
|
const duplicateRequest = getDuplicateRequest(requestKey);
|
|
148
|
-
if (duplicateRequest) {
|
|
150
|
+
if (duplicateRequest && method !== 'GET') {
|
|
149
151
|
return duplicateRequest;
|
|
150
152
|
}
|
|
151
153
|
|
|
@@ -162,7 +164,7 @@ export async function apiRequest(
|
|
|
162
164
|
headers: {
|
|
163
165
|
'Content-Type': 'application/json',
|
|
164
166
|
'Cache-Control': method === 'GET' ? 'max-age=30' : 'no-cache',
|
|
165
|
-
'Accept-Language': options.language,
|
|
167
|
+
'Accept-Language': options.language || defaultLanguage,
|
|
166
168
|
},
|
|
167
169
|
body: body ? JSON.stringify(body) : null,
|
|
168
170
|
};
|
|
@@ -218,7 +220,7 @@ export async function apiRequest(
|
|
|
218
220
|
export async function presignUpload(
|
|
219
221
|
chatSessionId: string,
|
|
220
222
|
file: File,
|
|
221
|
-
language:
|
|
223
|
+
language: 'ar' | 'en' = defaultLanguage
|
|
222
224
|
): Promise<PresignUploadResponse> {
|
|
223
225
|
const requestBody: PresignUploadRequestDto = {
|
|
224
226
|
name: file.name,
|
|
@@ -238,7 +240,7 @@ export async function presignUpload(
|
|
|
238
240
|
|
|
239
241
|
return await response.json();
|
|
240
242
|
}
|
|
241
|
-
export async function presignDownload(fileId: string, language:
|
|
243
|
+
export async function presignDownload(fileId: string, language: 'ar' | 'en' = defaultLanguage): Promise<PresignDownloadResponse> {
|
|
242
244
|
try {
|
|
243
245
|
const response = await apiRequest(`NewFile/${fileId}/presign-download`, 'GET', null, {
|
|
244
246
|
language,
|
package/src/globals.css
CHANGED
|
@@ -1,68 +1,234 @@
|
|
|
1
|
-
|
|
2
|
-
@
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
:root,
|
|
6
|
-
:host {
|
|
7
|
-
--babylai-primary-color: #AD49E1;
|
|
8
|
-
--babylai-secondary-color: #F6ECFC;
|
|
9
|
-
--babylai-storm-dust: #3d3d3d;
|
|
10
|
-
--babylai-storm-dust-950: #262626;
|
|
11
|
-
}
|
|
1
|
+
@import url('https://fonts.googleapis.com/css2?family=Cairo:wght@200..1000&display=swap');
|
|
2
|
+
@import "tailwindcss" prefix(babylai);
|
|
12
3
|
|
|
13
|
-
|
|
14
|
-
:
|
|
15
|
-
:
|
|
16
|
-
|
|
17
|
-
--
|
|
18
|
-
--
|
|
19
|
-
|
|
20
|
-
|
|
4
|
+
/* CSS Custom Properties - Light Theme (Default) */
|
|
5
|
+
:root {
|
|
6
|
+
--babylai-font-sans: "Cairo", sans-serif;
|
|
7
|
+
/* Light theme colors */
|
|
8
|
+
--black-white-50: #ffffff;
|
|
9
|
+
--black-white-100: #f3f3f3;
|
|
10
|
+
--black-white-200: #e2e2e2;
|
|
11
|
+
--black-white-300: #919191;
|
|
12
|
+
--black-white-400: #606060;
|
|
13
|
+
--black-white-500: #333333;
|
|
14
|
+
--black-white-600: #1f1f1f;
|
|
15
|
+
--black-white-700: #171717;
|
|
16
|
+
--black-white-800: #0a0a0a;
|
|
17
|
+
--black-white-900: #050505;
|
|
18
|
+
--black-white-950: #000000;
|
|
19
|
+
--black-white-default: #333333;
|
|
20
|
+
--storm-dust: #3d3d3d;
|
|
21
|
+
--storm-dust-950: #262626;
|
|
22
|
+
--babylai-primary-color: #ad49e1;
|
|
23
|
+
--babylai-primary-color-100: #f6ecfc;
|
|
24
|
+
--babylai-primary-color-200: #deb6f3;
|
|
25
|
+
--babylai-primary-color-300: #d49cee;
|
|
26
|
+
--babylai-primary-color-400: #c57fea;
|
|
27
|
+
--babylai-primary-color-500: #ad49e1;
|
|
28
|
+
--babylai-primary-color-600: #672b87;
|
|
29
|
+
--babylai-primary-color-700: #451d5a;
|
|
30
|
+
--babylai-primary-color-800: #220e2d;
|
|
31
|
+
--babylai-primary-color-900: #110716;
|
|
32
|
+
--babylai-primary-color-950: #0a0310;
|
|
21
33
|
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
/* Theme-aware colors - Light mode defaults */
|
|
35
|
+
--background: #ffffff;
|
|
36
|
+
--foreground: #333333;
|
|
37
|
+
--card: #ffffff;
|
|
38
|
+
--card-foreground: #333333;
|
|
39
|
+
--popover: #ffffff;
|
|
40
|
+
--popover-foreground: #333333;
|
|
41
|
+
--secondary: #f3f3f3;
|
|
42
|
+
--secondary-foreground: #333333;
|
|
43
|
+
--muted: #f3f3f3;
|
|
44
|
+
--muted-foreground: #606060;
|
|
45
|
+
--accent: #f3f3f3;
|
|
46
|
+
--accent-foreground: #333333;
|
|
47
|
+
--destructive: #ef4444;
|
|
48
|
+
--destructive-foreground: #ffffff;
|
|
49
|
+
--border: #e2e2e2;
|
|
50
|
+
--input: #e2e2e2;
|
|
51
|
+
--ring: var(--babylai-primary-color);
|
|
52
|
+
--radius: 0.5rem;
|
|
24
53
|
}
|
|
25
54
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
55
|
+
/* Tailwind v4 Theme Configuration - must come after @import */
|
|
56
|
+
/* Using actual color values for build-time, CSS variables will override at runtime */
|
|
57
|
+
/* postcss-disable-next-line */
|
|
58
|
+
@theme {
|
|
59
|
+
/* Font Family - override Tailwind's default sans font */
|
|
60
|
+
--font-sans: "Cairo", sans-serif;
|
|
32
61
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
62
|
+
/* Primary Colors - default light theme values */
|
|
63
|
+
--color-primary: var(--babylai-primary-color);
|
|
64
|
+
--color-primary-100: var(--babylai-primary-color-100);
|
|
65
|
+
--color-primary-200: var(--babylai-primary-color-200);
|
|
66
|
+
--color-primary-300: var(--babylai-primary-color-300);
|
|
67
|
+
--color-primary-400: var(--babylai-primary-color-400);
|
|
68
|
+
--color-primary-500: var(--babylai-primary-color-500);
|
|
69
|
+
--color-primary-600: var(--babylai-primary-color-600);
|
|
70
|
+
--color-primary-700: var(--babylai-primary-color-700);
|
|
71
|
+
--color-primary-800: var(--babylai-primary-color-800);
|
|
72
|
+
--color-primary-900: var(--babylai-primary-color-900);
|
|
73
|
+
--color-primary-950: var(--babylai-primary-color-950);
|
|
74
|
+
|
|
75
|
+
/* Theme Colors - default light theme values */
|
|
76
|
+
--color-background: var(--background);
|
|
77
|
+
--color-foreground: var(--foreground);
|
|
78
|
+
--color-card: var(--card);
|
|
79
|
+
--color-card-foreground: var(--card-foreground);
|
|
80
|
+
--color-popover: var(--popover);
|
|
81
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
82
|
+
--color-secondary: var(--secondary);
|
|
83
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
84
|
+
--color-muted: var(--muted);
|
|
85
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
86
|
+
--color-accent: var(--accent);
|
|
87
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
88
|
+
--color-destructive: var(--destructive);
|
|
89
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
90
|
+
--color-border: var(--border);
|
|
91
|
+
--color-input: var(--input);
|
|
92
|
+
--color-ring: var(--ring);
|
|
93
|
+
|
|
94
|
+
/* Black-White Scale */
|
|
95
|
+
--color-black-white-50: var(--black-white-50);
|
|
96
|
+
--color-black-white-100: var(--black-white-100);
|
|
97
|
+
--color-black-white-200: var(--black-white-200);
|
|
98
|
+
--color-black-white-300: var(--black-white-300);
|
|
99
|
+
--color-black-white-400: var(--black-white-400);
|
|
100
|
+
--color-black-white-500: var(--black-white-500);
|
|
101
|
+
--color-black-white-600: var(--black-white-600);
|
|
102
|
+
--color-black-white-700: var(--black-white-700);
|
|
103
|
+
--color-black-white-800: var(--black-white-800);
|
|
104
|
+
--color-black-white-900: var(--black-white-900);
|
|
105
|
+
--color-black-white-950: var(--black-white-950);
|
|
106
|
+
|
|
107
|
+
/* Storm Dust Colors */
|
|
108
|
+
--color-storm-dust: var(--storm-dust);
|
|
109
|
+
--color-storm-dust-950: var(--storm-dust-950);
|
|
110
|
+
|
|
111
|
+
--animate-wave: wave 1.3s ease-in-out infinite;
|
|
112
|
+
--animate-circular-progress: circular-progress 2s ease-in-out infinite;
|
|
113
|
+
--animate-float: float 3s infinite ease-in-out;
|
|
114
|
+
|
|
115
|
+
@keyframes wave {
|
|
37
116
|
|
|
38
|
-
|
|
39
|
-
|
|
117
|
+
0%,
|
|
118
|
+
60%,
|
|
119
|
+
100% {
|
|
120
|
+
transform: initial;
|
|
121
|
+
}
|
|
40
122
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
123
|
+
30% {
|
|
124
|
+
transform: translateY(-10px);
|
|
125
|
+
}
|
|
44
126
|
}
|
|
45
127
|
|
|
46
|
-
|
|
47
|
-
|
|
128
|
+
@keyframes circular-progress {
|
|
129
|
+
0% {
|
|
130
|
+
stroke-dashoffset: 100.48;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
50% {
|
|
134
|
+
stroke-dashoffset: 25.12;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
100% {
|
|
138
|
+
stroke-dashoffset: 100.48;
|
|
139
|
+
}
|
|
48
140
|
}
|
|
49
|
-
}
|
|
50
141
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
142
|
+
@keyframes float {
|
|
143
|
+
|
|
144
|
+
0%,
|
|
145
|
+
100% {
|
|
146
|
+
transform: translateY(0);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
50% {
|
|
150
|
+
transform: translateY(-10px);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
54
153
|
}
|
|
55
154
|
|
|
56
|
-
/*
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
155
|
+
/* Re-scope primary theme vars on widget root so primaryColor prop (inline style) wins over :root.
|
|
156
|
+
Tailwind v4 with prefix(babylai) emits --babylai-color-primary-* in utilities, so we set
|
|
157
|
+
prefixed names here so they resolve from this element. */
|
|
158
|
+
.babylai-theme-root {
|
|
159
|
+
--babylai-color-primary: var(--babylai-primary-color);
|
|
160
|
+
--babylai-color-primary-100: var(--babylai-primary-color-100);
|
|
161
|
+
--babylai-color-primary-200: var(--babylai-primary-color-200);
|
|
162
|
+
--babylai-color-primary-300: var(--babylai-primary-color-300);
|
|
163
|
+
--babylai-color-primary-400: var(--babylai-primary-color-400);
|
|
164
|
+
--babylai-color-primary-500: var(--babylai-primary-color-500);
|
|
165
|
+
--babylai-color-primary-600: var(--babylai-primary-color-600);
|
|
166
|
+
--babylai-color-primary-700: var(--babylai-primary-color-700);
|
|
167
|
+
--babylai-color-primary-800: var(--babylai-primary-color-800);
|
|
168
|
+
--babylai-color-primary-900: var(--babylai-primary-color-900);
|
|
169
|
+
--babylai-color-primary-950: var(--babylai-primary-color-950);
|
|
170
|
+
--ring: var(--babylai-primary-color);
|
|
171
|
+
--color-ring: var(--babylai-primary-color);
|
|
60
172
|
}
|
|
61
173
|
|
|
62
|
-
/* Dark
|
|
174
|
+
/* Dark theme colors */
|
|
63
175
|
@media (prefers-color-scheme: dark) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
176
|
+
:root {
|
|
177
|
+
--black-white-50: #000000;
|
|
178
|
+
--black-white-100: #050505;
|
|
179
|
+
--black-white-200: #0a0a0a;
|
|
180
|
+
--black-white-300: #171717;
|
|
181
|
+
--black-white-400: #1f1f1f;
|
|
182
|
+
--black-white-500: #333333;
|
|
183
|
+
--black-white-600: #606060;
|
|
184
|
+
--black-white-700: #919191;
|
|
185
|
+
--black-white-800: #e2e2e2;
|
|
186
|
+
--black-white-900: #f3f3f3;
|
|
187
|
+
--black-white-950: #ffffff;
|
|
188
|
+
--black-white-default: #e2e2e2;
|
|
189
|
+
--storm-dust: #262626;
|
|
190
|
+
--storm-dust-950: #3d3d3d;
|
|
191
|
+
|
|
192
|
+
/* Theme-aware colors - Dark mode (WCAG 2.1 AA compliant) */
|
|
193
|
+
--background: #121212;
|
|
194
|
+
/* Better than pure black, reduces eye strain */
|
|
195
|
+
--foreground: #ffffff;
|
|
196
|
+
/* High contrast white text */
|
|
197
|
+
--card: #262626;
|
|
198
|
+
/* Slightly lighter than background for depth */
|
|
199
|
+
--card-foreground: #ffffff;
|
|
200
|
+
/* High contrast white text */
|
|
201
|
+
--popover: #1e1e1e;
|
|
202
|
+
/* Consistent with card background */
|
|
203
|
+
--popover-foreground: #ffffff;
|
|
204
|
+
/* High contrast white text */
|
|
205
|
+
--secondary: #3d3d3d;
|
|
206
|
+
/* Accessible secondary background */
|
|
207
|
+
--secondary-foreground: #ffffff;
|
|
208
|
+
/* High contrast white text */
|
|
209
|
+
--muted: #2a2a2a;
|
|
210
|
+
/* Accessible muted background */
|
|
211
|
+
--muted-foreground: #b3b3b3;
|
|
212
|
+
/* WCAG AA compliant contrast (4.5:1) */
|
|
213
|
+
--accent: #2a2a2a;
|
|
214
|
+
/* Accessible accent background */
|
|
215
|
+
--accent-foreground: #ffffff;
|
|
216
|
+
/* High contrast white text */
|
|
217
|
+
--destructive: #ff6b6b;
|
|
218
|
+
/* More accessible red with better contrast */
|
|
219
|
+
--destructive-foreground: #ffffff;
|
|
220
|
+
/* High contrast white text */
|
|
221
|
+
--border: #404040;
|
|
222
|
+
/* Better contrast for borders */
|
|
223
|
+
--input: var(--card);
|
|
224
|
+
/* Accessible input background */
|
|
225
|
+
--ring: var(--babylai-primary-color);
|
|
226
|
+
/* Keep primary color for focus rings */
|
|
67
227
|
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.bg-header {
|
|
231
|
+
background: linear-gradient(171deg,
|
|
232
|
+
color-mix(in srgb, var(--babylai-primary-color) 25%, transparent) -131.06%,
|
|
233
|
+
color-mix(in srgb, var(--black-white-50) 25%, transparent) 89.82%);
|
|
68
234
|
}
|