@envive-ai/react-toolkit-v3 0.3.15 → 0.3.17
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/AnimatedText/AnimatedText.d.cts +3 -3
- package/dist/CSSVariablesEditor/CssVariablesEditorComponent.d.cts +2 -2
- package/dist/Carousel/Carousel.d.cts +2 -2
- package/dist/Carousel/Carousel.d.ts +2 -2
- package/dist/ChatFooter/ChatFooter.d.cts +2 -2
- package/dist/ChatFooter/ChatFooter.d.ts +2 -2
- package/dist/ChatFooter/components/index.d.cts +5 -5
- package/dist/ChatFooter/components/index.d.ts +3 -3
- package/dist/ChatFooter/hooks/useGetContainerProperties.cjs +1 -1
- package/dist/ChatFooter/hooks/useGetContainerProperties.js +1 -1
- package/dist/ChatHeader/ChatHeader.d.cts +2 -2
- package/dist/ChatHeader/ChatHeader.d.ts +2 -2
- package/dist/ChatHeader/components/Handle.cjs +6 -4
- package/dist/ChatHeader/components/Handle.js +6 -4
- package/dist/ChatPreview/ChatPreview.cjs +14 -5
- package/dist/ChatPreview/ChatPreview.d.cts +2 -2
- package/dist/ChatPreview/ChatPreview.d.ts +2 -2
- package/dist/ChatPreview/ChatPreview.js +14 -5
- package/dist/ChatPreview/components/Message.cjs +3 -2
- package/dist/ChatPreview/components/Message.js +3 -2
- package/dist/ChatPreview/types/types.d.cts +34 -2
- package/dist/ChatPreview/types/types.d.ts +34 -2
- package/dist/ChatPreviewComparison/ChatPreviewComparison.cjs +11 -4
- package/dist/ChatPreviewComparison/ChatPreviewComparison.d.cts +2 -2
- package/dist/ChatPreviewComparison/ChatPreviewComparison.d.ts +2 -2
- package/dist/ChatPreviewComparison/ChatPreviewComparison.js +11 -4
- package/dist/ChatPreviewComparison/components/Message.cjs +3 -2
- package/dist/ChatPreviewComparison/components/Message.js +3 -2
- package/dist/ChatPreviewComparison/types/types.d.cts +34 -1
- package/dist/ChatPreviewComparison/types/types.d.ts +34 -1
- package/dist/ChatPreviewLoading/ChatPreviewLoading.cjs +1 -1
- package/dist/ChatPreviewLoading/ChatPreviewLoading.d.cts +2 -2
- package/dist/ChatPreviewLoading/ChatPreviewLoading.d.ts +2 -2
- package/dist/ChatPreviewLoading/ChatPreviewLoading.js +1 -1
- package/dist/Container/Container.d.cts +180 -180
- package/dist/Container/Container.d.ts +10 -10
- package/dist/DesignTokens/DesignTokensComponent.d.cts +2 -2
- package/dist/DesignTokens/DesignTokensComponent.d.ts +2 -2
- package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.cts +2 -2
- package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.ts +2 -2
- package/dist/FloatingButton/FloatingButton.d.cts +2 -2
- package/dist/FloatingButton/FloatingButton.d.ts +2 -2
- package/dist/FloatingChat/FloatingChat.cjs +4 -8
- package/dist/FloatingChat/FloatingChat.d.cts +2 -2
- package/dist/FloatingChat/FloatingChat.d.ts +2 -2
- package/dist/FloatingChat/FloatingChat.js +4 -8
- package/dist/FloatingChat/components/AgentMessage.cjs +1 -2
- package/dist/FloatingChat/components/AgentMessage.js +1 -2
- package/dist/FloatingChat/components/ChatMessages.cjs +1 -2
- package/dist/FloatingChat/components/ChatMessages.js +1 -2
- package/dist/FloatingChat/components/ModalSheet.cjs +13 -3
- package/dist/FloatingChat/components/ModalSheet.js +14 -4
- package/dist/FloatingChat/components/SalesAgentProductCardsCarousel.cjs +2 -3
- package/dist/FloatingChat/components/SalesAgentProductCardsCarousel.js +2 -3
- package/dist/FloatingChat/hooks/useFilteredChatMessages.cjs +1 -1
- package/dist/FloatingChat/hooks/useFilteredChatMessages.js +1 -1
- package/dist/FloatingChat/hooks/useSnapControl.cjs +17 -16
- package/dist/FloatingChat/hooks/useSnapControl.js +17 -16
- package/dist/FloatingChat/hooks/useSnapSetup.cjs +9 -27
- package/dist/FloatingChat/hooks/useSnapSetup.js +10 -28
- package/dist/FloatingChat/snapConstants.cjs +10 -0
- package/dist/FloatingChat/snapConstants.js +7 -0
- package/dist/FullPageSalesAgent/FullPageSalesAgent.cjs +5 -2
- package/dist/FullPageSalesAgent/FullPageSalesAgent.d.cts +2 -2
- package/dist/FullPageSalesAgent/FullPageSalesAgent.d.ts +2 -2
- package/dist/FullPageSalesAgent/FullPageSalesAgent.js +5 -2
- package/dist/FullPageSalesAgent/components/Layout.cjs +3 -1
- package/dist/FullPageSalesAgent/components/Layout.js +3 -1
- package/dist/FullPageSalesAgent/hooks/useGetFooterStyles.cjs +2 -1
- package/dist/FullPageSalesAgent/hooks/useGetFooterStyles.js +2 -1
- package/dist/FullPageSalesAgent/hooks/useGetMessagesStyles.cjs +10 -0
- package/dist/FullPageSalesAgent/hooks/useGetMessagesStyles.js +10 -0
- package/dist/FullPageSalesAgent/hooks/useGetScrollContentStyles.cjs +4 -2
- package/dist/FullPageSalesAgent/hooks/useGetScrollContentStyles.js +4 -2
- package/dist/Image/Image.d.cts +2 -2
- package/dist/Image/Image.d.ts +2 -2
- package/dist/ImageGallery/ImageGallery.d.cts +2 -2
- package/dist/ImageGallery/ImageGallery.d.ts +2 -2
- package/dist/MarkdownProcessor/MarkdownProcessor.cjs +2 -1
- package/dist/MarkdownProcessor/MarkdownProcessor.d.cts +2 -2
- package/dist/MarkdownProcessor/MarkdownProcessor.d.ts +2 -2
- package/dist/MarkdownProcessor/MarkdownProcessor.js +2 -1
- package/dist/ProductCard/ProductCard.cjs +8 -2
- package/dist/ProductCard/ProductCard.d.cts +8 -2
- package/dist/ProductCard/ProductCard.d.ts +8 -2
- package/dist/ProductCard/ProductCard.js +8 -2
- package/dist/ProductCard/components/Carousel.cjs +9 -3
- package/dist/ProductCard/components/Carousel.js +9 -3
- package/dist/ProductCard/types/index.d.cts +34 -0
- package/dist/ProductCard/types/index.d.ts +34 -0
- package/dist/PromptButton/PromptButton.d.cts +2 -2
- package/dist/PromptButton/PromptButton.d.ts +2 -2
- package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.cts +2 -2
- package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.ts +2 -2
- package/dist/PromptButtonCarouselWithImage/components/PromptButtonsCarousel.cjs +15 -21
- package/dist/PromptButtonCarouselWithImage/components/PromptButtonsCarousel.js +15 -21
- package/dist/PromptCarousel/PromptCarousel.d.cts +2 -2
- package/dist/PromptCarousel/PromptCarousel.d.ts +2 -2
- package/dist/ReviewCard/ReviewCard.d.cts +2 -2
- package/dist/ReviewCard/ReviewCard.d.ts +2 -2
- package/dist/ReviewCard/components/index.d.cts +6 -6
- package/dist/ReviewCard/components/index.d.ts +6 -6
- package/dist/SalesAgentProductCard/SalesAgentProductCard.d.cts +2 -2
- package/dist/SalesAgentProductCard/SalesAgentProductCard.d.ts +2 -2
- package/dist/SalesAgentProductCard/components/index.d.cts +8 -8
- package/dist/SalesAgentProductCard/components/index.d.ts +8 -8
- package/dist/SocialProof/SocialProof.cjs +4 -4
- package/dist/SocialProof/SocialProof.d.cts +2 -2
- package/dist/SocialProof/SocialProof.d.ts +2 -2
- package/dist/SocialProof/SocialProof.js +1 -1
- package/dist/SparkleAnimation/SparkleAnimation.d.cts +2 -2
- package/dist/SparkleAnimation/SparkleAnimation.d.ts +2 -2
- package/dist/Stack/Stack.d.cts +2 -2
- package/dist/Stack/Stack.d.ts +2 -2
- package/dist/TitledPromptCarousel/TitledPromptCarousel.d.cts +2 -2
- package/dist/TitledPromptCarousel/TitledPromptCarousel.d.ts +2 -2
- package/dist/TypingAnimation/TypingAnimation.cjs +8 -2
- package/dist/TypingAnimation/TypingAnimation.d.cts +2 -2
- package/dist/TypingAnimation/TypingAnimation.d.ts +2 -2
- package/dist/TypingAnimation/TypingAnimation.js +8 -2
- package/dist/TypingAnimation/types/index.d.cts +28 -0
- package/dist/TypingAnimation/types/index.d.ts +28 -0
- package/dist/Typography/Typography.d.cts +4 -4
- package/dist/WidgetTextField/WidgetTextField.d.cts +2 -2
- package/dist/WidgetTextField/WidgetTextField.d.ts +2 -2
- package/dist/WidgetTextField/components/Icon.cjs +2 -2
- package/dist/WidgetTextField/components/Icon.js +2 -2
- package/dist/WidgetWrapper/WidgetWrapper.d.cts +2 -2
- package/dist/WidgetWrapper/WidgetWrapper.d.ts +2 -2
- package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.ts +2 -2
- package/dist/styles.css +1 -1
- package/package.json +3 -3
- package/src/components/ChatFooter/__tests__/ChatFooter.test.tsx +3 -0
- package/src/components/ChatFooter/hooks/useGetContainerProperties.ts +1 -1
- package/src/components/ChatHeader/components/Handle.tsx +14 -4
- package/src/components/ChatPreview/ChatPreview.tsx +27 -6
- package/src/components/ChatPreview/__tests__/ChatPreview.test.tsx +16 -5
- package/src/components/ChatPreview/components/Message.tsx +3 -1
- package/src/components/ChatPreview/types/types.ts +35 -2
- package/src/components/ChatPreviewComparison/ChatPreviewComparison.tsx +23 -6
- package/src/components/ChatPreviewComparison/__tests__/ChatPreviewComparison.test.tsx +16 -5
- package/src/components/ChatPreviewComparison/components/Message.tsx +7 -1
- package/src/components/ChatPreviewComparison/types/types.ts +35 -1
- package/src/components/FloatingChat/FloatingChat.tsx +3 -9
- package/src/components/FloatingChat/components/AgentMessage.tsx +0 -3
- package/src/components/FloatingChat/components/ChatMessages.tsx +0 -3
- package/src/components/FloatingChat/components/ModalSheet.tsx +18 -10
- package/src/components/FloatingChat/components/SalesAgentProductCardsCarousel.tsx +1 -5
- package/src/components/FloatingChat/hooks/useFilteredChatMessages.ts +2 -2
- package/src/components/FloatingChat/hooks/useScrollToBottom.ts +1 -0
- package/src/components/FloatingChat/hooks/useSnapControl.ts +17 -22
- package/src/components/FloatingChat/hooks/useSnapSetup.ts +16 -37
- package/src/components/FloatingChat/snapConstants.ts +7 -0
- package/src/components/FullPageSalesAgent/FullPageSalesAgent.tsx +5 -2
- package/src/components/FullPageSalesAgent/components/Layout.tsx +3 -1
- package/src/components/FullPageSalesAgent/hooks/useGetFooterStyles.ts +7 -2
- package/src/components/FullPageSalesAgent/hooks/useGetMessagesStyles.ts +11 -0
- package/src/components/FullPageSalesAgent/hooks/useGetScrollContentStyles.ts +5 -1
- package/src/components/MarkdownProcessor/MarkdownProcessor.tsx +1 -1
- package/src/components/Message/__tests__/Message.test.tsx +3 -3
- package/src/components/ProductCard/ProductCard.tsx +13 -1
- package/src/components/ProductCard/__tests__/ProductCard.test.tsx +73 -1
- package/src/components/ProductCard/components/Carousel.tsx +13 -1
- package/src/components/ProductCard/types/index.ts +34 -0
- package/src/components/PromptButtonCarouselWithImage/components/PromptButtonsCarousel.tsx +12 -9
- package/src/components/TypingAnimation/TypingAnimation.tsx +22 -7
- package/src/components/TypingAnimation/types/index.ts +29 -0
- package/src/components/WidgetTextField/components/Icon.tsx +2 -2
|
@@ -19,7 +19,7 @@ export const useGetContainerProperties = ({
|
|
|
19
19
|
return themeContainerClassNameMap[theme] ?? '';
|
|
20
20
|
}, [theme, isScrolled]);
|
|
21
21
|
|
|
22
|
-
const baseClassName = `envive-tw-w-full envive-tw-border-border-light ${!isScrolled ? 'envive-tw-
|
|
22
|
+
const baseClassName = `envive-tw-w-full envive-tw-border-border-light ${!isScrolled ? 'envive-tw-bg-[color-mix(in_srgb,var(--envive-colors-background-light),transparent_10%)] envive-tw-backdrop-blur-[12px]' : ''}`;
|
|
23
23
|
|
|
24
24
|
return { baseClassName, themeContainerClassNames };
|
|
25
25
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { motion, useMotionValue, useTransform } from 'framer-motion';
|
|
2
|
+
import { MAX_SWIPEABLE_VIEW_HEIGHT } from 'src/components/FloatingChat/snapConstants';
|
|
2
3
|
import { Container } from '../../Container';
|
|
3
4
|
import { Stack } from '../../Stack';
|
|
4
5
|
import { useGetHandleProperties } from '../hooks/useGetHandleProperties';
|
|
@@ -7,14 +8,23 @@ import { HandleProps } from '../types';
|
|
|
7
8
|
export const Handle = ({ theme, variant, state, animationKey }: HandleProps) => {
|
|
8
9
|
const { containerClasses, leftBar, rightBar } = useGetHandleProperties(theme, variant, state);
|
|
9
10
|
|
|
10
|
-
const
|
|
11
|
-
const
|
|
11
|
+
const swipeviewFactor = MAX_SWIPEABLE_VIEW_HEIGHT / 100;
|
|
12
|
+
const closetSheetHeight = Math.floor(window.innerHeight * swipeviewFactor);
|
|
13
|
+
const snapFullView = 0;
|
|
12
14
|
|
|
13
15
|
const defaultAnimationKey = useMotionValue(0);
|
|
14
16
|
const activeAnimationKey = animationKey || defaultAnimationKey;
|
|
15
17
|
|
|
16
|
-
const leftRotation = useTransform(
|
|
17
|
-
|
|
18
|
+
const leftRotation = useTransform(
|
|
19
|
+
activeAnimationKey,
|
|
20
|
+
[snapFullView, closetSheetHeight],
|
|
21
|
+
[0, -10],
|
|
22
|
+
);
|
|
23
|
+
const rightRotation = useTransform(
|
|
24
|
+
activeAnimationKey,
|
|
25
|
+
[snapFullView, closetSheetHeight],
|
|
26
|
+
[0, 10],
|
|
27
|
+
);
|
|
18
28
|
|
|
19
29
|
if (animationKey) {
|
|
20
30
|
return (
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { useCallback, useMemo } from 'react';
|
|
2
|
-
import { WidgetWrapperVariant } from '../WidgetWrapper/types/types';
|
|
3
|
-
import { Theme } from '../Tokens';
|
|
4
|
-
import { resolveTheme } from '../utils/resolveTheme';
|
|
5
|
-
import { ChatPreviewComponents } from './components';
|
|
6
2
|
import { PromptButtonVariant } from '../PromptButton';
|
|
7
3
|
import { PromptCarousel, PromptCarouselRows } from '../PromptCarousel';
|
|
4
|
+
import { Theme } from '../Tokens';
|
|
5
|
+
import { resolveTheme } from '../utils/resolveTheme';
|
|
8
6
|
import { WidgetTextField } from '../WidgetTextField';
|
|
7
|
+
import { WidgetWrapperVariant } from '../WidgetWrapper/types/types';
|
|
9
8
|
import { WidgetWrapperWithTitle } from '../WidgetWrapperWithTitle/WidgetWrapperWithTitle';
|
|
9
|
+
import { ChatPreviewComponents } from './components';
|
|
10
10
|
import { ChatPreviewProps } from './types/types';
|
|
11
11
|
|
|
12
12
|
export const ChatPreview = ({
|
|
@@ -28,7 +28,17 @@ export const ChatPreview = ({
|
|
|
28
28
|
const { messageText, promptButtons, textFieldPlaceholderText, logoSrc, titleLabel } =
|
|
29
29
|
widgetContentProps ?? {};
|
|
30
30
|
|
|
31
|
-
const {
|
|
31
|
+
const {
|
|
32
|
+
handlePromptButtonClick,
|
|
33
|
+
handlePromptButtonDrag,
|
|
34
|
+
handlePromptButtonHover,
|
|
35
|
+
handlePromptButtonMouseDown,
|
|
36
|
+
handlePromptButtonMouseUp,
|
|
37
|
+
handlePromptButtonTouchStart,
|
|
38
|
+
handlePromptButtonTouchEnd,
|
|
39
|
+
handleLinkClick,
|
|
40
|
+
handleTextFieldClick,
|
|
41
|
+
} = widgetEventProps ?? {};
|
|
32
42
|
|
|
33
43
|
const suggestionTextMap = useMemo(() => {
|
|
34
44
|
return Object.fromEntries(
|
|
@@ -48,7 +58,12 @@ export const ChatPreview = ({
|
|
|
48
58
|
|
|
49
59
|
const finalTheme = resolveTheme(theme);
|
|
50
60
|
|
|
51
|
-
const message =
|
|
61
|
+
const message = (
|
|
62
|
+
<ChatPreviewComponents.Message
|
|
63
|
+
messageText={messageText ?? ''}
|
|
64
|
+
onLinkClick={handleLinkClick}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
52
67
|
|
|
53
68
|
const promptCarousel = (
|
|
54
69
|
<PromptCarousel
|
|
@@ -56,6 +71,12 @@ export const ChatPreview = ({
|
|
|
56
71
|
promptButtonType={PromptButtonVariant.SUGGESTED_RESPONSE}
|
|
57
72
|
promptCarouselRows={PromptCarouselRows.ALWAYS_ONE}
|
|
58
73
|
handleButtonClick={handleSuggestionButtonClick}
|
|
74
|
+
handleButtonDrag={handlePromptButtonDrag}
|
|
75
|
+
handleButtonHover={text => handlePromptButtonHover(suggestionTextMap[text].id)}
|
|
76
|
+
handleButtonMouseDown={text => handlePromptButtonMouseDown(suggestionTextMap[text].id)}
|
|
77
|
+
handleButtonMouseUp={handlePromptButtonMouseUp}
|
|
78
|
+
handleButtonTouchStart={text => handlePromptButtonTouchStart(suggestionTextMap[text].id)}
|
|
79
|
+
handleButtonTouchEnd={handlePromptButtonTouchEnd}
|
|
59
80
|
/>
|
|
60
81
|
);
|
|
61
82
|
|
|
@@ -2,10 +2,21 @@ import '@testing-library/jest-dom';
|
|
|
2
2
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
4
4
|
import { createElement } from 'react';
|
|
5
|
+
import { Suggestion } from '@envive-ai/react-hooks/application/models';
|
|
6
|
+
import { SuggestionCategory } from '@envive-ai/react-hooks/contexts/salesAgentContext';
|
|
5
7
|
import { ChatPreview } from '../ChatPreview';
|
|
6
8
|
import { WidgetWrapperVariant } from '../../WidgetWrapper/types/types';
|
|
7
9
|
import { Theme } from '../../Tokens';
|
|
8
10
|
|
|
11
|
+
const createSuggestions = (texts: string[]): Suggestion[] =>
|
|
12
|
+
texts.map((content, i) => ({
|
|
13
|
+
id: `suggestion-${i}`,
|
|
14
|
+
content,
|
|
15
|
+
category: SuggestionCategory.ProductBased,
|
|
16
|
+
createdAt: new Date().toISOString(),
|
|
17
|
+
isAnswer: false,
|
|
18
|
+
}));
|
|
19
|
+
|
|
9
20
|
vi.mock('../../MarkdownProcessor/MarkdownProcessor', () => {
|
|
10
21
|
return {
|
|
11
22
|
MarkdownProcessor: function MockMarkdownProcessor({ content }: { content: string }) {
|
|
@@ -20,12 +31,12 @@ describe('ChatPreview', () => {
|
|
|
20
31
|
widgetContentProps: {
|
|
21
32
|
titleLabel: 'Shopping Assistant',
|
|
22
33
|
messageText: 'How can I help you find the perfect product today?',
|
|
23
|
-
|
|
34
|
+
promptButtons: createSuggestions([
|
|
24
35
|
'What are the best products for gifting?',
|
|
25
36
|
'Show me summer dresses',
|
|
26
37
|
'Do you have free shipping?',
|
|
27
38
|
'What sizes are available?',
|
|
28
|
-
],
|
|
39
|
+
]),
|
|
29
40
|
textFieldPlaceholderText: 'What can I help you find?',
|
|
30
41
|
logoSrc: 'https://example.com/logo.svg',
|
|
31
42
|
},
|
|
@@ -290,13 +301,13 @@ describe('ChatPreview', () => {
|
|
|
290
301
|
});
|
|
291
302
|
|
|
292
303
|
describe('Edge cases', () => {
|
|
293
|
-
it('should render with empty
|
|
304
|
+
it('should render with empty promptButtons array', async () => {
|
|
294
305
|
render(
|
|
295
306
|
<ChatPreview
|
|
296
307
|
{...defaultProps}
|
|
297
308
|
widgetContentProps={{
|
|
298
309
|
...defaultProps.widgetContentProps,
|
|
299
|
-
|
|
310
|
+
promptButtons: [],
|
|
300
311
|
}}
|
|
301
312
|
/>,
|
|
302
313
|
);
|
|
@@ -326,7 +337,7 @@ describe('ChatPreview', () => {
|
|
|
326
337
|
widgetContentProps={{
|
|
327
338
|
titleLabel: 'Shopping Assistant',
|
|
328
339
|
messageText: 'Test message',
|
|
329
|
-
|
|
340
|
+
promptButtons: createSuggestions(['Button 1']),
|
|
330
341
|
}}
|
|
331
342
|
widgetStyleProps={{}}
|
|
332
343
|
widgetEventProps={{}}
|
|
@@ -7,9 +7,10 @@ const MarkdownProcessor = lazy(async () => ({
|
|
|
7
7
|
|
|
8
8
|
type MessageProps = {
|
|
9
9
|
messageText: string;
|
|
10
|
+
onLinkClick?: (url: string) => void;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
|
-
export const Message = ({ messageText }: MessageProps) => {
|
|
13
|
+
export const Message = ({ messageText, onLinkClick }: MessageProps) => {
|
|
13
14
|
return (
|
|
14
15
|
<Suspense>
|
|
15
16
|
<MarkdownProcessor
|
|
@@ -17,6 +18,7 @@ export const Message = ({ messageText }: MessageProps) => {
|
|
|
17
18
|
clampParagraphs={4}
|
|
18
19
|
textColor={TypographyColor.TEXT_PRIMARY}
|
|
19
20
|
textVariant={TypographyVariant.B3_RG}
|
|
21
|
+
onLinkClick={onLinkClick}
|
|
20
22
|
/>
|
|
21
23
|
</Suspense>
|
|
22
24
|
);
|
|
@@ -130,11 +130,44 @@ export type WidgetEventProps = {
|
|
|
130
130
|
* @param text - The text label of the clicked prompt button
|
|
131
131
|
*/
|
|
132
132
|
handlePromptButtonClick?: (suggestion: Suggestion) => void;
|
|
133
|
+
/**
|
|
134
|
+
* Callback function invoked when the prompt buttons carousel is dragged.
|
|
135
|
+
* Useful for tracking drag-to-scroll interactions.
|
|
136
|
+
*/
|
|
137
|
+
handlePromptButtonDrag?: () => void;
|
|
138
|
+
/**
|
|
139
|
+
* Callback function invoked when the user hovers over a prompt button.
|
|
140
|
+
* Receives the hovered button's text as a parameter.
|
|
141
|
+
*/
|
|
142
|
+
handlePromptButtonHover?: (text: string) => void;
|
|
143
|
+
/**
|
|
144
|
+
* Callback function invoked when the mouse button is pressed down on a prompt button.
|
|
145
|
+
* Receives the pressed button's text as a parameter.
|
|
146
|
+
*/
|
|
147
|
+
handlePromptButtonMouseDown?: (text: string) => void;
|
|
148
|
+
/**
|
|
149
|
+
* Callback function invoked when the mouse button is released after pressing a prompt button.
|
|
150
|
+
*/
|
|
151
|
+
handlePromptButtonMouseUp?: () => void;
|
|
152
|
+
/**
|
|
153
|
+
* Callback function invoked when a touch interaction starts on a prompt button.
|
|
154
|
+
* Receives the touched button's text as a parameter.
|
|
155
|
+
*/
|
|
156
|
+
handlePromptButtonTouchStart?: (text: string) => void;
|
|
157
|
+
/**
|
|
158
|
+
* Callback function invoked when a touch interaction ends after touching a prompt button.
|
|
159
|
+
*/
|
|
160
|
+
handlePromptButtonTouchEnd?: () => void;
|
|
133
161
|
|
|
134
162
|
/**
|
|
135
|
-
* Callback function invoked when the
|
|
163
|
+
* Callback function invoked when a link inside the widget is clicked.
|
|
136
164
|
*
|
|
137
|
-
* @param
|
|
165
|
+
* @param url - The URL of the clicked link
|
|
166
|
+
*/
|
|
167
|
+
handleLinkClick?: (url: string) => void;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Callback function invoked when the text field is clicked.
|
|
138
171
|
*/
|
|
139
172
|
handleTextFieldClick?: () => void;
|
|
140
173
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useCallback, useMemo } from 'react';
|
|
2
|
-
import { WidgetWrapperVariant } from '../WidgetWrapper/types/types';
|
|
3
|
-
import { Theme } from '../Tokens';
|
|
4
|
-
import { resolveTheme } from '../utils/resolveTheme';
|
|
5
|
-
import { ChatPreviewComparisonComponents } from './components';
|
|
6
2
|
import { PromptButtonVariant } from '../PromptButton';
|
|
7
3
|
import { PromptCarousel, PromptCarouselRows } from '../PromptCarousel';
|
|
4
|
+
import { Theme } from '../Tokens';
|
|
5
|
+
import { resolveTheme } from '../utils/resolveTheme';
|
|
8
6
|
import { WidgetTextField } from '../WidgetTextField';
|
|
9
|
-
import {
|
|
7
|
+
import { WidgetWrapperVariant } from '../WidgetWrapper/types/types';
|
|
10
8
|
import { WidgetWrapperWithTitle } from '../WidgetWrapperWithTitle/WidgetWrapperWithTitle';
|
|
9
|
+
import { ChatPreviewComparisonComponents } from './components';
|
|
10
|
+
import { ChatPreviewComparisonProps } from './types/types';
|
|
11
11
|
|
|
12
12
|
export const ChatPreviewComparison = ({
|
|
13
13
|
baseProps,
|
|
@@ -36,7 +36,17 @@ export const ChatPreviewComparison = ({
|
|
|
36
36
|
titleLabel,
|
|
37
37
|
} = widgetContentProps ?? {};
|
|
38
38
|
|
|
39
|
-
const {
|
|
39
|
+
const {
|
|
40
|
+
handlePromptButtonClick,
|
|
41
|
+
handlePromptButtonDrag,
|
|
42
|
+
handlePromptButtonHover,
|
|
43
|
+
handlePromptButtonMouseDown,
|
|
44
|
+
handlePromptButtonMouseUp,
|
|
45
|
+
handlePromptButtonTouchStart,
|
|
46
|
+
handlePromptButtonTouchEnd,
|
|
47
|
+
handleLinkClick,
|
|
48
|
+
handleTextFieldClick,
|
|
49
|
+
} = widgetEventProps ?? {};
|
|
40
50
|
|
|
41
51
|
const finalTheme = resolveTheme(theme);
|
|
42
52
|
|
|
@@ -67,6 +77,7 @@ export const ChatPreviewComparison = ({
|
|
|
67
77
|
<ChatPreviewComparisonComponents.Message
|
|
68
78
|
messageText={messageText ?? ''}
|
|
69
79
|
theme={finalTheme}
|
|
80
|
+
onLinkClick={handleLinkClick}
|
|
70
81
|
/>
|
|
71
82
|
);
|
|
72
83
|
|
|
@@ -76,6 +87,12 @@ export const ChatPreviewComparison = ({
|
|
|
76
87
|
promptButtonType={PromptButtonVariant.SUGGESTED_RESPONSE}
|
|
77
88
|
promptCarouselRows={PromptCarouselRows.ALWAYS_ONE}
|
|
78
89
|
handleButtonClick={handleSuggestionButtonClick}
|
|
90
|
+
handleButtonDrag={handlePromptButtonDrag}
|
|
91
|
+
handleButtonHover={text => handlePromptButtonHover(suggestionTextMap[text].id)}
|
|
92
|
+
handleButtonMouseDown={text => handlePromptButtonMouseDown(suggestionTextMap[text].id)}
|
|
93
|
+
handleButtonMouseUp={handlePromptButtonMouseUp}
|
|
94
|
+
handleButtonTouchStart={text => handlePromptButtonTouchStart(suggestionTextMap[text].id)}
|
|
95
|
+
handleButtonTouchEnd={handlePromptButtonTouchEnd}
|
|
79
96
|
/>
|
|
80
97
|
);
|
|
81
98
|
|
|
@@ -2,10 +2,21 @@ import '@testing-library/jest-dom';
|
|
|
2
2
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
4
4
|
import { createElement } from 'react';
|
|
5
|
+
import { Suggestion } from '@envive-ai/react-hooks/application/models';
|
|
6
|
+
import { SuggestionCategory } from '@envive-ai/react-hooks/contexts/salesAgentContext';
|
|
5
7
|
import { ChatPreviewComparison } from '../ChatPreviewComparison';
|
|
6
8
|
import { WidgetWrapperVariant } from '../../WidgetWrapper/types/types';
|
|
7
9
|
import { Theme } from '../../Tokens';
|
|
8
10
|
|
|
11
|
+
const createSuggestions = (texts: string[]): Suggestion[] =>
|
|
12
|
+
texts.map((content, i) => ({
|
|
13
|
+
id: `suggestion-${i}`,
|
|
14
|
+
content,
|
|
15
|
+
category: SuggestionCategory.ProductBased,
|
|
16
|
+
createdAt: new Date().toISOString(),
|
|
17
|
+
isAnswer: false,
|
|
18
|
+
}));
|
|
19
|
+
|
|
9
20
|
const mockUseCheckIsMobile = vi.fn(() => ({ isMobile: false, viewportWidth: 1024 }));
|
|
10
21
|
vi.mock('../../utils/useCheckIsMobile', () => ({
|
|
11
22
|
useCheckIsMobile: () => mockUseCheckIsMobile(),
|
|
@@ -40,12 +51,12 @@ describe('ChatPreviewComparison', () => {
|
|
|
40
51
|
headlineText: 'Compare these products',
|
|
41
52
|
messageText:
|
|
42
53
|
'I can help you compare these two products side by side. Let me know what specific features, specifications, or details you would like to know more about.',
|
|
43
|
-
|
|
54
|
+
promptButtons: createSuggestions([
|
|
44
55
|
'Tell me about product A',
|
|
45
56
|
'Tell me about product B',
|
|
46
57
|
'What are the differences?',
|
|
47
58
|
'Which one is better?',
|
|
48
|
-
],
|
|
59
|
+
]),
|
|
49
60
|
textFieldPlaceholderText: 'What can I help you find?',
|
|
50
61
|
images: [
|
|
51
62
|
{ src: 'https://picsum.photos/400/600?random=1', alt: 'Image 1' },
|
|
@@ -349,13 +360,13 @@ describe('ChatPreviewComparison', () => {
|
|
|
349
360
|
expect(screen.getByText('Compare these products')).toBeInTheDocument();
|
|
350
361
|
});
|
|
351
362
|
|
|
352
|
-
it('should render with empty
|
|
363
|
+
it('should render with empty promptButtons array', () => {
|
|
353
364
|
render(
|
|
354
365
|
<ChatPreviewComparison
|
|
355
366
|
{...defaultProps}
|
|
356
367
|
widgetContentProps={{
|
|
357
368
|
...defaultProps.widgetContentProps,
|
|
358
|
-
|
|
369
|
+
promptButtons: [],
|
|
359
370
|
}}
|
|
360
371
|
/>,
|
|
361
372
|
);
|
|
@@ -396,7 +407,7 @@ describe('ChatPreviewComparison', () => {
|
|
|
396
407
|
titleLabel: 'Shopping Assistant',
|
|
397
408
|
headlineText: 'Compare these products',
|
|
398
409
|
messageText: 'Test message',
|
|
399
|
-
|
|
410
|
+
promptButtons: createSuggestions(['Button 1']),
|
|
400
411
|
}}
|
|
401
412
|
widgetStyleProps={{}}
|
|
402
413
|
widgetEventProps={{}}
|
|
@@ -11,9 +11,14 @@ const MarkdownProcessor = lazy(async () => ({
|
|
|
11
11
|
type MessageProps = {
|
|
12
12
|
messageText: string;
|
|
13
13
|
theme: Theme;
|
|
14
|
+
onLinkClick?: (url: string) => void;
|
|
14
15
|
};
|
|
15
16
|
|
|
16
|
-
export const Message = ({
|
|
17
|
+
export const Message = ({
|
|
18
|
+
messageText,
|
|
19
|
+
theme = Theme.GLOBAL_CUSTOM,
|
|
20
|
+
onLinkClick,
|
|
21
|
+
}: MessageProps) => {
|
|
17
22
|
const { isMobile } = useCheckIsMobile();
|
|
18
23
|
|
|
19
24
|
const finalTheme = resolveTheme(theme);
|
|
@@ -28,6 +33,7 @@ export const Message = ({ messageText, theme = Theme.GLOBAL_CUSTOM }: MessagePro
|
|
|
28
33
|
clampParagraphs={isStandardAndMobile ? 7 : 3}
|
|
29
34
|
textColor={TypographyColor.TEXT_PRIMARY}
|
|
30
35
|
textVariant={TypographyVariant.B3_RG}
|
|
36
|
+
onLinkClick={onLinkClick}
|
|
31
37
|
/>
|
|
32
38
|
</Suspense>
|
|
33
39
|
);
|
|
@@ -136,10 +136,44 @@ export type WidgetEventProps = {
|
|
|
136
136
|
* @param text - The text label of the clicked prompt button
|
|
137
137
|
*/
|
|
138
138
|
handlePromptButtonClick?: (suggestion: Suggestion) => void;
|
|
139
|
+
/**
|
|
140
|
+
* Callback function invoked when the prompt buttons carousel is dragged.
|
|
141
|
+
* Useful for tracking drag-to-scroll interactions.
|
|
142
|
+
*/
|
|
143
|
+
handlePromptButtonDrag?: () => void;
|
|
144
|
+
/**
|
|
145
|
+
* Callback function invoked when the user hovers over a prompt button.
|
|
146
|
+
* Receives the hovered button's text as a parameter.
|
|
147
|
+
*/
|
|
148
|
+
handlePromptButtonHover?: (text: string) => void;
|
|
149
|
+
/**
|
|
150
|
+
* Callback function invoked when the mouse button is pressed down on a prompt button.
|
|
151
|
+
* Receives the pressed button's text as a parameter.
|
|
152
|
+
*/
|
|
153
|
+
handlePromptButtonMouseDown?: (text: string) => void;
|
|
154
|
+
/**
|
|
155
|
+
* Callback function invoked when the mouse button is released after pressing a prompt button.
|
|
156
|
+
*/
|
|
157
|
+
handlePromptButtonMouseUp?: () => void;
|
|
158
|
+
/**
|
|
159
|
+
* Callback function invoked when a touch interaction starts on a prompt button.
|
|
160
|
+
* Receives the touched button's text as a parameter.
|
|
161
|
+
*/
|
|
162
|
+
handlePromptButtonTouchStart?: (text: string) => void;
|
|
163
|
+
/**
|
|
164
|
+
* Callback function invoked when a touch interaction ends after touching a prompt button.
|
|
165
|
+
*/
|
|
166
|
+
handlePromptButtonTouchEnd?: () => void;
|
|
139
167
|
|
|
140
168
|
/**
|
|
141
|
-
* Callback function invoked when the
|
|
169
|
+
* Callback function invoked when a link inside the widget is clicked.
|
|
142
170
|
*
|
|
171
|
+
* @param url - The URL of the clicked link
|
|
172
|
+
*/
|
|
173
|
+
handleLinkClick?: (url: string) => void;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Callback function invoked when the text field is clicked.
|
|
143
177
|
*/
|
|
144
178
|
handleTextFieldClick?: () => void;
|
|
145
179
|
};
|
|
@@ -65,7 +65,6 @@ export const FloatingChat = ({
|
|
|
65
65
|
showEnviveLogo,
|
|
66
66
|
ignoreFirstModelResponse,
|
|
67
67
|
neverShowSingleProductCards,
|
|
68
|
-
partialViewConfig,
|
|
69
68
|
} = floatingChatConfig;
|
|
70
69
|
|
|
71
70
|
const {
|
|
@@ -108,8 +107,6 @@ export const FloatingChat = ({
|
|
|
108
107
|
}
|
|
109
108
|
};
|
|
110
109
|
|
|
111
|
-
const partialViewDisabled = partialViewConfig?.disabled ?? false;
|
|
112
|
-
|
|
113
110
|
const {
|
|
114
111
|
modalSheetControl,
|
|
115
112
|
maxSwipeableViewHeight,
|
|
@@ -122,10 +119,8 @@ export const FloatingChat = ({
|
|
|
122
119
|
handleSnapChange,
|
|
123
120
|
animationKey,
|
|
124
121
|
mobileHeaderHeight,
|
|
125
|
-
shouldShowHeader,
|
|
126
122
|
isFullView,
|
|
127
|
-
|
|
128
|
-
} = useSnapSetup({ isFloatingChatOpen, partialViewDisabled });
|
|
123
|
+
} = useSnapSetup({ isFloatingChatOpen });
|
|
129
124
|
|
|
130
125
|
const { showScrollButton, scrollToBottom, isFloatingLayout } = useScrollToBottom({
|
|
131
126
|
messagesRef: chatMessagesRef,
|
|
@@ -137,7 +132,7 @@ export const FloatingChat = ({
|
|
|
137
132
|
generalSuggestions,
|
|
138
133
|
],
|
|
139
134
|
scrollThreshold: 100,
|
|
140
|
-
useFloatingLayout:
|
|
135
|
+
useFloatingLayout: false,
|
|
141
136
|
footerHeight: 160,
|
|
142
137
|
isOpen: isFloatingChatOpen,
|
|
143
138
|
});
|
|
@@ -304,7 +299,6 @@ export const FloatingChat = ({
|
|
|
304
299
|
ignoreFirstModelResponse={ignoreFirstModelResponse}
|
|
305
300
|
neverShowSingleProductCards={neverShowSingleProductCards}
|
|
306
301
|
showVerifiedBuyer={showVerifiedBuyer}
|
|
307
|
-
isPartialView={isPartialView}
|
|
308
302
|
onFormResponseSubmitted={onFormResponseSubmitted}
|
|
309
303
|
parentWidget={WidgetInteractionComponent.FLOATING_CHAT}
|
|
310
304
|
/>
|
|
@@ -367,7 +361,7 @@ export const FloatingChat = ({
|
|
|
367
361
|
style={style}
|
|
368
362
|
testId={testId}
|
|
369
363
|
theme={finalTheme}
|
|
370
|
-
header={
|
|
364
|
+
header={mobileHeader}
|
|
371
365
|
footer={footer}
|
|
372
366
|
welcomeMessage={welcomeMessage}
|
|
373
367
|
chatMessages={chatMessages}
|
|
@@ -40,7 +40,6 @@ export interface AgentMessageProps {
|
|
|
40
40
|
isPendingResponse?: boolean;
|
|
41
41
|
neverShowSingleProductCards?: boolean;
|
|
42
42
|
showVerifiedBuyer?: boolean;
|
|
43
|
-
isPartialView?: boolean;
|
|
44
43
|
onFormResponseSubmitted?: (formResponse: FormSubmittedAttributes) => void;
|
|
45
44
|
parentWidget: WidgetInteractionComponent;
|
|
46
45
|
}
|
|
@@ -55,7 +54,6 @@ export const AgentMessage = ({
|
|
|
55
54
|
isPendingResponse = false,
|
|
56
55
|
neverShowSingleProductCards = false,
|
|
57
56
|
showVerifiedBuyer = false,
|
|
58
|
-
isPartialView,
|
|
59
57
|
onFormResponseSubmitted,
|
|
60
58
|
parentWidget,
|
|
61
59
|
}: AgentMessageProps) => {
|
|
@@ -175,7 +173,6 @@ export const AgentMessage = ({
|
|
|
175
173
|
products={products}
|
|
176
174
|
numberOfProducts={products.length}
|
|
177
175
|
theme={finalTheme}
|
|
178
|
-
isPartialView={isPartialView}
|
|
179
176
|
onProductCardClick={handleProductCardClick}
|
|
180
177
|
/>
|
|
181
178
|
);
|
|
@@ -30,7 +30,6 @@ export interface ChatMessagesProps {
|
|
|
30
30
|
ignoreFirstModelResponse?: boolean;
|
|
31
31
|
neverShowSingleProductCards?: boolean;
|
|
32
32
|
showVerifiedBuyer?: boolean;
|
|
33
|
-
isPartialView?: boolean;
|
|
34
33
|
onFormResponseSubmitted?: (formResponse: FormSubmittedAttributes) => void;
|
|
35
34
|
parentWidget: WidgetInteractionComponent;
|
|
36
35
|
}
|
|
@@ -49,7 +48,6 @@ export const ChatMessages = forwardRef<HTMLDivElement, ChatMessagesProps>(
|
|
|
49
48
|
ignoreFirstModelResponse,
|
|
50
49
|
neverShowSingleProductCards,
|
|
51
50
|
showVerifiedBuyer,
|
|
52
|
-
isPartialView,
|
|
53
51
|
onFormResponseSubmitted,
|
|
54
52
|
parentWidget,
|
|
55
53
|
},
|
|
@@ -143,7 +141,6 @@ export const ChatMessages = forwardRef<HTMLDivElement, ChatMessagesProps>(
|
|
|
143
141
|
isPendingResponse={isLoading && isLastMessageTurn}
|
|
144
142
|
neverShowSingleProductCards={neverShowSingleProductCards}
|
|
145
143
|
showVerifiedBuyer={showVerifiedBuyer}
|
|
146
|
-
isPartialView={isPartialView}
|
|
147
144
|
onFormResponseSubmitted={onFormResponseSubmitted}
|
|
148
145
|
parentWidget={parentWidget}
|
|
149
146
|
/>
|
|
@@ -5,14 +5,12 @@ import {
|
|
|
5
5
|
motion,
|
|
6
6
|
useAnimate,
|
|
7
7
|
} from 'framer-motion';
|
|
8
|
-
import React, { FC, TouchEvent, useEffect, useImperativeHandle } from 'react';
|
|
8
|
+
import React, { FC, TouchEvent, useEffect, useImperativeHandle, useRef } from 'react';
|
|
9
9
|
import { usePreventScroll } from '../hooks/usePreventScroll';
|
|
10
10
|
import { Unit } from '../hooks/useSnapCalculator';
|
|
11
11
|
import { useSnapControl } from '../hooks/useSnapControl';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
jumpToSnap: (snapIndex: number) => void;
|
|
15
|
-
}
|
|
12
|
+
import { FULL_SNAP_INDEX, HIDDEN_SNAP_INDEX } from '../snapConstants';
|
|
13
|
+
import type { ModalSheetControl } from '../snapConstants';
|
|
16
14
|
|
|
17
15
|
interface ModalSheetProps {
|
|
18
16
|
animationKey: MotionValue;
|
|
@@ -47,6 +45,7 @@ export const ModalSheet: FC<ModalSheetProps> = ({
|
|
|
47
45
|
}) => {
|
|
48
46
|
const [layerRef] = useAnimate();
|
|
49
47
|
const [containerRef] = useAnimate();
|
|
48
|
+
const justDraggedRef = useRef(false);
|
|
50
49
|
|
|
51
50
|
const {
|
|
52
51
|
gestureRef,
|
|
@@ -98,10 +97,15 @@ export const ModalSheet: FC<ModalSheetProps> = ({
|
|
|
98
97
|
},
|
|
99
98
|
}));
|
|
100
99
|
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
const handleHandlerClick = () => {
|
|
101
|
+
if (justDraggedRef.current) {
|
|
102
|
+
justDraggedRef.current = false;
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (snaps.length === 2) {
|
|
106
|
+
// Toggle between open and closed. if full (100): close. if closed (0): open.
|
|
107
|
+
const targetSnap = currentSnap === 100 ? snaps[HIDDEN_SNAP_INDEX] : snaps[FULL_SNAP_INDEX];
|
|
108
|
+
jumpTo(getSnapToPixel(targetSnap));
|
|
105
109
|
}
|
|
106
110
|
};
|
|
107
111
|
|
|
@@ -148,6 +152,10 @@ export const ModalSheet: FC<ModalSheetProps> = ({
|
|
|
148
152
|
}, [open]);
|
|
149
153
|
|
|
150
154
|
const handleDragEnd = () => {
|
|
155
|
+
justDraggedRef.current = true;
|
|
156
|
+
setTimeout(() => {
|
|
157
|
+
justDraggedRef.current = false;
|
|
158
|
+
}, 200);
|
|
151
159
|
const snap = defineNextSnapByPosition();
|
|
152
160
|
jumpTo(snap);
|
|
153
161
|
};
|
|
@@ -229,7 +237,7 @@ export const ModalSheet: FC<ModalSheetProps> = ({
|
|
|
229
237
|
exit={{ y: swipeviewHeightPx }}
|
|
230
238
|
transition={animation}
|
|
231
239
|
onDragEnd={handleDragEnd}
|
|
232
|
-
onClick={
|
|
240
|
+
onClick={handleHandlerClick}
|
|
233
241
|
style={{
|
|
234
242
|
y: animatedY,
|
|
235
243
|
bottom: swipeviewHeightPx,
|
|
@@ -13,7 +13,6 @@ export interface SalesAgentProductCardsCarouselProps {
|
|
|
13
13
|
numberOfProducts?: number;
|
|
14
14
|
products: SalesAgentProductCardProps[];
|
|
15
15
|
variant?: SalesAgentProductCardVariant;
|
|
16
|
-
isPartialView?: boolean;
|
|
17
16
|
onProductCardClick?: (product: SalesAgentProductCardProps) => void;
|
|
18
17
|
}
|
|
19
18
|
|
|
@@ -23,13 +22,10 @@ export const SalesAgentProductCardsCarousel = ({
|
|
|
23
22
|
hideNavigation = false,
|
|
24
23
|
numberOfProducts,
|
|
25
24
|
variant = SalesAgentProductCardVariant.LARGE,
|
|
26
|
-
isPartialView = false,
|
|
27
25
|
onProductCardClick,
|
|
28
26
|
}: SalesAgentProductCardsCarouselProps) => {
|
|
29
27
|
const finalTheme = resolveTheme(theme);
|
|
30
28
|
|
|
31
|
-
const finalVariant = isPartialView ? SalesAgentProductCardVariant.SMALL : variant;
|
|
32
|
-
|
|
33
29
|
const forceShowCurrentPriceSpace = products.some(
|
|
34
30
|
product => product.currentPrice && product.previousPrice !== product.currentPrice,
|
|
35
31
|
);
|
|
@@ -44,7 +40,7 @@ export const SalesAgentProductCardsCarousel = ({
|
|
|
44
40
|
elements={products.map(product => (
|
|
45
41
|
<SalesAgentProductCard
|
|
46
42
|
key={product.id}
|
|
47
|
-
variant={
|
|
43
|
+
variant={variant}
|
|
48
44
|
productName={product.productName}
|
|
49
45
|
currentPrice={product.currentPrice}
|
|
50
46
|
previousPrice={product.previousPrice}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RefObject, useMemo } from 'react';
|
|
2
2
|
import { Message } from '@envive-ai/react-hooks/application/models';
|
|
3
3
|
import { useMessageFilter } from '@envive-ai/react-hooks/hooks/MessageFilter';
|
|
4
|
-
import { ModalSheetControl } from '../
|
|
4
|
+
import type { ModalSheetControl } from '../types';
|
|
5
5
|
|
|
6
6
|
export interface UseFilteredChatMessagesProps {
|
|
7
7
|
messages: Message[][];
|
|
@@ -33,7 +33,7 @@ export const useFilteredChatMessages = ({
|
|
|
33
33
|
|
|
34
34
|
const hasFilteredMessages = filteredMessages.length !== messages.length && isMobile;
|
|
35
35
|
|
|
36
|
-
const handlePreviousDiscussions = () => modalSheetControl.current?.jumpToSnap(
|
|
36
|
+
const handlePreviousDiscussions = () => modalSheetControl.current?.jumpToSnap(1);
|
|
37
37
|
|
|
38
38
|
return {
|
|
39
39
|
filteredMessages,
|
|
@@ -125,6 +125,7 @@ export const useScrollToBottom = ({
|
|
|
125
125
|
}
|
|
126
126
|
});
|
|
127
127
|
}
|
|
128
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- autoScrollDependencies is intentionally spread for dynamic deps
|
|
128
129
|
}, [...autoScrollDependencies, getScrollableContainer, useFloatingLayout]);
|
|
129
130
|
|
|
130
131
|
useEffect(() => {
|