@aslaluroba/help-center-react 3.2.4 → 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.
- 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/AblyService.d.ts +4 -1
- package/dist/core/api.d.ts +4 -4
- package/dist/index.css +1 -1
- package/dist/index.esm.js +16040 -15655
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +16043 -15664
- package/dist/index.js.map +1 -1
- package/dist/lib/custom-hooks/useActionHandler.d.ts +8 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/theme-utils.d.ts +0 -9
- package/dist/lib/types.d.ts +6 -3
- package/dist/services.esm.js +9588 -9443
- package/dist/services.esm.js.map +1 -1
- package/dist/services.js +9582 -9439
- 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 +60 -23
- package/src/core/api.ts +9 -7
- package/src/globals.css +216 -50
- package/src/lib/custom-hooks/useActionHandler.ts +102 -0
- package/src/lib/index.ts +1 -0
- 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 +95 -58
- 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/.DS_Store +0 -0
- 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
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
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export type ActionHandler = (messageData: unknown) => void | Promise<void>;
|
|
4
|
+
|
|
5
|
+
export interface ActionHandlerService {
|
|
6
|
+
registerHandler(actionType: string, handler: ActionHandler): void;
|
|
7
|
+
unregisterHandler(actionType: string): void;
|
|
8
|
+
handleAction(actionType: string | undefined | null, messageData: unknown): Promise<void>;
|
|
9
|
+
getRegisteredActions(): string[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const useActionHandler = (): ActionHandlerService => {
|
|
13
|
+
const handlersRef = useRef<Map<string, ActionHandler>>(new Map());
|
|
14
|
+
|
|
15
|
+
const defaultHandlerRef = useRef<ActionHandler>((messageData) => {
|
|
16
|
+
const message = (messageData as { actionType?: string } | undefined) ?? {};
|
|
17
|
+
const actionType = message.actionType || '';
|
|
18
|
+
|
|
19
|
+
if (actionType) {
|
|
20
|
+
// Log unknown actions for debugging but do not crash
|
|
21
|
+
// eslint-disable-next-line no-console
|
|
22
|
+
console.warn(
|
|
23
|
+
`[ActionHandler] Unknown action type received: "${actionType}". Message data:`,
|
|
24
|
+
messageData
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const registerHandler = useCallback((actionType: string, handler: ActionHandler) => {
|
|
30
|
+
if (!actionType) {
|
|
31
|
+
// eslint-disable-next-line no-console
|
|
32
|
+
console.warn('[ActionHandler] Attempted to register handler with empty action type. Ignored.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (handlersRef.current.has(actionType)) {
|
|
37
|
+
// eslint-disable-next-line no-console
|
|
38
|
+
console.warn(
|
|
39
|
+
`[ActionHandler] Handler for action type "${actionType}" already exists. Overwriting with new handler.`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
handlersRef.current.set(actionType, handler);
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
const unregisterHandler = useCallback((actionType: string) => {
|
|
47
|
+
if (!actionType) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
handlersRef.current.delete(actionType);
|
|
51
|
+
}, []);
|
|
52
|
+
|
|
53
|
+
const handleAction = useCallback(
|
|
54
|
+
async (actionType: string | undefined | null, messageData: unknown) => {
|
|
55
|
+
// Ignore empty, null, or undefined action types (no-op)
|
|
56
|
+
if (!actionType || actionType === '') {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const handler = handlersRef.current.get(actionType);
|
|
61
|
+
|
|
62
|
+
if (handler) {
|
|
63
|
+
try {
|
|
64
|
+
await handler(messageData);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
// eslint-disable-next-line no-console
|
|
67
|
+
console.error(
|
|
68
|
+
`[ActionHandler] Error executing handler for action type "${actionType}":`,
|
|
69
|
+
error
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const defaultHandler = defaultHandlerRef.current;
|
|
76
|
+
if (defaultHandler) {
|
|
77
|
+
try {
|
|
78
|
+
await Promise.resolve(defaultHandler(messageData));
|
|
79
|
+
} catch (error) {
|
|
80
|
+
// eslint-disable-next-line no-console
|
|
81
|
+
console.error(
|
|
82
|
+
`[ActionHandler] Error executing default handler for unknown action type "${actionType}":`,
|
|
83
|
+
error
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
[]
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const getRegisteredActions = useCallback(() => {
|
|
92
|
+
return Array.from(handlersRef.current.keys());
|
|
93
|
+
}, []);
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
registerHandler,
|
|
97
|
+
unregisterHandler,
|
|
98
|
+
handleAction,
|
|
99
|
+
getRegisteredActions,
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
package/src/lib/index.ts
CHANGED
package/src/lib/theme-utils.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
export interface ThemeColors {
|
|
6
6
|
primaryColor?: string;
|
|
7
|
-
secondaryColor?: string;
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
/**
|
|
@@ -12,7 +11,7 @@ export interface ThemeColors {
|
|
|
12
11
|
*/
|
|
13
12
|
export const getPrimaryColorStyles = (primaryColor?: string) => {
|
|
14
13
|
if (!primaryColor) return {};
|
|
15
|
-
|
|
14
|
+
|
|
16
15
|
return {
|
|
17
16
|
'--babylai-primary-color': primaryColor,
|
|
18
17
|
'--babylai-primary-color-100': lightenColor(primaryColor, 0.9),
|
|
@@ -28,37 +27,6 @@ export const getPrimaryColorStyles = (primaryColor?: string) => {
|
|
|
28
27
|
} as React.CSSProperties;
|
|
29
28
|
};
|
|
30
29
|
|
|
31
|
-
/**
|
|
32
|
-
* Generate dynamic styles for secondary color
|
|
33
|
-
*/
|
|
34
|
-
export const getSecondaryColorStyles = (secondaryColor?: string) => {
|
|
35
|
-
if (!secondaryColor) return {};
|
|
36
|
-
|
|
37
|
-
return {
|
|
38
|
-
'--babylai-secondary-color': secondaryColor,
|
|
39
|
-
'--babylai-secondary-color-100': lightenColor(secondaryColor, 0.9),
|
|
40
|
-
'--babylai-secondary-color-200': lightenColor(secondaryColor, 0.8),
|
|
41
|
-
'--babylai-secondary-color-300': lightenColor(secondaryColor, 0.7),
|
|
42
|
-
'--babylai-secondary-color-400': lightenColor(secondaryColor, 0.6),
|
|
43
|
-
'--babylai-secondary-color-500': secondaryColor,
|
|
44
|
-
'--babylai-secondary-color-600': darkenColor(secondaryColor, 0.1),
|
|
45
|
-
'--babylai-secondary-color-700': darkenColor(secondaryColor, 0.2),
|
|
46
|
-
'--babylai-secondary-color-800': darkenColor(secondaryColor, 0.3),
|
|
47
|
-
'--babylai-secondary-color-900': darkenColor(secondaryColor, 0.4),
|
|
48
|
-
'--babylai-secondary-color-950': darkenColor(secondaryColor, 0.5),
|
|
49
|
-
} as React.CSSProperties;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Get combined theme styles
|
|
54
|
-
*/
|
|
55
|
-
export const getThemeStyles = (colors: ThemeColors): React.CSSProperties => {
|
|
56
|
-
return {
|
|
57
|
-
...getPrimaryColorStyles(colors.primaryColor),
|
|
58
|
-
...getSecondaryColorStyles(colors.secondaryColor),
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
|
|
62
30
|
/**
|
|
63
31
|
* Lighten a color by a percentage
|
|
64
32
|
*/
|
package/src/lib/types.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export interface HelpCenterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
2
2
|
helpScreenId: string;
|
|
3
3
|
primaryColor?: string;
|
|
4
|
-
|
|
5
|
-
logoUrl?: string;
|
|
4
|
+
language?: 'ar' | 'en';
|
|
6
5
|
}
|
|
7
6
|
|
|
8
7
|
export interface Theme {
|
|
@@ -88,7 +87,11 @@ export interface HelpScreenData {
|
|
|
88
87
|
tenant: {
|
|
89
88
|
id: string;
|
|
90
89
|
name: string;
|
|
91
|
-
key: string;
|
|
90
|
+
key: string;
|
|
91
|
+
logoUrl: string;
|
|
92
|
+
settings: {
|
|
93
|
+
description: string;
|
|
94
|
+
};
|
|
92
95
|
};
|
|
93
96
|
title: string;
|
|
94
97
|
description: string;
|
|
@@ -125,7 +128,7 @@ export interface Option {
|
|
|
125
128
|
}
|
|
126
129
|
|
|
127
130
|
export interface ReviewProps {
|
|
128
|
-
comment
|
|
131
|
+
comment?: string;
|
|
129
132
|
rating: number;
|
|
130
133
|
}
|
|
131
134
|
|
package/src/locales/ar.json
CHANGED
|
@@ -13,21 +13,31 @@
|
|
|
13
13
|
"poweredBy": "مدعوم بواسطة",
|
|
14
14
|
|
|
15
15
|
"ReviewDialog": {
|
|
16
|
-
"title": "
|
|
17
|
-
"
|
|
16
|
+
"title": "نحن نقدر ملاحظاتك!",
|
|
17
|
+
"simple_title": "نود معرفة رأيك!",
|
|
18
|
+
"simple_description": "رأيك يساعدنا على التحسين وتقديم دعم أفضل. يُرجى تقييم تجربتك مع خدمتنا وإخبارنا كيف كان أداؤنا.",
|
|
19
|
+
"description": "رأيك يساعدنا على التحسين وتقديم دعم أفضل. يُرجى تقييم تجربتك مع خدمتنا وإخبارنا كيف كان أداؤنا.",
|
|
18
20
|
"rating_label": "التقييم:",
|
|
19
21
|
"comment_label": "التعليق:",
|
|
20
22
|
"comment_placeholder": "اكتب تعليقك هنا...",
|
|
21
23
|
"submit_button": "إرسال التقييم",
|
|
24
|
+
"rate_button": "تقييم",
|
|
22
25
|
"comment_error": "يجب أن يكون التعليق بين 10 و500 حرف.",
|
|
23
26
|
"rating_error": "يجب أن يكون التقييم بين 1 و5.",
|
|
24
27
|
"skip_button": "تخطي"
|
|
25
28
|
},
|
|
29
|
+
"InChatReview": {
|
|
30
|
+
"title": "كيف كانت محادثتك معنا اليوم؟",
|
|
31
|
+
"description": "نحب أن نعرف كيف كان أداؤنا - ملاحظاتك تساعدنا على جعل كل محادثة أفضل.",
|
|
32
|
+
"follow_up": "رائع! نحن سعداء أنك استمتعت بالدردشة معنا. هل يمكنك تقييم تجربتك الإجمالية لمساعدتنا على الحفاظ على ذلك؟",
|
|
33
|
+
"note_placeholder": "اكتب ملاحظتك",
|
|
34
|
+
"submit_button": "تقديم"
|
|
35
|
+
},
|
|
26
36
|
"ConfirmationModal": {
|
|
27
|
-
"title": "
|
|
28
|
-
"message": "
|
|
29
|
-
"confirmation_button": "
|
|
30
|
-
"cancel_button": "
|
|
37
|
+
"title": "تريد المغادرة؟ 👋",
|
|
38
|
+
"message": "لا تقلق، يمكنك العودة في أي وقت. نحن دائما هنا إذا كنت تحتاج مساعدة أو لديك أسئلة.",
|
|
39
|
+
"confirmation_button": "إغلاق المحادثة",
|
|
40
|
+
"cancel_button": "استمرار",
|
|
31
41
|
"endAndStartNewChatTitle": "إنهاء وبدء محادثة جديدة",
|
|
32
42
|
"endAndStartNewChatMessage": "هل أنت متأكد أنك تريد إنهاء هذه المحادثة وبدء محادثة جديدة؟"
|
|
33
43
|
}
|
package/src/locales/en.json
CHANGED
|
@@ -13,21 +13,31 @@
|
|
|
13
13
|
"poweredBy": "Powered by",
|
|
14
14
|
|
|
15
15
|
"ReviewDialog": {
|
|
16
|
-
"title": "
|
|
17
|
-
"
|
|
16
|
+
"title": "We’d Love Your Feedback!",
|
|
17
|
+
"simple_title": "We'd Love Your Feedback!",
|
|
18
|
+
"simple_description": "Your opinion helps us improve and deliver better support. Please rate your experience with our service and let us know how we did.",
|
|
19
|
+
"description": "Your opinion helps us improve and deliver better support. Please rate your experience with our service and let us know how we did.",
|
|
18
20
|
"rating_label": "Rating:",
|
|
19
21
|
"comment_label": "Comment:",
|
|
20
22
|
"comment_placeholder": "Write your comment here...",
|
|
21
23
|
"submit_button": "Submit Review",
|
|
24
|
+
"rate_button": "Rate",
|
|
22
25
|
"comment_error": "Comment must be between 10 and 500 characters.",
|
|
23
26
|
"rating_error": "Rating must be between 1 and 5.",
|
|
24
27
|
"skip_button": "Skip"
|
|
25
28
|
},
|
|
29
|
+
"InChatReview": {
|
|
30
|
+
"title": "How was your conversation with us today?",
|
|
31
|
+
"description": "We'd love to know how we did - your feedback helps us make every chat even better.",
|
|
32
|
+
"follow_up": "Awesome! We're glad you enjoyed chatting with us. Could you rate your overall experience to help us keep it that way?",
|
|
33
|
+
"note_placeholder": "Write Your Note",
|
|
34
|
+
"submit_button": "Submit Review"
|
|
35
|
+
},
|
|
26
36
|
"ConfirmationModal": {
|
|
27
|
-
"title": "
|
|
28
|
-
"message": "
|
|
29
|
-
"confirmation_button": "
|
|
30
|
-
"cancel_button": "
|
|
37
|
+
"title": "Leaving so soon? 👋",
|
|
38
|
+
"message": "Don't worry, you can come back anytime. We're always here if you need help or have questions.",
|
|
39
|
+
"confirmation_button": "Close Chat",
|
|
40
|
+
"cancel_button": "Continue",
|
|
31
41
|
"endAndStartNewChatTitle": "End and Start New Chat",
|
|
32
42
|
"endAndStartNewChatMessage": "Are you sure you want to end the current conversation and start a new one?"
|
|
33
43
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Button } from '@/components';
|
|
2
|
+
import { useLocalTranslation } from '@/useLocalTranslation';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import SolarPlain2BoldDuotone from '~icons/solar/plain-2-bold-duotone';
|
|
5
|
+
|
|
6
|
+
interface ActiveChatActionsProps {
|
|
7
|
+
onConfirm: () => void;
|
|
8
|
+
onCancel: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const ActiveChatActions: React.FC<ActiveChatActionsProps> = ({
|
|
12
|
+
onConfirm,
|
|
13
|
+
onCancel,
|
|
14
|
+
}) => {
|
|
15
|
+
const { t } = useLocalTranslation();
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<section className="babylai:flex babylai:justify-between babylai:gap-3 babylai:px-4 babylai:py-6 babylai:absolute babylai:left-0 babylai:right-0 babylai:bottom-11 babylai:z-20 babylai:bg-linear-to-t babylai:from-card babylai:to-transparent babylai:from-[28.32%] babylai:to-[112.59%]">
|
|
19
|
+
<Button
|
|
20
|
+
onClick={onConfirm}
|
|
21
|
+
variant='secondary'
|
|
22
|
+
>
|
|
23
|
+
{t('homeSdk.ConfirmationModal.confirmation_button')}
|
|
24
|
+
|
|
25
|
+
</Button>
|
|
26
|
+
<Button
|
|
27
|
+
onClick={onCancel}
|
|
28
|
+
variant='default'
|
|
29
|
+
>
|
|
30
|
+
{t('homeSdk.ConfirmationModal.cancel_button')}
|
|
31
|
+
<SolarPlain2BoldDuotone className="babylai:w-6 babylai:h-6" />
|
|
32
|
+
</Button>
|
|
33
|
+
</section>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
ActiveChatActions.displayName = 'ActiveChatActions';
|
|
38
|
+
|
|
39
|
+
export default ActiveChatActions;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { cn } from '@/lib/utils';
|
|
3
|
+
|
|
4
|
+
interface ActionButtonProps {
|
|
5
|
+
onClick: () => void;
|
|
6
|
+
icon?: React.ReactNode;
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
ariaLabel?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const ActionButton: React.FC<ActionButtonProps> = ({
|
|
13
|
+
onClick,
|
|
14
|
+
icon,
|
|
15
|
+
children,
|
|
16
|
+
ariaLabel,
|
|
17
|
+
className,
|
|
18
|
+
}) => {
|
|
19
|
+
return (
|
|
20
|
+
<button
|
|
21
|
+
onClick={onClick}
|
|
22
|
+
className={cn(
|
|
23
|
+
'babylai:bg-card babylai:text-card-foreground babylai:h-6 babylai:w-8 babylai:rounded-full babylai:flex babylai:items-center babylai:justify-center babylai:font-bold babylai:text-base babylai:ml-auto babylai:cursor-pointer',
|
|
24
|
+
className
|
|
25
|
+
)}
|
|
26
|
+
aria-label={ariaLabel}
|
|
27
|
+
type="button"
|
|
28
|
+
>
|
|
29
|
+
{icon}
|
|
30
|
+
{children}
|
|
31
|
+
</button>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
ActionButton.displayName = 'ActionButton';
|
|
36
|
+
|
|
37
|
+
export default ActionButton;
|