@bytexbyte/nxtlinq-ai-agent-ui-react-development 0.1.1

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 (142) hide show
  1. package/dist/NxtlinqAgentChat.d.ts +26 -0
  2. package/dist/NxtlinqAgentChat.d.ts.map +1 -0
  3. package/dist/NxtlinqAgentChat.js +28 -0
  4. package/dist/components/AgentAssistantShell.d.ts +5 -0
  5. package/dist/components/AgentAssistantShell.d.ts.map +1 -0
  6. package/dist/components/AgentAssistantShell.js +52 -0
  7. package/dist/components/AgentComposer.d.ts +3 -0
  8. package/dist/components/AgentComposer.d.ts.map +1 -0
  9. package/dist/components/AgentComposer.js +60 -0
  10. package/dist/components/AgentMessageList.d.ts +3 -0
  11. package/dist/components/AgentMessageList.d.ts.map +1 -0
  12. package/dist/components/AgentMessageList.js +37 -0
  13. package/dist/components/AgentRemoteAudio.d.ts +4 -0
  14. package/dist/components/AgentRemoteAudio.d.ts.map +1 -0
  15. package/dist/components/AgentRemoteAudio.js +34 -0
  16. package/dist/components/AgentVoiceBar.d.ts +3 -0
  17. package/dist/components/AgentVoiceBar.d.ts.map +1 -0
  18. package/dist/components/AgentVoiceBar.js +91 -0
  19. package/dist/components/PresetMessageChips.d.ts +3 -0
  20. package/dist/components/PresetMessageChips.d.ts.map +1 -0
  21. package/dist/components/PresetMessageChips.js +23 -0
  22. package/dist/context/AgentAssistantContext.d.ts +32 -0
  23. package/dist/context/AgentAssistantContext.d.ts.map +1 -0
  24. package/dist/context/AgentAssistantContext.js +159 -0
  25. package/dist/index.d.ts +16 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +12 -0
  28. package/dist/legacy/assets/images/adiSideItalicDataUri.d.ts +2 -0
  29. package/dist/legacy/assets/images/adiSideItalicDataUri.d.ts.map +1 -0
  30. package/dist/legacy/assets/images/adiSideItalicDataUri.js +1 -0
  31. package/dist/legacy/chatbot/ChatBot.d.ts +5 -0
  32. package/dist/legacy/chatbot/ChatBot.d.ts.map +1 -0
  33. package/dist/legacy/chatbot/ChatBot.js +35 -0
  34. package/dist/legacy/chatbot/context/ChatBotContext.d.ts +5 -0
  35. package/dist/legacy/chatbot/context/ChatBotContext.d.ts.map +1 -0
  36. package/dist/legacy/chatbot/context/ChatBotContext.js +2908 -0
  37. package/dist/legacy/chatbot/types/ChatBotTypes.d.ts +166 -0
  38. package/dist/legacy/chatbot/types/ChatBotTypes.d.ts.map +1 -0
  39. package/dist/legacy/chatbot/types/ChatBotTypes.js +1 -0
  40. package/dist/legacy/chatbot/ui/BerifyMeModal.d.ts +17 -0
  41. package/dist/legacy/chatbot/ui/BerifyMeModal.d.ts.map +1 -0
  42. package/dist/legacy/chatbot/ui/BerifyMeModal.js +110 -0
  43. package/dist/legacy/chatbot/ui/ChatBotUI.d.ts +3 -0
  44. package/dist/legacy/chatbot/ui/ChatBotUI.d.ts.map +1 -0
  45. package/dist/legacy/chatbot/ui/ChatBotUI.js +625 -0
  46. package/dist/legacy/chatbot/ui/MessageInput.d.ts +3 -0
  47. package/dist/legacy/chatbot/ui/MessageInput.d.ts.map +1 -0
  48. package/dist/legacy/chatbot/ui/MessageInput.js +321 -0
  49. package/dist/legacy/chatbot/ui/MessageList.d.ts +4 -0
  50. package/dist/legacy/chatbot/ui/MessageList.d.ts.map +1 -0
  51. package/dist/legacy/chatbot/ui/MessageList.js +455 -0
  52. package/dist/legacy/chatbot/ui/ModelSelector.d.ts +4 -0
  53. package/dist/legacy/chatbot/ui/ModelSelector.d.ts.map +1 -0
  54. package/dist/legacy/chatbot/ui/ModelSelector.js +122 -0
  55. package/dist/legacy/chatbot/ui/NotificationModal.d.ts +15 -0
  56. package/dist/legacy/chatbot/ui/NotificationModal.d.ts.map +1 -0
  57. package/dist/legacy/chatbot/ui/NotificationModal.js +53 -0
  58. package/dist/legacy/chatbot/ui/PermissionForm.d.ts +8 -0
  59. package/dist/legacy/chatbot/ui/PermissionForm.d.ts.map +1 -0
  60. package/dist/legacy/chatbot/ui/PermissionForm.js +465 -0
  61. package/dist/legacy/chatbot/ui/PresetMessages.d.ts +4 -0
  62. package/dist/legacy/chatbot/ui/PresetMessages.d.ts.map +1 -0
  63. package/dist/legacy/chatbot/ui/PresetMessages.js +33 -0
  64. package/dist/legacy/chatbot/ui/VoiceModePanel.d.ts +3 -0
  65. package/dist/legacy/chatbot/ui/VoiceModePanel.d.ts.map +1 -0
  66. package/dist/legacy/chatbot/ui/VoiceModePanel.js +95 -0
  67. package/dist/legacy/chatbot/ui/styles/isolatedStyles.d.ts +73 -0
  68. package/dist/legacy/chatbot/ui/styles/isolatedStyles.d.ts.map +1 -0
  69. package/dist/legacy/chatbot/ui/styles/isolatedStyles.js +985 -0
  70. package/dist/legacy/index.d.ts +14 -0
  71. package/dist/legacy/index.d.ts.map +1 -0
  72. package/dist/legacy/index.js +12 -0
  73. package/dist/theme/defaultTheme.d.ts +3 -0
  74. package/dist/theme/defaultTheme.d.ts.map +1 -0
  75. package/dist/theme/defaultTheme.js +20 -0
  76. package/dist/types.d.ts +62 -0
  77. package/dist/types.d.ts.map +1 -0
  78. package/dist/types.js +1 -0
  79. package/dist/voice/useVoiceConnectOrchestration.d.ts +21 -0
  80. package/dist/voice/useVoiceConnectOrchestration.d.ts.map +1 -0
  81. package/dist/voice/useVoiceConnectOrchestration.js +86 -0
  82. package/dist/voice/useVoiceMicState.d.ts +15 -0
  83. package/dist/voice/useVoiceMicState.d.ts.map +1 -0
  84. package/dist/voice/useVoiceMicState.js +94 -0
  85. package/dist/voice/useVoiceSilenceCommit.d.ts +10 -0
  86. package/dist/voice/useVoiceSilenceCommit.d.ts.map +1 -0
  87. package/dist/voice/useVoiceSilenceCommit.js +67 -0
  88. package/dist/voice/useVoiceTranscriptMessages.d.ts +16 -0
  89. package/dist/voice/useVoiceTranscriptMessages.d.ts.map +1 -0
  90. package/dist/voice/useVoiceTranscriptMessages.js +129 -0
  91. package/dist/voice/useWsRealtimeAudio.d.ts +18 -0
  92. package/dist/voice/useWsRealtimeAudio.d.ts.map +1 -0
  93. package/dist/voice/useWsRealtimeAudio.js +102 -0
  94. package/dist/voice/voiceMicConstants.d.ts +4 -0
  95. package/dist/voice/voiceMicConstants.d.ts.map +1 -0
  96. package/dist/voice/voiceMicConstants.js +10 -0
  97. package/dist/voice/ws/BrowserWsPcmPlayer.d.ts +23 -0
  98. package/dist/voice/ws/BrowserWsPcmPlayer.d.ts.map +1 -0
  99. package/dist/voice/ws/BrowserWsPcmPlayer.js +137 -0
  100. package/dist/voice/ws/BrowserWsPcmRecorder.d.ts +17 -0
  101. package/dist/voice/ws/BrowserWsPcmRecorder.d.ts.map +1 -0
  102. package/dist/voice/ws/BrowserWsPcmRecorder.js +71 -0
  103. package/dist/voice/ws/float32ToPcm16.d.ts +2 -0
  104. package/dist/voice/ws/float32ToPcm16.d.ts.map +1 -0
  105. package/dist/voice/ws/float32ToPcm16.js +8 -0
  106. package/dist/voice/ws/voiceSilenceConstants.d.ts +5 -0
  107. package/dist/voice/ws/voiceSilenceConstants.d.ts.map +1 -0
  108. package/dist/voice/ws/voiceSilenceConstants.js +4 -0
  109. package/dist/voice/ws/wsRealtimeConstants.d.ts +2 -0
  110. package/dist/voice/ws/wsRealtimeConstants.d.ts.map +1 -0
  111. package/dist/voice/ws/wsRealtimeConstants.js +1 -0
  112. package/package.json +60 -0
  113. package/src/NxtlinqAgentChat.tsx +79 -0
  114. package/src/components/AgentAssistantShell.tsx +104 -0
  115. package/src/components/AgentComposer.tsx +134 -0
  116. package/src/components/AgentMessageList.tsx +78 -0
  117. package/src/components/AgentRemoteAudio.tsx +34 -0
  118. package/src/components/AgentVoiceBar.tsx +173 -0
  119. package/src/components/PresetMessageChips.tsx +41 -0
  120. package/src/context/AgentAssistantContext.tsx +276 -0
  121. package/src/index.ts +78 -0
  122. package/src/legacy/assets/images/adiSideItalicDataUri.ts +1 -0
  123. package/src/legacy/chatbot/ChatBot.tsx +61 -0
  124. package/src/legacy/chatbot/context/ChatBotContext.tsx +3227 -0
  125. package/src/legacy/chatbot/types/ChatBotTypes.ts +195 -0
  126. package/src/legacy/chatbot/ui/BerifyMeModal.tsx +145 -0
  127. package/src/legacy/chatbot/ui/ChatBotUI.tsx +949 -0
  128. package/src/legacy/chatbot/ui/MessageInput.tsx +517 -0
  129. package/src/legacy/chatbot/ui/MessageList.tsx +764 -0
  130. package/src/legacy/chatbot/ui/ModelSelector.tsx +190 -0
  131. package/src/legacy/chatbot/ui/NotificationModal.tsx +110 -0
  132. package/src/legacy/chatbot/ui/PermissionForm.tsx +632 -0
  133. package/src/legacy/chatbot/ui/PresetMessages.tsx +50 -0
  134. package/src/legacy/chatbot/ui/VoiceModePanel.tsx +168 -0
  135. package/src/legacy/chatbot/ui/styles/isolatedStyles.ts +1058 -0
  136. package/src/legacy/index.ts +26 -0
  137. package/src/theme/defaultTheme.ts +22 -0
  138. package/src/types.ts +65 -0
  139. package/src/voice/useVoiceConnectOrchestration.ts +117 -0
  140. package/src/voice/useVoiceMicState.ts +117 -0
  141. package/src/voice/useVoiceTranscriptMessages.ts +173 -0
  142. package/src/voice/voiceMicConstants.ts +13 -0
