@envive-ai/react-toolkit-v3 0.3.19 → 0.3.21

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 (117) hide show
  1. package/dist/AnimatedText/AnimatedText.d.cts +3 -3
  2. package/dist/CSSVariablesEditor/CssVariablesEditorComponent.d.cts +2 -2
  3. package/dist/Carousel/Carousel.d.cts +2 -2
  4. package/dist/Carousel/Carousel.d.ts +2 -2
  5. package/dist/ChatFooter/ChatFooter.d.cts +2 -2
  6. package/dist/ChatFooter/ChatFooter.d.ts +2 -2
  7. package/dist/ChatFooter/components/index.d.cts +5 -5
  8. package/dist/ChatFooter/components/index.d.ts +5 -5
  9. package/dist/ChatHeader/ChatHeader.d.ts +2 -2
  10. package/dist/ChatPreview/ChatPreview.d.cts +2 -2
  11. package/dist/ChatPreview/ChatPreview.d.ts +2 -2
  12. package/dist/ChatPreviewComparison/ChatPreviewComparison.d.cts +2 -2
  13. package/dist/ChatPreviewComparison/ChatPreviewComparison.d.ts +2 -2
  14. package/dist/ChatPreviewComparison/components/Layout.cjs +2 -2
  15. package/dist/ChatPreviewComparison/components/Message.cjs +2 -2
  16. package/dist/ChatPreviewLoading/ChatPreviewLoading.d.cts +2 -2
  17. package/dist/ChatPreviewLoading/ChatPreviewLoading.d.ts +2 -2
  18. package/dist/Container/Container.d.cts +175 -175
  19. package/dist/Container/Container.d.ts +175 -175
  20. package/dist/DesignTokens/DesignTokensComponent.d.cts +2 -2
  21. package/dist/DesignTokens/DesignTokensComponent.d.ts +2 -2
  22. package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.cts +2 -2
  23. package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.ts +2 -2
  24. package/dist/FloatingButton/FloatingButton.d.cts +2 -2
  25. package/dist/FloatingButton/FloatingButton.d.ts +2 -2
  26. package/dist/FloatingChat/FloatingChat.cjs +25 -22
  27. package/dist/FloatingChat/FloatingChat.d.cts +4 -3
  28. package/dist/FloatingChat/FloatingChat.d.ts +4 -3
  29. package/dist/FloatingChat/FloatingChat.js +26 -23
  30. package/dist/FloatingChat/components/AgentMessage.cjs +2 -8
  31. package/dist/FloatingChat/components/AgentMessage.js +2 -8
  32. package/dist/FloatingChat/components/ProductResultsModal.cjs +62 -0
  33. package/dist/FloatingChat/components/ProductResultsModal.js +60 -0
  34. package/dist/FloatingChat/components/ResultsGridView.cjs +17 -3
  35. package/dist/FloatingChat/components/ResultsGridView.js +15 -4
  36. package/dist/FloatingChat/components/SlideChatContent.cjs +3 -2
  37. package/dist/FloatingChat/components/SlideChatContent.js +4 -3
  38. package/dist/FloatingChat/components/index.cjs +2 -0
  39. package/dist/FloatingChat/components/index.js +2 -0
  40. package/dist/FloatingChat/hooks/useProductResultsView.cjs +14 -1
  41. package/dist/FloatingChat/hooks/useProductResultsView.js +15 -2
  42. package/dist/FloatingChat/hooks/useSnapSetup.cjs +2 -2
  43. package/dist/FloatingChat/types/types.d.cts +4 -0
  44. package/dist/FloatingChat/types/types.d.ts +4 -0
  45. package/dist/FloatingChat/utils/functions.cjs +24 -16
  46. package/dist/FloatingChat/utils/functions.js +24 -17
  47. package/dist/FloatingChat/utils/trackProductCardInteraction.cjs +18 -0
  48. package/dist/FloatingChat/utils/trackProductCardInteraction.js +17 -0
  49. package/dist/FullPageSalesAgent/FullPageSalesAgent.cjs +29 -7
  50. package/dist/FullPageSalesAgent/FullPageSalesAgent.d.cts +2 -2
  51. package/dist/FullPageSalesAgent/FullPageSalesAgent.js +29 -7
  52. package/dist/FullPageSalesAgent/components/Layout.cjs +2 -1
  53. package/dist/FullPageSalesAgent/components/Layout.js +2 -1
  54. package/dist/FullPageSalesAgent/hooks/useIsMobile.cjs +2 -2
  55. package/dist/Image/Image.d.cts +2 -2
  56. package/dist/Image/Image.d.ts +2 -2
  57. package/dist/ImageGallery/ImageGallery.d.cts +2 -2
  58. package/dist/ImageGallery/ImageGallery.d.ts +2 -2
  59. package/dist/ImageGallery/components/Layout.cjs +2 -2
  60. package/dist/MarkdownProcessor/MarkdownProcessor.d.cts +2 -2
  61. package/dist/MarkdownProcessor/MarkdownProcessor.d.ts +2 -2
  62. package/dist/ProductCard/ProductCard.d.cts +2 -2
  63. package/dist/ProductCard/ProductCard.d.ts +2 -2
  64. package/dist/PromptButton/PromptButton.d.cts +2 -2
  65. package/dist/PromptButton/PromptButton.d.ts +2 -2
  66. package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.cts +2 -2
  67. package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.ts +2 -2
  68. package/dist/PromptButtonCarouselWithImage/components/Layout.cjs +2 -2
  69. package/dist/PromptButtonCarouselWithImage/components/PromptButtonsCarousel.cjs +2 -2
  70. package/dist/PromptCarousel/PromptCarousel.cjs +2 -2
  71. package/dist/PromptCarousel/PromptCarousel.d.cts +2 -2
  72. package/dist/PromptCarousel/PromptCarousel.d.ts +2 -2
  73. package/dist/ReviewCard/ReviewCard.d.cts +2 -2
  74. package/dist/ReviewCard/ReviewCard.d.ts +2 -2
  75. package/dist/ReviewCard/components/index.d.cts +6 -6
  76. package/dist/ReviewCard/components/index.d.ts +6 -6
  77. package/dist/SalesAgentProductCard/SalesAgentProductCard.d.cts +2 -2
  78. package/dist/SalesAgentProductCard/SalesAgentProductCard.d.ts +2 -2
  79. package/dist/SalesAgentProductCard/components/index.d.cts +8 -8
  80. package/dist/SalesAgentProductCard/components/index.d.ts +8 -8
  81. package/dist/SocialProof/SocialProof.cjs +2 -2
  82. package/dist/SocialProof/SocialProof.d.cts +2 -2
  83. package/dist/SocialProof/SocialProof.d.ts +2 -2
  84. package/dist/SocialProof/components/LayoutFourHorizontal.cjs +2 -2
  85. package/dist/SocialProof/components/LayoutSingle.cjs +2 -2
  86. package/dist/SparkleAnimation/SparkleAnimation.d.cts +2 -2
  87. package/dist/SparkleAnimation/SparkleAnimation.d.ts +2 -2
  88. package/dist/Stack/Stack.d.cts +2 -2
  89. package/dist/Stack/Stack.d.ts +2 -2
  90. package/dist/TitledPromptCarousel/TitledPromptCarousel.d.cts +2 -2
  91. package/dist/TitledPromptCarousel/TitledPromptCarousel.d.ts +2 -2
  92. package/dist/TypingAnimation/TypingAnimation.d.cts +2 -2
  93. package/dist/TypingAnimation/TypingAnimation.d.ts +2 -2
  94. package/dist/Typography/Typography.d.cts +4 -4
  95. package/dist/Typography/Typography.d.ts +4 -4
  96. package/dist/WidgetTextField/WidgetTextField.d.cts +2 -2
  97. package/dist/WidgetTextField/WidgetTextField.d.ts +2 -2
  98. package/dist/WidgetWrapper/WidgetWrapper.d.cts +2 -2
  99. package/dist/WidgetWrapper/WidgetWrapper.d.ts +2 -2
  100. package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.cts +2 -2
  101. package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.ts +2 -2
  102. package/dist/styles.css +1 -1
  103. package/dist/utils/useCheckIsMobile.d.cts +9 -0
  104. package/dist/utils/useCheckIsMobile.d.ts +9 -0
  105. package/package.json +5 -1
  106. package/src/components/FloatingChat/FloatingChat.tsx +35 -34
  107. package/src/components/FloatingChat/components/AgentMessage.tsx +2 -12
  108. package/src/components/FloatingChat/components/ProductResultsModal.tsx +87 -0
  109. package/src/components/FloatingChat/components/ResultsGridView.tsx +26 -2
  110. package/src/components/FloatingChat/components/SlideChatContent.tsx +9 -1
  111. package/src/components/FloatingChat/components/index.ts +2 -0
  112. package/src/components/FloatingChat/hooks/useProductResultsView.ts +26 -2
  113. package/src/components/FloatingChat/types/types.ts +4 -0
  114. package/src/components/FloatingChat/utils/functions.ts +34 -19
  115. package/src/components/FloatingChat/utils/trackProductCardInteraction.ts +26 -0
  116. package/src/components/FullPageSalesAgent/FullPageSalesAgent.tsx +54 -5
  117. package/src/components/FullPageSalesAgent/components/Layout.tsx +7 -1
