@bytexbyte/nxtlinq-ai-agent-sdk 1.6.29 → 1.6.31
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/dist/components/context/ChatBotContext.d.ts.map +1 -1
- package/dist/components/context/ChatBotContext.js +211 -69
- package/dist/components/types/ChatBotTypes.d.ts +8 -1
- package/dist/components/types/ChatBotTypes.d.ts.map +1 -1
- package/dist/components/ui/ChatBotUI.d.ts.map +1 -1
- package/dist/components/ui/ChatBotUI.js +255 -16
- package/dist/components/ui/MessageList.d.ts.map +1 -1
- package/dist/components/ui/MessageList.js +6 -2
- package/dist/components/ui/styles/isolatedStyles.d.ts +14 -0
- package/dist/components/ui/styles/isolatedStyles.d.ts.map +1 -1
- package/dist/components/ui/styles/isolatedStyles.js +138 -7
- package/dist/core/lib/textToSpeech.js +1 -1
- package/dist/core/lib/useDraggable.d.ts +15 -0
- package/dist/core/lib/useDraggable.d.ts.map +1 -0
- package/dist/core/lib/useDraggable.js +158 -0
- package/dist/core/lib/useResizable.d.ts +16 -0
- package/dist/core/lib/useResizable.d.ts.map +1 -0
- package/dist/core/lib/useResizable.js +180 -0
- package/dist/core/lib/useSpeechToTextFromMic/helper.d.ts.map +1 -1
- package/dist/core/lib/useSpeechToTextFromMic/helper.js +13 -1
- package/dist/core/utils/aitUtils.js +1 -1
- package/dist/core/utils/ethersUtils.d.ts +8 -0
- package/dist/core/utils/ethersUtils.d.ts.map +1 -0
- package/dist/core/utils/ethersUtils.js +19 -0
- package/dist/core/utils/index.d.ts +1 -0
- package/dist/core/utils/index.d.ts.map +1 -1
- package/dist/core/utils/index.js +1 -0
- package/dist/core/utils/walletUtils.d.ts +1 -1
- package/dist/core/utils/walletUtils.d.ts.map +1 -1
- package/dist/core/utils/walletUtils.js +5 -1
- package/dist/types/ait-api.d.ts +6 -0
- package/dist/types/ait-api.d.ts.map +1 -1
- package/package.json +3 -3
- package/umd/nxtlinq-ai-agent.umd.js +212 -92
- package/dist/assets/images/adilasDogHeadTiltDataUri.d.ts +0 -2
- package/dist/assets/images/adilasDogHeadTiltDataUri.d.ts.map +0 -1
- package/dist/assets/images/adilasDogHeadTiltDataUri.js +0 -1
|
@@ -9,7 +9,11 @@ import { MessageInput } from './MessageInput';
|
|
|
9
9
|
import { PresetMessages } from './PresetMessages';
|
|
10
10
|
import { ModelSelector } from './ModelSelector';
|
|
11
11
|
import * as walletTextUtils from '../../core/utils/walletTextUtils';
|
|
12
|
+
import { useResizable } from '../../core/lib/useResizable';
|
|
13
|
+
import { useDraggable } from '../../core/lib/useDraggable';
|
|
14
|
+
import useLocalStorage from '../../core/lib/useLocalStorage';
|
|
12
15
|
import { sdkContainer, floatingButton, chatWindow, chatHeader, headerTitle, headerButton, closeButton, modalOverlay, idvBanner, idvBannerTitle, idvBannerText, idvVerifyButton, idvDismissButton, loadingSpinner, successToast, errorToast, warningToast, infoToast, toastCloseButton } from './styles/isolatedStyles';
|
|
16
|
+
import { resizeHandle } from './styles/isolatedStyles';
|
|
13
17
|
// Toast Notification Component
|
|
14
18
|
const ToastNotification = ({ type, message, onClose, isChatOpen = false }) => {
|
|
15
19
|
const getToastStyles = () => {
|
|
@@ -49,7 +53,20 @@ const ToastNotification = ({ type, message, onClose, isChatOpen = false }) => {
|
|
|
49
53
|
return (_jsxs("div", { css: getToastStyles(), children: [_jsx("span", { css: css `font-size: 18px !important;`, children: getIcon() }), _jsx("span", { css: css `flex: 1 !important;`, children: message }), _jsx("button", { onClick: onClose, css: toastCloseButton, children: "\u00D7" })] }));
|
|
50
54
|
};
|
|
51
55
|
export const ChatBotUI = () => {
|
|
52
|
-
const { isOpen, setIsOpen, showPermissionForm, setShowPermissionForm, notification, setNotification, isAITLoading, hitAddress, walletInfo, onVerifyWallet, serviceId, props } = useChatBot();
|
|
56
|
+
const { isOpen, setIsOpen, showPermissionForm, setShowPermissionForm, notification, setNotification, isAITLoading, hitAddress, walletInfo, onVerifyWallet, serviceId, isNeedSignInWithWallet, props } = useChatBot();
|
|
57
|
+
const positionRef = React.useRef({ x: 0, y: 0 });
|
|
58
|
+
const { dimensions, handleResizeStart, positionAdjustment } = useResizable(positionRef);
|
|
59
|
+
const { position, handleDragStart, isDragging, updatePosition } = useDraggable(dimensions);
|
|
60
|
+
// Update position ref when position changes
|
|
61
|
+
React.useEffect(() => {
|
|
62
|
+
positionRef.current = position;
|
|
63
|
+
}, [position]);
|
|
64
|
+
// Update position when resizing to keep bottom-right corner fixed
|
|
65
|
+
React.useEffect(() => {
|
|
66
|
+
if (positionAdjustment) {
|
|
67
|
+
updatePosition(positionAdjustment);
|
|
68
|
+
}
|
|
69
|
+
}, [positionAdjustment, updatePosition]);
|
|
53
70
|
// IDV suggestion banner state
|
|
54
71
|
const [showIDVSuggestion, setShowIDVSuggestion] = React.useState(true);
|
|
55
72
|
const [dismissUntil, setDismissUntil] = React.useState(null);
|
|
@@ -57,21 +74,21 @@ export const ChatBotUI = () => {
|
|
|
57
74
|
// Check if there's a berifyme token in URL (indicating recent berifyme verification)
|
|
58
75
|
const urlParams = new URLSearchParams(window.location.search);
|
|
59
76
|
const hasBerifymeToken = urlParams.get('token') && urlParams.get('method') === 'berifyme';
|
|
60
|
-
// Check if wallet is verified with berifyme
|
|
61
77
|
const isWalletVerifiedWithBerifyme = walletInfo?.id && walletInfo?.method === 'berifyme';
|
|
62
78
|
// Check if IDV suggestion should be shown
|
|
63
79
|
React.useEffect(() => {
|
|
64
|
-
// Only show suggestion when verification is not required and wallet is not verified with berifyme
|
|
65
80
|
const shouldShowBanner = hitAddress &&
|
|
66
81
|
!props.requireWalletIDVVerification &&
|
|
67
82
|
!hasBerifymeToken &&
|
|
68
|
-
!isWalletVerifiedWithBerifyme
|
|
83
|
+
!isWalletVerifiedWithBerifyme &&
|
|
84
|
+
!isNeedSignInWithWallet;
|
|
69
85
|
if (shouldShowBanner) {
|
|
70
86
|
const timer = setTimeout(() => {
|
|
71
87
|
const shouldShowBannerAfterDelay = hitAddress &&
|
|
72
88
|
!props.requireWalletIDVVerification &&
|
|
73
89
|
!hasBerifymeToken &&
|
|
74
|
-
!isWalletVerifiedWithBerifyme
|
|
90
|
+
!isWalletVerifiedWithBerifyme &&
|
|
91
|
+
!isNeedSignInWithWallet;
|
|
75
92
|
if (shouldShowBannerAfterDelay) {
|
|
76
93
|
const dismissed = localStorage.getItem('idv-suggestion-dismissed');
|
|
77
94
|
if (dismissed) {
|
|
@@ -95,7 +112,7 @@ export const ChatBotUI = () => {
|
|
|
95
112
|
localStorage.removeItem('idv-suggestion-dismissed');
|
|
96
113
|
clearInterval(countdownTimer);
|
|
97
114
|
}
|
|
98
|
-
}, 60000);
|
|
115
|
+
}, 60000);
|
|
99
116
|
return () => clearInterval(countdownTimer);
|
|
100
117
|
}
|
|
101
118
|
else {
|
|
@@ -116,8 +133,7 @@ export const ChatBotUI = () => {
|
|
|
116
133
|
setDismissUntil(null);
|
|
117
134
|
setTimeRemaining('');
|
|
118
135
|
}
|
|
119
|
-
}, 1000);
|
|
120
|
-
// Cleanup timer if component unmounts or dependencies change
|
|
136
|
+
}, 1000);
|
|
121
137
|
return () => clearTimeout(timer);
|
|
122
138
|
}
|
|
123
139
|
else {
|
|
@@ -128,15 +144,13 @@ export const ChatBotUI = () => {
|
|
|
128
144
|
setDismissUntil(null);
|
|
129
145
|
setTimeRemaining('');
|
|
130
146
|
}
|
|
131
|
-
}, [hitAddress, walletInfo]);
|
|
132
|
-
// Handle dismiss IDV suggestion
|
|
147
|
+
}, [hitAddress, walletInfo, isNeedSignInWithWallet, props.requireWalletIDVVerification]);
|
|
133
148
|
const handleDismissIDV = () => {
|
|
134
|
-
const dismissSeconds = props.idvBannerDismissSeconds || 86400;
|
|
135
|
-
const dismissTime = Date.now() + (dismissSeconds * 1000);
|
|
149
|
+
const dismissSeconds = props.idvBannerDismissSeconds || 86400;
|
|
150
|
+
const dismissTime = Date.now() + (dismissSeconds * 1000);
|
|
136
151
|
localStorage.setItem('idv-suggestion-dismissed', dismissTime.toString());
|
|
137
152
|
setShowIDVSuggestion(false);
|
|
138
153
|
setDismissUntil(dismissTime);
|
|
139
|
-
// Show confirmation message
|
|
140
154
|
const hours = Math.floor(dismissSeconds / 3600);
|
|
141
155
|
const minutes = Math.floor((dismissSeconds % 3600) / 60);
|
|
142
156
|
const timeText = hours > 0
|
|
@@ -165,9 +179,35 @@ export const ChatBotUI = () => {
|
|
|
165
179
|
};
|
|
166
180
|
}, []);
|
|
167
181
|
const handleClose = () => {
|
|
182
|
+
// When closing window, update button position to align with window's bottom-right corner
|
|
183
|
+
if (typeof window !== 'undefined') {
|
|
184
|
+
// Window uses left/top, button uses right/bottom
|
|
185
|
+
const windowRight = window.innerWidth - (position.x + dimensions.width);
|
|
186
|
+
const windowBottom = window.innerHeight - (position.y + dimensions.height);
|
|
187
|
+
const newButtonPosition = clampButtonPosition({ right: windowRight, bottom: windowBottom });
|
|
188
|
+
setButtonPosition(newButtonPosition);
|
|
189
|
+
if (hasLoadedButtonPosition.current) {
|
|
190
|
+
setSavedButtonPosition(newButtonPosition);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
168
193
|
setIsOpen(false);
|
|
169
194
|
};
|
|
170
195
|
const handleOpen = () => {
|
|
196
|
+
// Calculate window position based on button position when opening
|
|
197
|
+
// Window's bottom-right corner should align with button's position
|
|
198
|
+
if (typeof window !== 'undefined' && buttonRef.current) {
|
|
199
|
+
const buttonRect = buttonRef.current.getBoundingClientRect();
|
|
200
|
+
// Get button's right and bottom values (distance from viewport edges)
|
|
201
|
+
const buttonRight = window.innerWidth - buttonRect.right;
|
|
202
|
+
const buttonBottom = window.innerHeight - buttonRect.bottom;
|
|
203
|
+
// Window uses left/top, button uses right/bottom
|
|
204
|
+
const windowLeft = window.innerWidth - dimensions.width - buttonRight;
|
|
205
|
+
const windowTop = window.innerHeight - dimensions.height - buttonBottom;
|
|
206
|
+
// Clamp to ensure window stays within viewport (use same margin as button)
|
|
207
|
+
const clampedLeft = Math.max(BUTTON_MARGIN, Math.min(windowLeft, window.innerWidth - dimensions.width - BUTTON_MARGIN));
|
|
208
|
+
const clampedTop = Math.max(BUTTON_MARGIN, Math.min(windowTop, window.innerHeight - dimensions.height - BUTTON_MARGIN));
|
|
209
|
+
updatePosition({ x: clampedLeft, y: clampedTop });
|
|
210
|
+
}
|
|
171
211
|
setIsOpen(true);
|
|
172
212
|
};
|
|
173
213
|
const handleCloseNotification = () => {
|
|
@@ -185,11 +225,210 @@ export const ChatBotUI = () => {
|
|
|
185
225
|
const handleSettingsClick = () => {
|
|
186
226
|
setShowPermissionForm(true);
|
|
187
227
|
};
|
|
228
|
+
// Constants for button positioning
|
|
229
|
+
const BUTTON_MARGIN = 20;
|
|
230
|
+
const BUTTON_MIN_MARGIN = 5;
|
|
231
|
+
const DRAG_THRESHOLD = 5; // Minimum distance in pixels to distinguish drag from click
|
|
232
|
+
// Track window size for responsive button positioning and dragging
|
|
233
|
+
const buttonRef = React.useRef(null);
|
|
234
|
+
const buttonDragState = React.useRef(null);
|
|
235
|
+
const [isButtonDragging, setIsButtonDragging] = React.useState(false);
|
|
236
|
+
const [isButtonDragActive, setIsButtonDragActive] = React.useState(false);
|
|
237
|
+
const hasLoadedButtonPosition = React.useRef(false);
|
|
238
|
+
const buttonDragDistance = React.useRef(0);
|
|
239
|
+
// Track latest button position for saving (to avoid stale closure issues)
|
|
240
|
+
const latestButtonPositionRef = React.useRef({ right: BUTTON_MARGIN, bottom: BUTTON_MARGIN });
|
|
241
|
+
// Load saved position synchronously on initialization to avoid position jump
|
|
242
|
+
const getInitialButtonPosition = () => {
|
|
243
|
+
if (typeof window === 'undefined') {
|
|
244
|
+
return { right: BUTTON_MARGIN, bottom: BUTTON_MARGIN };
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
const saved = localStorage.getItem('ai-agent-button-position');
|
|
248
|
+
if (saved) {
|
|
249
|
+
const parsed = JSON.parse(saved);
|
|
250
|
+
if (parsed && typeof parsed.right === 'number' && typeof parsed.bottom === 'number') {
|
|
251
|
+
return parsed;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
catch (e) {
|
|
256
|
+
// Ignore parse errors, use default
|
|
257
|
+
}
|
|
258
|
+
return { right: BUTTON_MARGIN, bottom: BUTTON_MARGIN };
|
|
259
|
+
};
|
|
260
|
+
const [, setSavedButtonPosition, isButtonPositionInitialized] = useLocalStorage('ai-agent-button-position', null);
|
|
261
|
+
const [buttonPosition, setButtonPosition] = React.useState(getInitialButtonPosition);
|
|
262
|
+
// Keep ref in sync with button position state and mark as loaded when initialized
|
|
263
|
+
React.useEffect(() => {
|
|
264
|
+
latestButtonPositionRef.current = buttonPosition;
|
|
265
|
+
if (isButtonPositionInitialized && !hasLoadedButtonPosition.current) {
|
|
266
|
+
hasLoadedButtonPosition.current = true;
|
|
267
|
+
}
|
|
268
|
+
}, [buttonPosition, isButtonPositionInitialized]);
|
|
269
|
+
// Fast clamp calculation helper (used in both drag and resize)
|
|
270
|
+
const clampButtonPositionFast = React.useCallback((right, bottom, buttonWidth, buttonHeight) => {
|
|
271
|
+
const viewportWidth = window.innerWidth;
|
|
272
|
+
const viewportHeight = window.innerHeight;
|
|
273
|
+
// Clamp horizontally
|
|
274
|
+
const maxRight = viewportWidth - buttonWidth - BUTTON_MARGIN;
|
|
275
|
+
let clampedRight = right;
|
|
276
|
+
if (clampedRight > maxRight) {
|
|
277
|
+
clampedRight = Math.max(BUTTON_MIN_MARGIN, maxRight);
|
|
278
|
+
}
|
|
279
|
+
else if (clampedRight < BUTTON_MARGIN) {
|
|
280
|
+
clampedRight = BUTTON_MARGIN;
|
|
281
|
+
}
|
|
282
|
+
// Clamp vertically
|
|
283
|
+
const maxBottom = viewportHeight - buttonHeight - BUTTON_MARGIN;
|
|
284
|
+
let clampedBottom = bottom;
|
|
285
|
+
if (clampedBottom > maxBottom) {
|
|
286
|
+
clampedBottom = Math.max(BUTTON_MIN_MARGIN, maxBottom);
|
|
287
|
+
}
|
|
288
|
+
else if (clampedBottom < BUTTON_MARGIN) {
|
|
289
|
+
clampedBottom = BUTTON_MARGIN;
|
|
290
|
+
}
|
|
291
|
+
return { right: clampedRight, bottom: clampedBottom };
|
|
292
|
+
}, []);
|
|
293
|
+
// Clamp button position to keep it within viewport
|
|
294
|
+
const clampButtonPosition = React.useCallback((pos, buttonWidth, buttonHeight) => {
|
|
295
|
+
if (typeof window === 'undefined') {
|
|
296
|
+
return pos;
|
|
297
|
+
}
|
|
298
|
+
// Use provided dimensions or get from DOM (avoid getBoundingClientRect during drag)
|
|
299
|
+
let width = buttonWidth;
|
|
300
|
+
let height = buttonHeight;
|
|
301
|
+
if (width === undefined || height === undefined) {
|
|
302
|
+
if (!buttonRef.current) {
|
|
303
|
+
return pos;
|
|
304
|
+
}
|
|
305
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
306
|
+
width = rect.width;
|
|
307
|
+
height = rect.height;
|
|
308
|
+
}
|
|
309
|
+
return clampButtonPositionFast(pos.right, pos.bottom, width, height);
|
|
310
|
+
}, [clampButtonPositionFast]);
|
|
311
|
+
const handleButtonDragStart = React.useCallback((event) => {
|
|
312
|
+
// Don't prevent default to allow normal button behavior if it's just a click
|
|
313
|
+
event.stopPropagation();
|
|
314
|
+
if (buttonRef.current) {
|
|
315
|
+
// Cache button dimensions to avoid getBoundingClientRect during drag
|
|
316
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
317
|
+
buttonDragState.current = {
|
|
318
|
+
startX: event.clientX,
|
|
319
|
+
startY: event.clientY,
|
|
320
|
+
startRight: buttonPosition.right,
|
|
321
|
+
startBottom: buttonPosition.bottom,
|
|
322
|
+
buttonWidth: rect.width,
|
|
323
|
+
buttonHeight: rect.height
|
|
324
|
+
};
|
|
325
|
+
buttonDragDistance.current = 0;
|
|
326
|
+
setIsButtonDragging(false);
|
|
327
|
+
setIsButtonDragActive(true);
|
|
328
|
+
document.body.style.userSelect = 'none';
|
|
329
|
+
}
|
|
330
|
+
}, [buttonPosition]);
|
|
331
|
+
// Handle button drag move and end
|
|
332
|
+
React.useEffect(() => {
|
|
333
|
+
// Only set up listeners when drag is active
|
|
334
|
+
if (!isButtonDragActive) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
const handlePointerMove = (event) => {
|
|
338
|
+
if (!buttonDragState.current)
|
|
339
|
+
return;
|
|
340
|
+
const deltaX = event.clientX - buttonDragState.current.startX;
|
|
341
|
+
const deltaY = event.clientY - buttonDragState.current.startY;
|
|
342
|
+
const dragDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
343
|
+
buttonDragDistance.current = dragDistance;
|
|
344
|
+
// Only start dragging if moved more than threshold (to distinguish from click)
|
|
345
|
+
if (dragDistance > DRAG_THRESHOLD && !isButtonDragging) {
|
|
346
|
+
setIsButtonDragging(true);
|
|
347
|
+
document.body.style.cursor = 'grabbing';
|
|
348
|
+
}
|
|
349
|
+
if (dragDistance > DRAG_THRESHOLD) {
|
|
350
|
+
// Calculate new position (right decreases when moving right, bottom decreases when moving down)
|
|
351
|
+
const newRight = buttonDragState.current.startRight - deltaX;
|
|
352
|
+
const newBottom = buttonDragState.current.startBottom - deltaY;
|
|
353
|
+
// Use fast clamp calculation with cached dimensions
|
|
354
|
+
const clampedPos = clampButtonPositionFast(newRight, newBottom, buttonDragState.current.buttonWidth, buttonDragState.current.buttonHeight);
|
|
355
|
+
latestButtonPositionRef.current = clampedPos;
|
|
356
|
+
// Update state immediately (same as window drag) for responsive dragging
|
|
357
|
+
setButtonPosition(clampedPos);
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
const handlePointerUp = () => {
|
|
361
|
+
const wasDragging = buttonDragDistance.current > DRAG_THRESHOLD;
|
|
362
|
+
// Save position to localStorage if we were dragging
|
|
363
|
+
if (wasDragging && hasLoadedButtonPosition.current) {
|
|
364
|
+
setSavedButtonPosition(latestButtonPositionRef.current);
|
|
365
|
+
}
|
|
366
|
+
setIsButtonDragging(false);
|
|
367
|
+
setIsButtonDragActive(false);
|
|
368
|
+
buttonDragDistance.current = 0;
|
|
369
|
+
document.body.style.userSelect = '';
|
|
370
|
+
document.body.style.cursor = '';
|
|
371
|
+
buttonDragState.current = null;
|
|
372
|
+
};
|
|
373
|
+
document.addEventListener('pointermove', handlePointerMove);
|
|
374
|
+
document.addEventListener('pointerup', handlePointerUp);
|
|
375
|
+
return () => {
|
|
376
|
+
document.removeEventListener('pointermove', handlePointerMove);
|
|
377
|
+
document.removeEventListener('pointerup', handlePointerUp);
|
|
378
|
+
document.body.style.userSelect = '';
|
|
379
|
+
document.body.style.cursor = '';
|
|
380
|
+
};
|
|
381
|
+
}, [isButtonDragActive, isButtonDragging, setSavedButtonPosition, clampButtonPositionFast]);
|
|
382
|
+
// Update button position on window resize to ensure it stays within viewport
|
|
383
|
+
React.useEffect(() => {
|
|
384
|
+
if (typeof window === 'undefined')
|
|
385
|
+
return;
|
|
386
|
+
const handleResize = () => {
|
|
387
|
+
// Use requestAnimationFrame to ensure DOM is updated
|
|
388
|
+
requestAnimationFrame(() => {
|
|
389
|
+
const clampedPos = clampButtonPosition(buttonPosition);
|
|
390
|
+
if (clampedPos.right !== buttonPosition.right || clampedPos.bottom !== buttonPosition.bottom) {
|
|
391
|
+
setButtonPosition(clampedPos);
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
};
|
|
395
|
+
window.addEventListener('resize', handleResize);
|
|
396
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
397
|
+
}, [buttonPosition, clampButtonPosition]);
|
|
398
|
+
// Calculate responsive button style - ensure it overrides base styles
|
|
399
|
+
const getButtonStyle = React.useMemo(() => {
|
|
400
|
+
return css `
|
|
401
|
+
position: fixed !important;
|
|
402
|
+
bottom: ${buttonPosition.bottom}px !important;
|
|
403
|
+
right: ${buttonPosition.right}px !important;
|
|
404
|
+
`;
|
|
405
|
+
}, [buttonPosition]);
|
|
188
406
|
// Show floating button when chat is closed
|
|
189
407
|
if (!isOpen) {
|
|
190
|
-
return (_jsxs("div", { css: sdkContainer, children: [_jsx("button", {
|
|
408
|
+
return (_jsxs("div", { css: sdkContainer, children: [_jsx("button", { ref: buttonRef, onClick: (e) => {
|
|
409
|
+
// Don't open if we just finished dragging (moved more than threshold)
|
|
410
|
+
if (buttonDragDistance.current > DRAG_THRESHOLD) {
|
|
411
|
+
e.preventDefault();
|
|
412
|
+
e.stopPropagation();
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
handleOpen();
|
|
416
|
+
}, onPointerDown: handleButtonDragStart, css: [floatingButton, getButtonStyle, css `
|
|
417
|
+
cursor: ${isButtonDragging ? 'grabbing' : 'grab'} !important;
|
|
418
|
+
user-select: none !important;
|
|
419
|
+
`], title: "Drag to move or click to open AI Agent Chat", children: "AI Agent" }), notification.show && (_jsx(ToastNotification, { type: notification.type, message: notification.message, onClose: handleCloseNotification, isChatOpen: isOpen }))] }));
|
|
191
420
|
}
|
|
192
|
-
return (_jsxs("div", { css: sdkContainer, children: [_jsxs("div", { css: chatWindow,
|
|
421
|
+
return (_jsxs("div", { css: sdkContainer, children: [_jsxs("div", { css: [chatWindow, css `
|
|
422
|
+
width: ${dimensions.width}px !important;
|
|
423
|
+
height: ${dimensions.height}px !important;
|
|
424
|
+
left: ${position.x}px !important;
|
|
425
|
+
top: ${position.y}px !important;
|
|
426
|
+
bottom: auto !important;
|
|
427
|
+
right: auto !important;
|
|
428
|
+
`], children: [_jsx("div", { css: resizeHandle, onPointerDown: handleResizeStart, title: "Resize", "aria-label": "Resize chat window" }), _jsxs("div", { css: [chatHeader, css `
|
|
429
|
+
cursor: ${isDragging ? 'grabbing' : 'grab'} !important;
|
|
430
|
+
user-select: none !important;
|
|
431
|
+
`], onPointerDown: handleDragStart, title: "Drag to move", children: [_jsxs("div", { css: css `
|
|
193
432
|
display: flex !important;
|
|
194
433
|
align-items: center !important;
|
|
195
434
|
gap: 10px !important;
|
|
@@ -203,7 +442,7 @@ export const ChatBotUI = () => {
|
|
|
203
442
|
display: flex !important;
|
|
204
443
|
align-items: center !important;
|
|
205
444
|
gap: 10px !important;
|
|
206
|
-
`, children: [_jsx("button", { onClick: handleSettingsClick, css: headerButton, title: "AIT Settings", children: "\u2699\uFE0F" }), _jsx("button", { onClick: handleClose, css: closeButton, children: "\
|
|
445
|
+
`, children: [_jsx("button", { onClick: handleSettingsClick, css: headerButton, title: "AIT Settings", onPointerDown: (e) => e.stopPropagation(), children: "\u2699\uFE0F" }), _jsx("button", { onClick: handleClose, css: closeButton, onPointerDown: (e) => e.stopPropagation(), title: "Minimize", children: "\u2212" })] })] }), showIDVSuggestion && hitAddress && !props.requireWalletIDVVerification && !hasBerifymeToken && !isWalletVerifiedWithBerifyme && (_jsxs("div", { "data-idv-banner": true, css: idvBanner, children: [_jsx("div", { css: css `
|
|
207
446
|
font-size: 20px !important;
|
|
208
447
|
color: #f39c12 !important;
|
|
209
448
|
`, children: "\uD83D\uDCA1" }), _jsxs("div", { css: css `flex: 1 !important;`, children: [_jsx("h5", { css: idvBannerTitle, children: walletTextUtils.getWalletText('Recommended: Verify Your Wallet', serviceId) }), _jsx("p", { css: idvBannerText, children: walletTextUtils.getWalletText('While not required, verifying your wallet with Berify.me provides additional security and trust for your AI agent interactions.', serviceId) }), _jsx("button", { onClick: () => onVerifyWallet('berifyme'), css: idvVerifyButton, children: walletTextUtils.getWalletText('Verify Wallet', serviceId) })] }), _jsx("button", { onClick: handleDismissIDV, css: idvDismissButton, title: `Hide for ${Math.floor((props.idvBannerDismissSeconds || 86400) / 3600)} hours`, children: "\u00D7" })] })), !showIDVSuggestion && dismissUntil && timeRemaining && (_jsxs("div", { css: css `
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/ui/MessageList.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/ui/MessageList.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAkC/B,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAsO/B,CAAC"}
|
|
@@ -5,7 +5,7 @@ import { css } from '@emotion/react';
|
|
|
5
5
|
import { convertUrlsToLinks } from '../../core/utils/urlUtils';
|
|
6
6
|
import * as walletTextUtils from '../../core/utils/walletTextUtils';
|
|
7
7
|
import { useChatBot } from '../context/ChatBotContext';
|
|
8
|
-
import { messageListContainer, messageBubble, userMessage, messageContent, userMessageContent, retryMessageContent, chatbotButton, connectedButton, loadingIndicator, modelIndicator, modelBadge, modelDot } from './styles/isolatedStyles';
|
|
8
|
+
import { messageListContainer, messageBubble, userMessage, messageContent, userMessageContent, retryMessageContent, chatbotButton, connectedButton, loadingIndicator, modelIndicator, modelBadge, modelDot, streamingCaret, streamingContainer, streamingHeader, streamingIcon, streamingToolName, streamingProgressPercent, streamingProgressContainer, streamingProgressBar, streamingPartialText, streamingStatus, streamingStepsContainer, streamingStepItem, streamingStepCheck } from './styles/isolatedStyles';
|
|
9
9
|
export const MessageList = () => {
|
|
10
10
|
const { messages, isLoading, isTtsProcessing, requiresGesture, retryTtsWithGesture, connectWallet, signInWallet, hitAddress, isAutoConnecting, isNeedSignInWithWallet, enableAIT, isAITLoading, isAITEnabling, sendMessage, permissions, availableModels, serviceId } = useChatBot();
|
|
11
11
|
const messagesEndRef = React.useRef(null);
|
|
@@ -16,6 +16,10 @@ export const MessageList = () => {
|
|
|
16
16
|
scrollToBottom();
|
|
17
17
|
}, [messages]);
|
|
18
18
|
const handleButtonClick = async (buttonType, message) => {
|
|
19
|
+
// Prevent sending messages while AI Agent is processing
|
|
20
|
+
if (isLoading) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
19
23
|
if (buttonType === 'connectWallet') {
|
|
20
24
|
connectWallet(true);
|
|
21
25
|
}
|
|
@@ -62,7 +66,7 @@ export const MessageList = () => {
|
|
|
62
66
|
? userMessageContent
|
|
63
67
|
: message.metadata?.isRetry
|
|
64
68
|
? retryMessageContent
|
|
65
|
-
: messageContent, children: [message.metadata?.isRetry && (_jsx("span", { css: css `margin-right: 8px !important; font-size: 14px !important;`, children: "\uD83D\uDD04" })), message.role === 'assistant' ? convertUrlsToLinks(message.content) : message.content, message.button && (_jsx("div", { css: css `margin-top: 10px !important;`, children: _jsx("button", { onClick: () => {
|
|
69
|
+
: messageContent, children: [message.metadata?.isRetry && (_jsx("span", { css: css `margin-right: 8px !important; font-size: 14px !important;`, children: "\uD83D\uDD04" })), message.isStreaming && message.partialContent && (_jsxs("div", { css: streamingPartialText, children: [message.role === 'assistant' ? convertUrlsToLinks(message.partialContent) : message.partialContent, _jsx("span", { css: streamingCaret, children: "\u258A" })] })), message.isStreaming && !message.partialContent && message.role === 'assistant' && (_jsxs("div", { css: streamingContainer, children: [_jsxs("div", { css: streamingHeader, children: [_jsx("span", { css: streamingIcon, children: "\uD83D\uDD27" }), _jsx("span", { css: streamingToolName, children: message.streamingToolName || 'Processing' }), message.streamingProgress !== undefined && (_jsxs("span", { css: streamingProgressPercent, children: [message.streamingProgress, "%"] }))] }), message.streamingProgress !== undefined && (_jsx("div", { css: streamingProgressContainer, children: _jsx("div", { css: [streamingProgressBar, css `width: ${message.streamingProgress}% !important;`] }) })), message.streamingStatus && (_jsx("div", { css: streamingStatus, children: message.streamingStatus })), message.streamingSteps && message.streamingSteps.length > 0 && (_jsx("div", { css: streamingStepsContainer, children: message.streamingSteps.map((step, idx) => (_jsxs("div", { css: streamingStepItem, children: [_jsx("span", { css: streamingStepCheck, children: "\u2713" }), _jsx("span", { children: step })] }, idx))) }))] })), !message.isStreaming && (message.role === 'assistant' ? convertUrlsToLinks(message.content) : message.content), message.button && (_jsx("div", { css: css `margin-top: 10px !important;`, children: _jsx("button", { onClick: () => {
|
|
66
70
|
if (message.button && message.button.trim()) {
|
|
67
71
|
handleButtonClick(message.button, message);
|
|
68
72
|
}
|
|
@@ -2,6 +2,7 @@ export declare const sdkReset: import("@emotion/utils").SerializedStyles;
|
|
|
2
2
|
export declare const sdkContainer: import("@emotion/utils").SerializedStyles;
|
|
3
3
|
export declare const floatingButton: import("@emotion/utils").SerializedStyles;
|
|
4
4
|
export declare const chatWindow: import("@emotion/utils").SerializedStyles;
|
|
5
|
+
export declare const resizeHandle: import("@emotion/utils").SerializedStyles;
|
|
5
6
|
export declare const chatHeader: import("@emotion/utils").SerializedStyles;
|
|
6
7
|
export declare const headerTitle: import("@emotion/utils").SerializedStyles;
|
|
7
8
|
export declare const headerButton: import("@emotion/utils").SerializedStyles;
|
|
@@ -32,4 +33,17 @@ export declare const idvBannerText: import("@emotion/utils").SerializedStyles;
|
|
|
32
33
|
export declare const idvVerifyButton: import("@emotion/utils").SerializedStyles;
|
|
33
34
|
export declare const idvDismissButton: import("@emotion/utils").SerializedStyles;
|
|
34
35
|
export declare const loadingSpinner: import("@emotion/utils").SerializedStyles;
|
|
36
|
+
export declare const streamingPartialText: import("@emotion/utils").SerializedStyles;
|
|
37
|
+
export declare const streamingContainer: import("@emotion/utils").SerializedStyles;
|
|
38
|
+
export declare const streamingHeader: import("@emotion/utils").SerializedStyles;
|
|
39
|
+
export declare const streamingIcon: import("@emotion/utils").SerializedStyles;
|
|
40
|
+
export declare const streamingToolName: import("@emotion/utils").SerializedStyles;
|
|
41
|
+
export declare const streamingProgressPercent: import("@emotion/utils").SerializedStyles;
|
|
42
|
+
export declare const streamingProgressContainer: import("@emotion/utils").SerializedStyles;
|
|
43
|
+
export declare const streamingProgressBar: import("@emotion/utils").SerializedStyles;
|
|
44
|
+
export declare const streamingStatus: import("@emotion/utils").SerializedStyles;
|
|
45
|
+
export declare const streamingCaret: import("@emotion/utils").SerializedStyles;
|
|
46
|
+
export declare const streamingStepsContainer: import("@emotion/utils").SerializedStyles;
|
|
47
|
+
export declare const streamingStepItem: import("@emotion/utils").SerializedStyles;
|
|
48
|
+
export declare const streamingStepCheck: import("@emotion/utils").SerializedStyles;
|
|
35
49
|
//# sourceMappingURL=isolatedStyles.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isolatedStyles.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/styles/isolatedStyles.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,QAAQ,2CAwBpB,CAAC;AAGF,eAAO,MAAM,YAAY,2CAmExB,CAAC;AAGF,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"isolatedStyles.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/styles/isolatedStyles.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,QAAQ,2CAwBpB,CAAC;AAGF,eAAO,MAAM,YAAY,2CAmExB,CAAC;AAGF,eAAO,MAAM,cAAc,2CAmD1B,CAAC;AAGF,eAAO,MAAM,UAAU,2CAuCtB,CAAC;AAGF,eAAO,MAAM,YAAY,2CAcxB,CAAC;AAGF,eAAO,MAAM,UAAU,2CAStB,CAAC;AAGF,eAAO,MAAM,WAAW,2CAMvB,CAAC;AAGF,eAAO,MAAM,YAAY,2CA0BxB,CAAC;AAGF,eAAO,MAAM,WAAW,2CAoBvB,CAAC;AAGF,eAAO,MAAM,oBAAoB,2CAQhC,CAAC;AAGF,eAAO,MAAM,aAAa,2CAKzB,CAAC;AAGF,eAAO,MAAM,WAAW,2CAKvB,CAAC;AAGF,eAAO,MAAM,cAAc,2CAQ1B,CAAC;AAGF,eAAO,MAAM,kBAAkB,2CAQ9B,CAAC;AAGF,eAAO,MAAM,mBAAmB,2CAS/B,CAAC;AAGF,eAAO,MAAM,aAAa,2CAezB,CAAC;AAGF,eAAO,MAAM,YAAY,2CAexB,CAAC;AAGF,eAAO,MAAM,eAAe,2CAc3B,CAAC;AAGF,eAAO,MAAM,gBAAgB,2CAQ5B,CAAC;AAGF,eAAO,MAAM,cAAc,2CAM1B,CAAC;AAGF,eAAO,MAAM,UAAU,2CAYtB,CAAC;AAGF,eAAO,MAAM,QAAQ,2CAMpB,CAAC;AAGF,eAAO,MAAM,iBAAiB,2CAc7B,CAAC;AAGF,eAAO,MAAM,YAAY,2CAIxB,CAAC;AAGF,eAAO,MAAM,UAAU,2CAItB,CAAC;AAGF,eAAO,MAAM,YAAY,2CAIxB,CAAC;AAGF,eAAO,MAAM,SAAS,2CAIrB,CAAC;AAGF,eAAO,MAAM,gBAAgB,2CAiB5B,CAAC;AAGF,eAAO,MAAM,YAAY,2CAyBxB,CAAC;AAGF,eAAO,MAAM,SAAS,2CAWrB,CAAC;AAGF,eAAO,MAAM,cAAc,2CAM1B,CAAC;AAGF,eAAO,MAAM,aAAa,2CAMzB,CAAC;AAGF,eAAO,MAAM,eAAe,2CAoB3B,CAAC;AAGF,eAAO,MAAM,gBAAgB,2CAmB5B,CAAC;AAGF,eAAO,MAAM,cAAc,2CAO1B,CAAC;AAGF,eAAO,MAAM,oBAAoB,2CAIhC,CAAC;AAGF,eAAO,MAAM,kBAAkB,2CAO9B,CAAC;AAGF,eAAO,MAAM,eAAe,2CAM3B,CAAC;AAGF,eAAO,MAAM,aAAa,2CAczB,CAAC;AAGF,eAAO,MAAM,iBAAiB,2CAK7B,CAAC;AAGF,eAAO,MAAM,wBAAwB,2CAMpC,CAAC;AAGF,eAAO,MAAM,0BAA0B,2CAOtC,CAAC;AAGF,eAAO,MAAM,oBAAoB,2CAIhC,CAAC;AAGF,eAAO,MAAM,eAAe,2CAK3B,CAAC;AAGF,eAAO,MAAM,cAAc,2CAY1B,CAAC;AAGF,eAAO,MAAM,uBAAuB,2CAInC,CAAC;AAGF,eAAO,MAAM,iBAAiB,2CAO7B,CAAC;AAGF,eAAO,MAAM,kBAAkB,2CAE9B,CAAC"}
|
|
@@ -97,8 +97,6 @@ export const sdkContainer = css `
|
|
|
97
97
|
// Floating button styles
|
|
98
98
|
export const floatingButton = css `
|
|
99
99
|
position: fixed !important;
|
|
100
|
-
bottom: 20px !important;
|
|
101
|
-
right: 20px !important;
|
|
102
100
|
background-color: #007bff !important;
|
|
103
101
|
color: white !important;
|
|
104
102
|
border: none !important;
|
|
@@ -112,6 +110,7 @@ export const floatingButton = css `
|
|
|
112
110
|
font-weight: 500 !important;
|
|
113
111
|
font-family: inherit !important;
|
|
114
112
|
max-width: calc(100vw - 40px) !important;
|
|
113
|
+
white-space: nowrap !important;
|
|
115
114
|
|
|
116
115
|
&:disabled {
|
|
117
116
|
cursor: not-allowed !important;
|
|
@@ -123,23 +122,30 @@ export const floatingButton = css `
|
|
|
123
122
|
transform: translateY(-2px) !important;
|
|
124
123
|
}
|
|
125
124
|
|
|
126
|
-
/*
|
|
125
|
+
/* Responsive adjustments for small windows */
|
|
127
126
|
@media (max-width: 768px) {
|
|
128
|
-
bottom: 15px !important;
|
|
129
|
-
right: 15px !important;
|
|
130
127
|
max-width: calc(100vw - 30px) !important;
|
|
131
128
|
padding: 8px 16px !important;
|
|
132
129
|
font-size: 13px !important;
|
|
133
130
|
}
|
|
134
131
|
|
|
135
132
|
@media (max-width: 480px) {
|
|
136
|
-
bottom: 10px !important;
|
|
137
|
-
right: 10px !important;
|
|
138
133
|
max-width: calc(100vw - 20px) !important;
|
|
139
134
|
padding: 6px 12px !important;
|
|
140
135
|
font-size: 12px !important;
|
|
141
136
|
border-radius: 16px !important;
|
|
142
137
|
}
|
|
138
|
+
|
|
139
|
+
/* Ensure button is visible when viewport is very small */
|
|
140
|
+
@media (max-height: 200px) {
|
|
141
|
+
padding: 4px 8px !important;
|
|
142
|
+
font-size: 11px !important;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@media (max-width: 200px) {
|
|
146
|
+
padding: 4px 8px !important;
|
|
147
|
+
font-size: 11px !important;
|
|
148
|
+
}
|
|
143
149
|
`;
|
|
144
150
|
// Chat window container styles
|
|
145
151
|
export const chatWindow = css `
|
|
@@ -182,6 +188,22 @@ export const chatWindow = css `
|
|
|
182
188
|
border-radius: 6px !important;
|
|
183
189
|
}
|
|
184
190
|
`;
|
|
191
|
+
// Resize handle for chat window (top-left, invisible until hover)
|
|
192
|
+
export const resizeHandle = css `
|
|
193
|
+
position: absolute !important;
|
|
194
|
+
top: 6px !important;
|
|
195
|
+
left: 6px !important;
|
|
196
|
+
width: 18px !important;
|
|
197
|
+
height: 18px !important;
|
|
198
|
+
border-radius: 4px !important;
|
|
199
|
+
background: transparent !important;
|
|
200
|
+
border: none !important;
|
|
201
|
+
box-shadow: none !important;
|
|
202
|
+
cursor: nwse-resize !important;
|
|
203
|
+
z-index: 10 !important;
|
|
204
|
+
display: grid !important;
|
|
205
|
+
place-items: center !important;
|
|
206
|
+
`;
|
|
185
207
|
// Header styles
|
|
186
208
|
export const chatHeader = css `
|
|
187
209
|
padding: 15px !important;
|
|
@@ -563,3 +585,112 @@ export const loadingSpinner = css `
|
|
|
563
585
|
border-radius: 50% !important;
|
|
564
586
|
animation: spin 1s linear infinite !important;
|
|
565
587
|
`;
|
|
588
|
+
// Streaming partial text block (token-level)
|
|
589
|
+
export const streamingPartialText = css `
|
|
590
|
+
color: #333 !important;
|
|
591
|
+
white-space: pre-wrap !important;
|
|
592
|
+
word-break: break-word !important;
|
|
593
|
+
`;
|
|
594
|
+
// Streaming indicator container styles
|
|
595
|
+
export const streamingContainer = css `
|
|
596
|
+
margin-bottom: 12px !important;
|
|
597
|
+
padding: 12px !important;
|
|
598
|
+
background: linear-gradient(135deg, #f5f7fa 0%, #e8eef5 100%) !important;
|
|
599
|
+
border-radius: 8px !important;
|
|
600
|
+
border-left: 3px solid #667eea !important;
|
|
601
|
+
font-family: inherit !important;
|
|
602
|
+
`;
|
|
603
|
+
// Streaming header styles
|
|
604
|
+
export const streamingHeader = css `
|
|
605
|
+
display: flex !important;
|
|
606
|
+
align-items: center !important;
|
|
607
|
+
gap: 8px !important;
|
|
608
|
+
margin-bottom: 8px !important;
|
|
609
|
+
font-family: inherit !important;
|
|
610
|
+
`;
|
|
611
|
+
// Streaming icon styles
|
|
612
|
+
export const streamingIcon = css `
|
|
613
|
+
font-size: 16px !important;
|
|
614
|
+
animation: pulse 1.5s ease-in-out infinite !important;
|
|
615
|
+
|
|
616
|
+
@keyframes pulse {
|
|
617
|
+
0%, 100% {
|
|
618
|
+
opacity: 1 !important;
|
|
619
|
+
transform: scale(1) !important;
|
|
620
|
+
}
|
|
621
|
+
50% {
|
|
622
|
+
opacity: 0.6 !important;
|
|
623
|
+
transform: scale(1.1) !important;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
`;
|
|
627
|
+
// Streaming tool name styles
|
|
628
|
+
export const streamingToolName = css `
|
|
629
|
+
font-weight: 600 !important;
|
|
630
|
+
color: #667eea !important;
|
|
631
|
+
font-size: 14px !important;
|
|
632
|
+
font-family: inherit !important;
|
|
633
|
+
`;
|
|
634
|
+
// Streaming progress percentage styles
|
|
635
|
+
export const streamingProgressPercent = css `
|
|
636
|
+
margin-left: auto !important;
|
|
637
|
+
color: #888 !important;
|
|
638
|
+
font-size: 12px !important;
|
|
639
|
+
font-weight: 600 !important;
|
|
640
|
+
font-family: inherit !important;
|
|
641
|
+
`;
|
|
642
|
+
// Streaming progress bar container styles
|
|
643
|
+
export const streamingProgressContainer = css `
|
|
644
|
+
width: 100% !important;
|
|
645
|
+
height: 4px !important;
|
|
646
|
+
background: rgba(102, 126, 234, 0.1) !important;
|
|
647
|
+
border-radius: 2px !important;
|
|
648
|
+
overflow: hidden !important;
|
|
649
|
+
margin-bottom: 8px !important;
|
|
650
|
+
`;
|
|
651
|
+
// Streaming progress bar fill styles
|
|
652
|
+
export const streamingProgressBar = css `
|
|
653
|
+
height: 100% !important;
|
|
654
|
+
background: linear-gradient(90deg, #667eea, #764ba2) !important;
|
|
655
|
+
transition: width 0.3s ease !important;
|
|
656
|
+
`;
|
|
657
|
+
// Streaming status message styles
|
|
658
|
+
export const streamingStatus = css `
|
|
659
|
+
font-size: 13px !important;
|
|
660
|
+
color: #555 !important;
|
|
661
|
+
font-style: italic !important;
|
|
662
|
+
font-family: inherit !important;
|
|
663
|
+
`;
|
|
664
|
+
// Streaming caret (blinking)
|
|
665
|
+
export const streamingCaret = css `
|
|
666
|
+
margin-left: 2px !important;
|
|
667
|
+
animation: blink 1s infinite !important;
|
|
668
|
+
|
|
669
|
+
@keyframes blink {
|
|
670
|
+
0%, 50% {
|
|
671
|
+
opacity: 1 !important;
|
|
672
|
+
}
|
|
673
|
+
51%, 100% {
|
|
674
|
+
opacity: 0 !important;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
`;
|
|
678
|
+
// Streaming steps container styles
|
|
679
|
+
export const streamingStepsContainer = css `
|
|
680
|
+
margin-top: 8px !important;
|
|
681
|
+
font-size: 12px !important;
|
|
682
|
+
font-family: inherit !important;
|
|
683
|
+
`;
|
|
684
|
+
// Streaming step item styles
|
|
685
|
+
export const streamingStepItem = css `
|
|
686
|
+
display: flex !important;
|
|
687
|
+
align-items: center !important;
|
|
688
|
+
gap: 6px !important;
|
|
689
|
+
margin-top: 4px !important;
|
|
690
|
+
color: #666 !important;
|
|
691
|
+
font-family: inherit !important;
|
|
692
|
+
`;
|
|
693
|
+
// Streaming step checkmark styles
|
|
694
|
+
export const streamingStepCheck = css `
|
|
695
|
+
color: #4caf50 !important;
|
|
696
|
+
`;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SpeechConfig, SpeechSynthesizer } from 'microsoft-cognitiveservices-speech-sdk';
|
|
2
2
|
import Cookie from 'universal-cookie';
|
|
3
3
|
// Hardcoded Azure Speech credentials
|
|
4
|
-
const SPEECH_KEY = '
|
|
4
|
+
const SPEECH_KEY = '70ab55f06c454e82bcb5ee0c7a5ea25e';
|
|
5
5
|
const SPEECH_REGION = 'westcentralus';
|
|
6
6
|
const cookie = new Cookie();
|
|
7
7
|
/**
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Position {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
}
|
|
5
|
+
export declare const useDraggable: (dimensions: {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}) => {
|
|
9
|
+
position: Position;
|
|
10
|
+
handleDragStart: (event: React.PointerEvent<HTMLDivElement>) => void;
|
|
11
|
+
isDragging: boolean;
|
|
12
|
+
updatePosition: (newPosition: Position) => void;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=useDraggable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDraggable.d.ts","sourceRoot":"","sources":["../../../src/core/lib/useDraggable.ts"],"names":[],"mappings":"AAGA,UAAU,QAAQ;IAChB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAKD,eAAO,MAAM,YAAY,GAAI,YAAY;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;;6BAuFxC,KAAK,CAAC,YAAY,CAAC,cAAc,CAAC;;kCA8EjB,QAAQ;CAgB1D,CAAC"}
|