@@ -0,0 +1,632 @@
1
+ /** @jsxImportSource @emotion/react */
2
+ import * as React from 'react';
3
+ import { css } from '@emotion/react';
4
+ import { useChatBot } from '../context/ChatBotContext';
5
+ import { walletTextUtils } from '@bytexbyte/nxtlinq-ai-agent-web-development';
6
+ import { actionButton, modalOverlay } from './styles/isolatedStyles';
7
+
8
+ interface PermissionFormProps {
9
+ onClose: () => void;
10
+ }
11
+
12
+ export const PermissionForm: React.FC<PermissionFormProps> = ({ onClose }) => {
13
+ const {
14
+ hitAddress,
15
+ permissions,
16
+ setPermissions,
17
+ setIsDisabled,
18
+ onSave,
19
+ onConnectWallet,
20
+ onSignIn,
21
+ isNeedSignInWithWallet,
22
+ walletInfo,
23
+ onVerifyWallet,
24
+ serviceId,
25
+ nxtlinqApi,
26
+ permissionGroup,
27
+ isAITLoading,
28
+ isWalletLoading = false,
29
+ refreshAIT,
30
+ props
31
+ } = useChatBot();
32
+
33
+ const [availablePermissions, setAvailablePermissions] = React.useState<any[]>([]);
34
+ const [isSaving, setIsSaving] = React.useState(false);
35
+ const [tempPermissions, setTempPermissions] = React.useState<string[]>(permissions);
36
+ const [hasUserInteracted, setHasUserInteracted] = React.useState(false);
37
+
38
+ // Check if ALL permission is selected
39
+ const isAllSelected = tempPermissions.includes('ALL');
40
+
41
+ // Update temp permissions when permissions change, but only if user hasn't interacted
42
+ React.useEffect(() => {
43
+ if (!hasUserInteracted) {
44
+ setTempPermissions(permissions);
45
+ }
46
+ }, [permissions, hasUserInteracted]);
47
+
48
+ // When ALL is selected, automatically select all other permissions
49
+ // This handles cases where ALL is set from initial permissions or when availablePermissions loads
50
+ React.useEffect(() => {
51
+ if (isAllSelected && availablePermissions.length > 0) {
52
+ const allPermissionLabels = availablePermissions.map(p => p.label);
53
+ const currentPermissionSet = new Set(tempPermissions);
54
+
55
+ // Check if all permissions are already selected
56
+ const hasAllPermissions = allPermissionLabels.every(label => currentPermissionSet.has(label));
57
+
58
+ if (!hasAllPermissions) {
59
+ // Add all permissions (this will include ALL and all others)
60
+ setTempPermissions([...allPermissionLabels].sort());
61
+ }
62
+ }
63
+ // eslint-disable-next-line react-hooks/exhaustive-deps
64
+ }, [isAllSelected, availablePermissions.length]);
65
+
66
+ const fetchAvailablePermissions = async () => {
67
+ if (!serviceId) return;
68
+
69
+ try {
70
+ const result = await nxtlinqApi.permissions.getServicePermissions({
71
+ serviceId,
72
+ ...(permissionGroup && { groupName: permissionGroup })
73
+ });
74
+ if ('error' in result) {
75
+ console.error('Failed to fetch permissions:', result.error);
76
+ return;
77
+ }
78
+ setAvailablePermissions(result.permissions);
79
+ } catch (error) {
80
+ console.error('Error fetching permissions:', error);
81
+ }
82
+ };
83
+
84
+ React.useEffect(() => {
85
+ fetchAvailablePermissions();
86
+ }, [serviceId, nxtlinqApi, permissionGroup]);
87
+
88
+ // Refresh wallet info when component mounts or when hitAddress changes
89
+ React.useEffect(() => {
90
+ if (hitAddress) {
91
+ // Trigger a refresh of AIT and wallet info when the form opens
92
+ const refreshWalletInfo = async () => {
93
+ try {
94
+ // This will trigger refreshAIT which includes wallet info fetch
95
+ await refreshAIT();
96
+ } catch (error) {
97
+ console.error('Failed to refresh wallet info:', error);
98
+ }
99
+ };
100
+ refreshWalletInfo();
101
+ }
102
+ }, [hitAddress]);
103
+
104
+ // Check if wallet IDV verification is required based on configuration
105
+ const requireWalletIDVVerification = props.requireWalletIDVVerification ?? true; // Default to true
106
+ const isWalletVerified = Boolean(walletInfo?.id);
107
+ const isWalletVerifiedWithBerifyme = walletInfo?.method === 'berifyme';
108
+
109
+ // Show verification prompt if:
110
+ // 1. IDV verification is required AND wallet is not verified, OR
111
+ // 2. IDV verification is required AND wallet is verified but not with Berifyme
112
+ const shouldShowVerificationPrompt = requireWalletIDVVerification && (!isWalletVerified || !isWalletVerifiedWithBerifyme);
113
+
114
+ const handleSave = async () => {
115
+ setIsSaving(true);
116
+ try {
117
+ // Update the actual permissions with temp permissions
118
+ setPermissions(tempPermissions);
119
+ await onSave(tempPermissions);
120
+ setHasUserInteracted(false);
121
+ } finally {
122
+ setIsSaving(false);
123
+ }
124
+ };
125
+
126
+ const handleCancel = () => {
127
+ // Reset temp permissions to original permissions
128
+ setTempPermissions(permissions);
129
+ setHasUserInteracted(false);
130
+ onClose();
131
+ };
132
+
133
+ // Check if permissions have changed
134
+ const hasPermissionChanges = () => {
135
+ if (tempPermissions.length !== permissions.length) return true;
136
+ return tempPermissions.some(p => !permissions.includes(p)) ||
137
+ permissions.some(p => !tempPermissions.includes(p));
138
+ };
139
+
140
+ // Show loading state while checking wallet status
141
+ if (isWalletLoading) {
142
+ return (
143
+ <div css={css`
144
+ background-color: white !important;
145
+ padding: 24px !important;
146
+ border-radius: 12px !important;
147
+ width: 480px !important;
148
+ max-width: 90% !important;
149
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1) !important;
150
+ `}>
151
+ <div css={css`
152
+ display: flex !important;
153
+ justify-content: space-between !important;
154
+ align-items: center !important;
155
+ margin-bottom: 24px !important;
156
+ `}>
157
+ <h3 css={css`
158
+ margin: 0 !important;
159
+ font-size: 20px !important;
160
+ font-weight: 600 !important;
161
+ color: #1a1a1a !important;
162
+ `}>AIT Settings</h3>
163
+ <button
164
+ onClick={onClose}
165
+ css={css`
166
+ background: none !important;
167
+ border: none !important;
168
+ font-size: 24px !important;
169
+ cursor: pointer !important;
170
+ color: #666 !important;
171
+ padding: 4px !important;
172
+ display: flex !important;
173
+ align-items: center !important;
174
+ justify-content: center !important;
175
+
176
+ &:hover {
177
+ background-color: #f0f0f0 !important;
178
+ color: #333 !important;
179
+ }
180
+ `}
181
+ >
182
+ ×
183
+ </button>
184
+ </div>
185
+ <div css={css`
186
+ text-align: center !important;
187
+ padding: 32px 0 !important;
188
+ `}>
189
+ <div css={css`
190
+ width: 64px !important;
191
+ height: 64px !important;
192
+ margin: 0 auto 16px !important;
193
+ background-color: #f5f5f5 !important;
194
+ border-radius: 50% !important;
195
+ display: flex !important;
196
+ align-items: center !important;
197
+ justify-content: center !important;
198
+ `}>
199
+ <div css={css`
200
+ width: 32px !important;
201
+ height: 32px !important;
202
+ border: 3px solid #e3e3e3 !important;
203
+ border-top: 3px solid #007bff !important;
204
+ border-radius: 50% !important;
205
+ animation: spin 1s linear infinite !important;
206
+ `}></div>
207
+ </div>
208
+ <p css={css`
209
+ margin-bottom: 24px !important;
210
+ font-size: 16px !important;
211
+ color: #666 !important;
212
+ `}>{walletTextUtils.getWalletText('Checking wallet status...', serviceId)}</p>
213
+ </div>
214
+ <style>{`
215
+ @keyframes spin {
216
+ 0% { transform: rotate(0deg); }
217
+ 100% { transform: rotate(360deg); }
218
+ }
219
+ `}</style>
220
+ </div>
221
+ );
222
+ }
223
+
224
+ return (
225
+ <div css={css`
226
+ background-color: white !important;
227
+ padding: 24px !important;
228
+ border-radius: 12px !important;
229
+ width: 480px !important;
230
+ max-width: 90% !important;
231
+ max-height: 90vh !important;
232
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1) !important;
233
+ display: flex !important;
234
+ flex-direction: column !important;
235
+ overflow: hidden !important;
236
+
237
+ /* Mobile responsive adjustments */
238
+ @media (max-width: 768px) {
239
+ width: 75vw !important;
240
+ max-width: 75vw !important;
241
+ padding: 20px !important;
242
+ border-radius: 8px !important;
243
+ max-height: 65vh !important;
244
+ }
245
+
246
+ @media (max-width: 480px) {
247
+ width: 70vw !important;
248
+ max-width: 70vw !important;
249
+ padding: 16px !important;
250
+ border-radius: 6px !important;
251
+ max-height: 60vh !important;
252
+ }
253
+ `}>
254
+ <div css={css`
255
+ display: flex !important;
256
+ justify-content: space-between !important;
257
+ align-items: center !important;
258
+ margin-bottom: 24px !important;
259
+ `}>
260
+ <h3 css={css`
261
+ margin: 0 !important;
262
+ font-size: 20px !important;
263
+ font-weight: 600 !important;
264
+ color: #1a1a1a !important;
265
+ `}>AIT Settings</h3>
266
+ <button
267
+ onClick={onClose}
268
+ css={css`
269
+ background: none !important;
270
+ border: none !important;
271
+ font-size: 24px !important;
272
+ cursor: pointer !important;
273
+ color: #666 !important;
274
+ padding: 8px !important;
275
+ display: flex !important;
276
+ align-items: center !important;
277
+ justify-content: center !important;
278
+ border-radius: 4px !important;
279
+ transition: background-color 0.2s !important;
280
+ min-width: 32px !important;
281
+ min-height: 32px !important;
282
+
283
+ &:hover {
284
+ background-color: #f0f0f0 !important;
285
+ color: #333 !important;
286
+ }
287
+ `}
288
+ title="Close"
289
+ >
290
+ ×
291
+ </button>
292
+ </div>
293
+
294
+ {!hitAddress ? (
295
+ <div css={css`
296
+ text-align: center !important;
297
+ padding: 32px 0 !important;
298
+ `}>
299
+ <div css={css`
300
+ width: 64px !important;
301
+ height: 64px !important;
302
+ margin: 0 auto 16px !important;
303
+ background-color: #f5f5f5 !important;
304
+ border-radius: 50% !important;
305
+ display: flex !important;
306
+ align-items: center !important;
307
+ justify-content: center !important;
308
+ `}>
309
+ <span css={css`font-size: 32px !important;`}>👛</span>
310
+ </div>
311
+ <p css={css`
312
+ margin-bottom: 24px !important;
313
+ font-size: 16px !important;
314
+ color: #666 !important;
315
+ `}>{walletTextUtils.getWalletText('Please connect your wallet first', serviceId)}</p>
316
+ <button
317
+ onClick={onConnectWallet}
318
+ disabled={Boolean(hitAddress)}
319
+ css={css`
320
+ ${actionButton}
321
+ padding: 12px 24px !important;
322
+ background-color: ${Boolean(hitAddress) ? '#28a745' : '#007bff'} !important;
323
+ border-radius: 8px !important;
324
+ font-size: 16px !important;
325
+ opacity: ${Boolean(hitAddress) ? 0.8 : 1} !important;
326
+
327
+ &:disabled {
328
+ cursor: not-allowed !important;
329
+ }
330
+
331
+ &:hover:not(:disabled) {
332
+ background-color: #0056b3 !important;
333
+ }
334
+ `}
335
+ >
336
+ {Boolean(hitAddress) ? 'Connected' : walletTextUtils.getWalletText('Connect Wallet', serviceId)}
337
+ </button>
338
+ </div>
339
+ ) : isNeedSignInWithWallet ? (
340
+ <div css={css`
341
+ text-align: center !important;
342
+ padding: 32px 0 !important;
343
+ `}>
344
+ <div css={css`margin-bottom: 24px !important;`}>
345
+ <h4 css={css`
346
+ margin-bottom: 12px !important;
347
+ font-size: 16px !important;
348
+ color: #666 !important;
349
+ `}>{walletTextUtils.getWalletText('Connected Wallet', serviceId)}</h4>
350
+ <p css={css`
351
+ word-break: break-all !important;
352
+ background-color: #f8f9fa !important;
353
+ padding: 12px !important;
354
+ border-radius: 8px !important;
355
+ font-size: 14px !important;
356
+ color: #333 !important;
357
+ border: 1px solid #e9ecef !important;
358
+ `}>
359
+ {hitAddress}
360
+ </p>
361
+ </div>
362
+ <p css={css`
363
+ margin-bottom: 24px !important;
364
+ font-size: 16px !important;
365
+ color: #666 !important;
366
+ `}>Please sign in to continue</p>
367
+ <button
368
+ onClick={onSignIn}
369
+ disabled={!isNeedSignInWithWallet}
370
+ css={css`
371
+ ${actionButton}
372
+ padding: 12px 24px !important;
373
+ background-color: ${!isNeedSignInWithWallet ? '#28a745' : '#007bff'} !important;
374
+ border-radius: 8px !important;
375
+ font-size: 16px !important;
376
+ opacity: ${!isNeedSignInWithWallet ? 0.8 : 1} !important;
377
+
378
+ &:disabled {
379
+ cursor: not-allowed !important;
380
+ }
381
+
382
+ &:hover:not(:disabled) {
383
+ background-color: #0056b3 !important;
384
+ }
385
+ `}
386
+ >
387
+ {!isNeedSignInWithWallet ? 'Signed In' : 'Sign In'}
388
+ </button>
389
+ </div>
390
+ ) : shouldShowVerificationPrompt ? (
391
+ <div css={css`
392
+ text-align: center !important;
393
+ padding: 32px 0 !important;
394
+ `}>
395
+ <div css={css`margin-bottom: 24px !important;`}>
396
+ <h4 css={css`
397
+ margin-bottom: 12px !important;
398
+ font-size: 16px !important;
399
+ color: #666 !important;
400
+ `}>{walletTextUtils.getWalletText('Connected Wallet', serviceId)}</h4>
401
+ <p css={css`
402
+ word-break: break-all !important;
403
+ background-color: #f8f9fa !important;
404
+ padding: 12px !important;
405
+ border-radius: 8px !important;
406
+ font-size: 14px !important;
407
+ color: #333 !important;
408
+ border: 1px solid #e9ecef !important;
409
+ `}>
410
+ {hitAddress}
411
+ </p>
412
+ </div>
413
+ <p css={css`
414
+ margin-bottom: 24px !important;
415
+ font-size: 16px !important;
416
+ color: #666 !important;
417
+ `}>
418
+ {isWalletVerified && !isWalletVerifiedWithBerifyme
419
+ ? walletTextUtils.getWalletText('Your wallet is verified with custom method, but Berify.me verification is required to continue.', serviceId)
420
+ : walletTextUtils.getWalletText('Please verify your wallet with Berify.me to continue', serviceId)
421
+ }
422
+ </p>
423
+ <button
424
+ onClick={() => onVerifyWallet('berifyme')}
425
+ css={css`
426
+ ${actionButton}
427
+ padding: 12px 24px !important;
428
+ background-color: #007bff !important;
429
+ border-radius: 8px !important;
430
+ font-size: 16px !important;
431
+
432
+ &:hover {
433
+ background-color: #0056b3 !important;
434
+ }
435
+ `}
436
+ >
437
+ {walletTextUtils.getWalletText('Verify your wallet', serviceId)}
438
+ </button>
439
+ </div>
440
+ ) : (
441
+ <>
442
+ <div css={css`margin-bottom: 24px !important;`}>
443
+ <h4 css={css`
444
+ margin-bottom: 12px !important;
445
+ font-size: 16px !important;
446
+ color: #666 !important;
447
+ `}>{walletTextUtils.getWalletText('Connected Wallet', serviceId)}</h4>
448
+ <p css={css`
449
+ word-break: break-all !important;
450
+ background-color: #f8f9fa !important;
451
+ padding: 12px !important;
452
+ border-radius: 8px !important;
453
+ font-size: 14px !important;
454
+ color: #333 !important;
455
+ border: 1px solid #e9ecef !important;
456
+ `}>
457
+ {hitAddress}
458
+ </p>
459
+ </div>
460
+ <div css={css`
461
+ margin-bottom: 24px !important;
462
+ flex: 1 !important;
463
+ display: flex !important;
464
+ flex-direction: column !important;
465
+ min-height: 0 !important;
466
+ `}>
467
+ <h4 css={css`
468
+ margin-bottom: 12px !important;
469
+ font-size: 16px !important;
470
+ color: #666 !important;
471
+ flex-shrink: 0 !important;
472
+ `}>Permissions</h4>
473
+ {isAITLoading ? (
474
+ <div css={css`
475
+ background-color: #f8f9fa !important;
476
+ padding: 16px !important;
477
+ border-radius: 8px !important;
478
+ border: 1px solid #e9ecef !important;
479
+ text-align: center !important;
480
+ color: #666 !important;
481
+ `}>
482
+ Loading permissions...
483
+ </div>
484
+ ) : (
485
+ <div css={css`
486
+ background-color: #f8f9fa !important;
487
+ padding: 16px !important;
488
+ border-radius: 8px !important;
489
+ border: 1px solid #e9ecef !important;
490
+ flex: 1 !important;
491
+ overflow-y: auto !important;
492
+ overflow-x: hidden !important;
493
+ min-height: 0 !important;
494
+ `}>
495
+ {availablePermissions.map((permission) => {
496
+ const isAllPermission = permission.label === 'ALL';
497
+ const isOtherPermissionDisabled = isAllSelected && !isAllPermission;
498
+ const isChecked = isAllSelected && !isAllPermission
499
+ ? true
500
+ : tempPermissions.includes(permission.label);
501
+
502
+ return (
503
+ <div key={permission.id} css={css`margin-bottom: 12px !important;`}>
504
+ <label css={css`
505
+ display: flex !important;
506
+ align-items: center !important;
507
+ gap: 12px !important;
508
+ cursor: ${isAITLoading || isOtherPermissionDisabled ? 'not-allowed' : 'pointer'} !important;
509
+ padding: 8px !important;
510
+ border-radius: 6px !important;
511
+ transition: background-color 0.2s !important;
512
+ opacity: ${isAITLoading || isOtherPermissionDisabled ? 0.6 : 1} !important;
513
+
514
+ &:hover {
515
+ background-color: ${!isAITLoading && !isOtherPermissionDisabled ? '#e9ecef' : 'transparent'} !important;
516
+ }
517
+ `}
518
+ >
519
+ <input
520
+ type="checkbox"
521
+ checked={isChecked}
522
+ onChange={() => {
523
+ if (!isAITLoading) {
524
+ if (isAllPermission) {
525
+ // Handle ALL permission toggle
526
+ if (isAllSelected) {
527
+ // Unchecking ALL - keep all other permissions selected
528
+ // Get all permission labels except ALL
529
+ const allOtherPermissions = availablePermissions
530
+ .map(p => p.label)
531
+ .filter(label => label !== 'ALL');
532
+ setTempPermissions(allOtherPermissions.sort());
533
+ } else {
534
+ // Checking ALL - add all permissions
535
+ const allPermissionLabels = availablePermissions.map(p => p.label);
536
+ setTempPermissions(allPermissionLabels.sort());
537
+ }
538
+ } else {
539
+ // Handle other permissions (only if ALL is not selected)
540
+ if (!isAllSelected) {
541
+ const newPermissions = tempPermissions.includes(permission.label)
542
+ ? tempPermissions.filter(p => p !== permission.label)
543
+ : [...tempPermissions, permission.label].sort();
544
+ setTempPermissions(newPermissions);
545
+ }
546
+ }
547
+ setHasUserInteracted(true);
548
+ setIsDisabled(false);
549
+ }
550
+ }}
551
+ disabled={isAITLoading || isOtherPermissionDisabled}
552
+ css={css`
553
+ margin: 0 !important;
554
+ width: 18px !important;
555
+ height: 18px !important;
556
+ cursor: ${isAITLoading || isOtherPermissionDisabled ? 'not-allowed' : 'pointer'} !important;
557
+ `}
558
+ />
559
+ <span css={css`
560
+ font-size: 14px !important;
561
+ color: ${isOtherPermissionDisabled ? '#999' : '#333'} !important;
562
+ `}>{permission.label}</span>
563
+ </label>
564
+ </div>
565
+ );
566
+ })}
567
+ </div>
568
+ )}
569
+ </div>
570
+ <div css={css`
571
+ display: flex !important;
572
+ justify-content: flex-end !important;
573
+ gap: 12px !important;
574
+ border-top: 1px solid #e9ecef !important;
575
+ padding-top: 24px !important;
576
+ flex-shrink: 0 !important;
577
+ margin-top: auto !important;
578
+ `}>
579
+ <button
580
+ onClick={handleCancel}
581
+ css={css`
582
+ padding: 10px 20px !important;
583
+ background-color: #f8f9fa !important;
584
+ color: #666 !important;
585
+ border: 1px solid #dee2e6 !important;
586
+ border-radius: 8px !important;
587
+ cursor: pointer !important;
588
+ font-size: 14px !important;
589
+ font-weight: 500 !important;
590
+ transition: all 0.2s !important;
591
+ margin-top: 0 !important;
592
+
593
+ &:hover {
594
+ background-color: #e9ecef !important;
595
+ border-color: #ced4da !important;
596
+ }
597
+ `}
598
+ >
599
+ Cancel
600
+ </button>
601
+ <button
602
+ onClick={handleSave}
603
+ disabled={!hasPermissionChanges() || isSaving || isAITLoading}
604
+ css={css`
605
+ padding: 10px 20px !important;
606
+ background-color: ${!hasPermissionChanges() || isSaving || isAITLoading ? '#e9ecef' : '#007bff'} !important;
607
+ color: ${!hasPermissionChanges() || isSaving || isAITLoading ? '#6c757d' : 'white'} !important;
608
+ border: none !important;
609
+ border-radius: 8px !important;
610
+ cursor: ${!hasPermissionChanges() || isSaving || isAITLoading ? 'not-allowed' : 'pointer'} !important;
611
+ font-size: 14px !important;
612
+ font-weight: 500 !important;
613
+ transition: all 0.2s !important;
614
+ margin-top: 0 !important;
615
+
616
+ &:disabled {
617
+ cursor: not-allowed !important;
618
+ }
619
+
620
+ &:hover:not(:disabled) {
621
+ background-color: #0056b3 !important;
622
+ }
623
+ `}
624
+ >
625
+ {isSaving ? 'Saving...' : 'Save'}
626
+ </button>
627
+ </div>
628
+ </>
629
+ )}
630
+ </div>
631
+ );
632
+ };
@@ -0,0 +1,50 @@
1
+ /** @jsxImportSource @emotion/react */
2
+ import * as React from 'react';
3
+ import { css } from '@emotion/react';
4
+ import { useChatBot } from '../context/ChatBotContext';
5
+ import { PresetMessage } from '../types/ChatBotTypes';
6
+ import { actionButton } from './styles/isolatedStyles';
7
+
8
+ export const PresetMessages: React.FC = () => {
9
+ const { suggestions, handlePresetMessage } = useChatBot();
10
+
11
+ if (!suggestions || suggestions.length === 0) {
12
+ return null;
13
+ }
14
+
15
+ return (
16
+ <div css={css`
17
+ padding: 10px 15px !important;
18
+ border-top: 1px solid #eee !important;
19
+ overflow-x: auto !important;
20
+ white-space: nowrap !important;
21
+ display: flex !important;
22
+ gap: 10px !important;
23
+ align-items: center !important;
24
+ `}>
25
+ {suggestions.map((preset: PresetMessage, index: number) => (
26
+ <button
27
+ key={index}
28
+ onClick={() => handlePresetMessage(preset)}
29
+ css={css`
30
+ ${actionButton}
31
+ padding: 5px 10px !important;
32
+ font-size: 12px !important;
33
+ white-space: nowrap !important;
34
+ flex-shrink: 0 !important;
35
+
36
+ &:hover {
37
+ background-color: #0056b3 !important;
38
+ }
39
+
40
+ &:active {
41
+ background-color: #004085 !important;
42
+ }
43
+ `}
44
+ >
45
+ {preset.text}
46
+ </button>
47
+ ))}
48
+ </div>
49
+ );
50
+ };