@@ -1,5 +1,10 @@
1
- import { useEffect, useRef, useState } from 'react';
2
- import { getCleanProducts } from '../utils/functions';
1
+ import { Message, MessageType } from '@envive-ai/react-hooks/application/models';
2
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
+ import {
4
+ getCleanProducts,
5
+ getCleanProductsForResultsGrid,
6
+ getSearchQueryFromMessageBlock,
7
+ } from '../utils/functions';
3
8
 
4
9
  export type ResultsViewData = {
5
10
  products: ReturnType<typeof getCleanProducts>;
@@ -22,6 +27,24 @@ export const useProductResultsView = ({ scrollToBottom }: UseResultsViewProps) =
22
27
  setResultsViewData(null);
23
28
  };
24
29
 
30
+ const handleExploreAllResults = useCallback(
31
+ (firstProductMessageId: string, messages: Message[][]) => {
32
+ const blockIndex = messages.findIndex(block =>
33
+ block.some(msg => msg.type === MessageType.Product && msg.id === firstProductMessageId),
34
+ );
35
+ if (blockIndex < 0) return;
36
+
37
+ const messageBlock = messages[blockIndex];
38
+ const productMessages = messageBlock.filter(msg => msg.type === MessageType.Product);
39
+ const products = getCleanProductsForResultsGrid(productMessages);
40
+ if (products.length === 0) return;
41
+
42
+ const searchQuery = getSearchQueryFromMessageBlock(messages, blockIndex);
43
+ setResultsViewData({ products, searchQuery });
44
+ },
45
+ [],
46
+ );
47
+
25
48
  // Scroll to top when navigating to results view
26
49
  useEffect(() => {
27
50
  if (isResultsView && scrollContainerRef.current) {
@@ -45,5 +68,6 @@ export const useProductResultsView = ({ scrollToBottom }: UseResultsViewProps) =
45
68
  scrollContainerRef,
46
69
  isResultsViewRef,
47
70
  handleBackToChat,
71
+ handleExploreAllResults,
48
72
  };
49
73
  };
@@ -69,4 +69,8 @@ export interface FloatingChatProps {
69
69
  * Debug bar to display in the chat.
70
70
  */
71
71
  debugBar?: React.ReactNode;
72
+ /**
73
+ * Updates whether the product results modal is open (desktop full-width grid view).
74
+ */
75
+ setIsResultsModalOpen?: (isOpen: boolean) => void;
72
76
  }
@@ -34,27 +34,42 @@ export const checkIfHideAgentName = (messages: Message[]) => {
34
34
  );
35
35
  };
36
36
 
37
+ const mapProductMessageToCardProps = (msg: Message): SalesAgentProductCardProps | null => {
38
+ if (msg.type !== MessageType.Product) return null;
39
+ return {
40
+ id: msg.id,
41
+ productName: msg.metadata.title,
42
+ currentPrice: msg.metadata.salePrice,
43
+ previousPrice: msg.metadata.originalPrice,
44
+ pricePrefix: '$',
45
+ rate: msg.metadata.averageRating,
46
+ numberOfReviews: msg.metadata.numberReviews,
47
+ url: msg.metadata.url,
48
+ image: {
49
+ src: msg.metadata.imageUrl,
50
+ alt: `${msg.metadata.title} image`,
51
+ },
52
+ };
53
+ };
54
+
55
+ /** Product cards for carousels; excludes grid-only rows from the API (`isForGrid`). */
37
56
  export const getCleanProducts = (messages: Message[]) => {
38
- const products: SalesAgentProductCardProps[] = messages.map(msg => {
39
- if (msg.type === MessageType.Product && !msg.metadata.isForGrid) {
40
- return {
41
- productName: msg.metadata.title,
42
- currentPrice: msg.metadata.salePrice,
43
- previousPrice: msg.metadata.originalPrice,
44
- pricePrefix: '$',
45
- rate: msg.metadata.averageRating,
46
- numberOfReviews: msg.metadata.numberReviews,
47
- url: msg.metadata.url,
48
- image: {
49
- src: msg.metadata.imageUrl,
50
- alt: `${msg.metadata.title} image`,
51
- },
52
- };
53
- }
54
- return null;
55
- });
57
+ const cleanProducts = messages
58
+ .map(msg =>
59
+ msg.type === MessageType.Product && !msg.metadata.isForGrid
60
+ ? mapProductMessageToCardProps(msg)
61
+ : null,
62
+ )
63
+ .filter((p): p is SalesAgentProductCardProps => p !== null);
64
+ return cleanProducts;
65
+ };
56
66
 
57
- return products.filter(product => product !== null);
67
+ /** All product rows in a turn, including `isForGrid`, for the full results grid. */
68
+ export const getCleanProductsForResultsGrid = (messages: Message[]) => {
69
+ const productsForGrid = messages
70
+ .map(msg => (msg.type === MessageType.Product ? mapProductMessageToCardProps(msg) : null))
71
+ .filter((p): p is SalesAgentProductCardProps => p !== null);
72
+ return productsForGrid;
58
73
  };
59
74
 
60
75
  export const getCleanReviews = (messages: Message[]) => {
@@ -0,0 +1,26 @@
1
+ import { EnviveMetricsEventName } from '@envive-ai/react-hooks/contexts/amplitudeContext';
2
+ import {
3
+ type WidgetInteraction,
4
+ WidgetInteractionComponent,
5
+ WidgetInteractionType,
6
+ } from '@envive-ai/react-hooks/hooks/WidgetInteraction/types';
7
+ import type { SalesAgentProductCardProps } from '../../SalesAgentProductCard/types/types';
8
+
9
+ export const trackProductCardClicked = (
10
+ trackWidgetInteraction: (props: WidgetInteraction) => void,
11
+ widget: WidgetInteractionComponent,
12
+ product: SalesAgentProductCardProps,
13
+ ) => {
14
+ trackWidgetInteraction({
15
+ eventName: EnviveMetricsEventName.WidgetInteraction,
16
+ trigger: {
17
+ widget,
18
+ widget_interaction: WidgetInteractionType.PRODUCT_CARD_CLICKED,
19
+ widget_interaction_data: {
20
+ product_card_clicked: {
21
+ product_id: product.id,
22
+ },
23
+ },
24
+ },
25
+ });
26
+ };
@@ -13,7 +13,10 @@ import { ChatFooter } from '../ChatFooter';
13
13
  import { Disclaimer } from '../Disclaimer';
14
14
  import { FloatingChatComponents } from '../FloatingChat/components';
15
15
  import { useChatSuggestions } from '../FloatingChat/hooks/useChatSuggestions';
16
+ import { useProductResultsView } from '../FloatingChat/hooks/useProductResultsView';
16
17
  import { useScrollToBottom } from '../FloatingChat/hooks/useScrollToBottom';
18
+ import { trackProductCardClicked } from '../FloatingChat/utils/trackProductCardInteraction';
19
+ import { SalesAgentProductCardProps } from '../SalesAgentProductCard/types/types';
17
20
  import { PromptButtonVariant } from '../PromptButton';
18
21
  import { PromptCarousel, PromptCarouselRows, usePromptCarouselAnalytics } from '../PromptCarousel';
19
22
  import { Theme } from '../Tokens';
@@ -24,6 +27,11 @@ import { useGetFooterStyles } from './hooks/useGetFooterStyles';
24
27
  import { useGetMessagesStyles } from './hooks/useGetMessagesStyles';
25
28
  import { useGetScrollContentStyles } from './hooks/useGetScrollContentStyles';
26
29
  import { useIsMobile } from './hooks/useIsMobile';
30
+ import {
31
+ NUM_COLUMNS_FPSA,
32
+ NUM_COLUMNS_MOBILE,
33
+ ResultsGridColumnCount,
34
+ } from '../FloatingChat/components/ResultsGridView';
27
35
 
28
36
  interface FullPageSalesAgentProps {
29
37
  theme?: Theme;
@@ -107,6 +115,15 @@ export const FullPageSalesAgent = ({
107
115
  ],
108
116
  });
109
117
 
118
+ const {
119
+ resultsViewData,
120
+ isResultsView,
121
+ scrollContainerRef,
122
+ isResultsViewRef,
123
+ handleBackToChat,
124
+ handleExploreAllResults,
125
+ } = useProductResultsView({ scrollToBottom });
126
+
110
127
  const handleScrollToBottom = () => {
111
128
  scrollToBottom();
112
129
  trackWidgetInteraction({
@@ -128,6 +145,14 @@ export const FullPageSalesAgent = ({
128
145
  });
129
146
  };
130
147
 
148
+ const handleProductCardClick = (product: SalesAgentProductCardProps) => {
149
+ trackProductCardClicked(
150
+ trackWidgetInteraction,
151
+ WidgetInteractionComponent.FULL_PAGE_SALES_AGENT,
152
+ product,
153
+ );
154
+ };
155
+
131
156
  const welcomeMessage = (
132
157
  <div className={messageContainerClasses}>
133
158
  <WelcomeMessage
@@ -165,6 +190,7 @@ export const FullPageSalesAgent = ({
165
190
 
166
191
  setAnswerSuggestions([]);
167
192
  setGeneralSuggestions([]);
193
+ handleBackToChat();
168
194
  }}
169
195
  onChange={setQuery}
170
196
  onSubmit={() => {
@@ -175,6 +201,7 @@ export const FullPageSalesAgent = ({
175
201
  });
176
202
  setAnswerSuggestions([]);
177
203
  setGeneralSuggestions([]);
204
+ handleBackToChat();
178
205
  }}
179
206
  onFocus={handleInputQueryFocus}
180
207
  parentWidget={WidgetInteractionComponent.FULL_PAGE_SALES_AGENT}
@@ -197,6 +224,25 @@ export const FullPageSalesAgent = ({
197
224
  showVerifiedBuyer={showVerifiedBuyer}
198
225
  onFormResponseSubmitted={onFormResponseSubmitted}
199
226
  parentWidget={WidgetInteractionComponent.FULL_PAGE_SALES_AGENT}
227
+ onExploreAllResults={firstProductMessageId =>
228
+ handleExploreAllResults(firstProductMessageId, messages)
229
+ }
230
+ />
231
+ );
232
+
233
+ const middleContent = (
234
+ <FloatingChatComponents.SlideChatContent
235
+ isResultsView={isResultsView}
236
+ isResultsViewRef={isResultsViewRef}
237
+ resultsViewData={resultsViewData}
238
+ onBackToChat={handleBackToChat}
239
+ onProductCardClick={handleProductCardClick}
240
+ theme={resolvedTheme}
241
+ chatMessages={chatMessages}
242
+ scrollToBottom={scrollToBottom}
243
+ resultsGridColumns={
244
+ (isMobile ? NUM_COLUMNS_MOBILE : NUM_COLUMNS_FPSA) as ResultsGridColumnCount
245
+ }
200
246
  />
201
247
  );
202
248
 
@@ -232,18 +278,21 @@ export const FullPageSalesAgent = ({
232
278
  return (
233
279
  <FullPageSAComponents.Layout
234
280
  theme={resolvedTheme}
235
- welcomeMessage={welcomeMessage}
281
+ welcomeMessage={isResultsView ? null : welcomeMessage}
236
282
  footer={footer}
237
- chatMessages={chatMessages}
238
- answerSuggestions={showAnswerSuggestions ? answerSuggestionsComponent : undefined}
283
+ chatMessages={middleContent}
284
+ answerSuggestions={
285
+ showAnswerSuggestions && !isResultsView ? answerSuggestionsComponent : undefined
286
+ }
239
287
  scrollToBottomButton={
240
- showScrollButton ? (
288
+ !isResultsView && showScrollButton ? (
241
289
  <FloatingChatComponents.ScrollToBottomButton onClick={handleScrollToBottom} />
242
290
  ) : undefined
243
291
  }
244
- disclaimer={disclaimer}
292
+ disclaimer={isResultsView ? null : disclaimer}
245
293
  headerContainer={headerContainer}
246
294
  autoHeight={autoHeight}
295
+ scrollContainerRef={scrollContainerRef}
247
296
  />
248
297
  );
249
298
  };
@@ -17,6 +17,8 @@ export interface LayoutProps {
17
17
  disclaimer?: React.ReactNode;
18
18
  headerContainer?: string;
19
19
  autoHeight?: boolean;
20
+ /** Scrollable content ref (e.g. scroll to top when opening product results grid) */
21
+ scrollContainerRef?: React.RefObject<HTMLDivElement | null>;
20
22
  }
21
23
 
22
24
  export const Layout = ({
@@ -29,6 +31,7 @@ export const Layout = ({
29
31
  disclaimer,
30
32
  headerContainer,
31
33
  autoHeight,
34
+ scrollContainerRef,
32
35
  }: LayoutProps) => {
33
36
  const hasWelcomeMessage = isValidElement(welcomeMessage);
34
37
  const hasAnswerSuggestions = isValidElement(answerSuggestions);
@@ -45,7 +48,10 @@ export const Layout = ({
45
48
  className={containerClasses}
46
49
  style={containerStyles}
47
50
  >
48
- <div className={contentClasses}>
51
+ <div
52
+ ref={scrollContainerRef}
53
+ className={contentClasses}
54
+ >
49
55
  <Stack
50
56
  direction="column"
51
57
  justify="between"