@envive-ai/react-toolkit-v3 0.3.6 → 0.3.7

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 (157) hide show
  1. package/dist/AnimatedText/AnimatedText.d.cts +3 -3
  2. package/dist/AnimatedText/AnimatedText.d.ts +3 -3
  3. package/dist/CSSVariablesEditor/CssVariablesEditorComponent.d.cts +2 -2
  4. package/dist/CSSVariablesEditor/CssVariablesEditorComponent.d.ts +2 -2
  5. package/dist/Carousel/Carousel.d.cts +2 -2
  6. package/dist/Carousel/Carousel.d.ts +2 -2
  7. package/dist/ChatFooter/ChatFooter.d.cts +2 -2
  8. package/dist/ChatFooter/ChatFooter.d.ts +2 -2
  9. package/dist/ChatFooter/components/index.d.cts +5 -5
  10. package/dist/ChatFooter/components/index.d.ts +5 -5
  11. package/dist/ChatFooter/hooks/useGetContainerProperties.cjs +2 -2
  12. package/dist/ChatFooter/hooks/useGetContainerProperties.js +2 -2
  13. package/dist/ChatHeader/ChatHeader.cjs +3 -2
  14. package/dist/ChatHeader/ChatHeader.d.cts +3 -2
  15. package/dist/ChatHeader/ChatHeader.d.ts +3 -2
  16. package/dist/ChatHeader/ChatHeader.js +3 -2
  17. package/dist/ChatHeader/components/Handle.cjs +27 -1
  18. package/dist/ChatHeader/components/Handle.js +27 -1
  19. package/dist/ChatHeader/types/index.d.cts +2 -0
  20. package/dist/ChatHeader/types/index.d.ts +2 -0
  21. package/dist/ChatPreview/ChatPreview.d.cts +2 -2
  22. package/dist/ChatPreview/ChatPreview.d.ts +2 -2
  23. package/dist/ChatPreviewComparison/ChatPreviewComparison.d.cts +2 -2
  24. package/dist/ChatPreviewComparison/ChatPreviewComparison.d.ts +2 -2
  25. package/dist/ChatPreviewLoading/ChatPreviewLoading.d.cts +2 -2
  26. package/dist/ChatPreviewLoading/ChatPreviewLoading.d.ts +2 -2
  27. package/dist/Container/Container.d.cts +176 -176
  28. package/dist/Container/Container.d.ts +176 -176
  29. package/dist/DesignTokens/DesignTokensComponent.d.cts +2 -2
  30. package/dist/DesignTokens/DesignTokensComponent.d.ts +2 -2
  31. package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.cts +2 -2
  32. package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.ts +2 -2
  33. package/dist/FloatingButton/FloatingButton.cjs +2 -1
  34. package/dist/FloatingButton/FloatingButton.d.cts +4 -3
  35. package/dist/FloatingButton/FloatingButton.d.ts +4 -3
  36. package/dist/FloatingButton/FloatingButton.js +2 -1
  37. package/dist/FloatingButton/components/Container.cjs +2 -2
  38. package/dist/FloatingButton/components/Container.js +2 -2
  39. package/dist/FloatingButton/hooks/useGetContainerProperties.cjs +2 -2
  40. package/dist/FloatingButton/hooks/useGetContainerProperties.js +2 -2
  41. package/dist/FloatingButton/types/types.cjs +4 -4
  42. package/dist/FloatingButton/types/types.d.cts +8 -4
  43. package/dist/FloatingButton/types/types.d.ts +8 -4
  44. package/dist/FloatingButton/types/types.js +4 -4
  45. package/dist/FloatingChat/FloatingChat.cjs +106 -39
  46. package/dist/FloatingChat/FloatingChat.d.cts +3 -2
  47. package/dist/FloatingChat/FloatingChat.d.ts +3 -2
  48. package/dist/FloatingChat/FloatingChat.js +108 -41
  49. package/dist/FloatingChat/components/AgentMessage.cjs +3 -2
  50. package/dist/FloatingChat/components/AgentMessage.js +3 -2
  51. package/dist/FloatingChat/components/ChatMessages.cjs +59 -41
  52. package/dist/FloatingChat/components/ChatMessages.js +58 -40
  53. package/dist/FloatingChat/components/Layout.cjs +2 -2
  54. package/dist/FloatingChat/components/Layout.js +2 -2
  55. package/dist/FloatingChat/components/ModalSheet.cjs +184 -0
  56. package/dist/FloatingChat/components/ModalSheet.js +182 -0
  57. package/dist/FloatingChat/components/SalesAgentProductCardsCarousel.cjs +3 -2
  58. package/dist/FloatingChat/components/SalesAgentProductCardsCarousel.js +3 -2
  59. package/dist/FloatingChat/components/index.cjs +1 -0
  60. package/dist/FloatingChat/components/index.js +1 -0
  61. package/dist/FloatingChat/hooks/useChatSuggestions.cjs +25 -0
  62. package/dist/FloatingChat/hooks/useChatSuggestions.js +24 -0
  63. package/dist/FloatingChat/hooks/useFilteredChatMessages.cjs +24 -0
  64. package/dist/FloatingChat/hooks/useFilteredChatMessages.js +23 -0
  65. package/dist/FloatingChat/hooks/usePreventScroll.cjs +117 -0
  66. package/dist/FloatingChat/hooks/usePreventScroll.js +116 -0
  67. package/dist/FloatingChat/hooks/useSnapCalculator.cjs +37 -0
  68. package/dist/FloatingChat/hooks/useSnapCalculator.js +35 -0
  69. package/dist/FloatingChat/hooks/useSnapControl.cjs +82 -0
  70. package/dist/FloatingChat/hooks/useSnapControl.js +81 -0
  71. package/dist/FloatingChat/hooks/useSnapSetup.cjs +59 -0
  72. package/dist/FloatingChat/hooks/useSnapSetup.js +58 -0
  73. package/dist/FloatingChat/types/types.d.cts +4 -0
  74. package/dist/FloatingChat/types/types.d.ts +4 -0
  75. package/dist/Image/Image.d.cts +2 -2
  76. package/dist/Image/Image.d.ts +2 -2
  77. package/dist/ImageGallery/ImageGallery.d.cts +2 -2
  78. package/dist/ImageGallery/ImageGallery.d.ts +2 -2
  79. package/dist/MarkdownProcessor/MarkdownProcessor.d.cts +2 -2
  80. package/dist/MarkdownProcessor/MarkdownProcessor.d.ts +2 -2
  81. package/dist/PromptButton/PromptButton.d.cts +2 -2
  82. package/dist/PromptButton/PromptButton.d.ts +2 -2
  83. package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.cts +2 -2
  84. package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.ts +2 -2
  85. package/dist/PromptCarousel/PromptCarousel.cjs +0 -1
  86. package/dist/PromptCarousel/PromptCarousel.d.cts +2 -2
  87. package/dist/PromptCarousel/PromptCarousel.d.ts +2 -2
  88. package/dist/PromptCarousel/PromptCarousel.js +0 -1
  89. package/dist/ReviewCard/ReviewCard.d.cts +2 -2
  90. package/dist/ReviewCard/ReviewCard.d.ts +2 -2
  91. package/dist/ReviewCard/components/index.d.cts +6 -6
  92. package/dist/ReviewCard/components/index.d.ts +6 -6
  93. package/dist/SalesAgentProductCard/SalesAgentProductCard.d.cts +2 -2
  94. package/dist/SalesAgentProductCard/SalesAgentProductCard.d.ts +2 -2
  95. package/dist/SalesAgentProductCard/components/index.d.cts +2 -2
  96. package/dist/SalesAgentProductCard/components/index.d.ts +8 -8
  97. package/dist/SocialProof/SocialProof.cjs +9 -2
  98. package/dist/SocialProof/SocialProof.d.cts +2 -2
  99. package/dist/SocialProof/SocialProof.d.ts +2 -2
  100. package/dist/SocialProof/SocialProof.js +9 -2
  101. package/dist/SocialProof/hooks/index.cjs +1 -0
  102. package/dist/SocialProof/hooks/index.js +3 -0
  103. package/dist/SocialProof/hooks/useSocialProofCount.cjs +48 -0
  104. package/dist/SocialProof/hooks/useSocialProofCount.d.cts +15 -0
  105. package/dist/SocialProof/hooks/useSocialProofCount.d.ts +15 -0
  106. package/dist/SocialProof/hooks/useSocialProofCount.js +46 -0
  107. package/dist/SocialProof/index.cjs +5 -1
  108. package/dist/SocialProof/index.d.cts +3 -2
  109. package/dist/SocialProof/index.d.ts +3 -2
  110. package/dist/SocialProof/index.js +4 -2
  111. package/dist/SocialProof/types/types.cjs +8 -1
  112. package/dist/SocialProof/types/types.d.cts +16 -6
  113. package/dist/SocialProof/types/types.d.ts +16 -6
  114. package/dist/SocialProof/types/types.js +7 -1
  115. package/dist/Stack/Stack.d.cts +2 -2
  116. package/dist/TitledPromptCarousel/TitledPromptCarousel.d.cts +2 -2
  117. package/dist/TitledPromptCarousel/TitledPromptCarousel.d.ts +2 -2
  118. package/dist/TypingAnimation/TypingAnimation.d.cts +2 -2
  119. package/dist/TypingAnimation/TypingAnimation.d.ts +2 -2
  120. package/dist/Typography/Typography.d.cts +4 -4
  121. package/dist/Typography/Typography.d.ts +4 -4
  122. package/dist/WidgetTextField/WidgetTextField.d.cts +2 -2
  123. package/dist/WidgetTextField/WidgetTextField.d.ts +2 -2
  124. package/dist/WidgetWrapper/WidgetWrapper.d.cts +2 -2
  125. package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.cts +2 -2
  126. package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.ts +2 -2
  127. package/dist/styles.css +1 -1
  128. package/package.json +1 -1
  129. package/src/components/ChatFooter/hooks/useGetContainerProperties.ts +2 -2
  130. package/src/components/ChatHeader/ChatHeader.tsx +2 -0
  131. package/src/components/ChatHeader/components/Handle.tsx +29 -1
  132. package/src/components/ChatHeader/types/index.ts +3 -0
  133. package/src/components/FloatingButton/FloatingButton.tsx +2 -0
  134. package/src/components/FloatingButton/components/Container.tsx +3 -0
  135. package/src/components/FloatingButton/hooks/useGetContainerProperties.ts +2 -1
  136. package/src/components/FloatingButton/types/types.ts +9 -4
  137. package/src/components/FloatingChat/FloatingChat.tsx +160 -59
  138. package/src/components/FloatingChat/components/AgentMessage.tsx +3 -0
  139. package/src/components/FloatingChat/components/ChatMessages.tsx +25 -0
  140. package/src/components/FloatingChat/components/Layout.tsx +2 -2
  141. package/src/components/FloatingChat/components/ModalSheet.tsx +288 -0
  142. package/src/components/FloatingChat/components/SalesAgentProductCardsCarousel.tsx +7 -2
  143. package/src/components/FloatingChat/components/index.ts +3 -0
  144. package/src/components/FloatingChat/hooks/useChatSuggestions.ts +49 -0
  145. package/src/components/FloatingChat/hooks/useFilteredChatMessages.ts +43 -0
  146. package/src/components/FloatingChat/hooks/usePreventScroll.ts +207 -0
  147. package/src/components/FloatingChat/hooks/useSnapCalculator.ts +41 -0
  148. package/src/components/FloatingChat/hooks/useSnapControl.ts +131 -0
  149. package/src/components/FloatingChat/hooks/useSnapSetup.ts +106 -0
  150. package/src/components/FloatingChat/types/types.ts +4 -0
  151. package/src/components/PromptCarousel/PromptCarousel.tsx +0 -1
  152. package/src/components/SocialProof/SocialProof.tsx +8 -2
  153. package/src/components/SocialProof/__tests__/SocialProof.test.tsx +66 -17
  154. package/src/components/SocialProof/hooks/index.ts +2 -0
  155. package/src/components/SocialProof/hooks/useSocialProofCount.ts +67 -0
  156. package/src/components/SocialProof/index.ts +2 -1
  157. package/src/components/SocialProof/types/types.ts +18 -6
@@ -2,12 +2,15 @@ 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 { SocialProof } from '../SocialProof';
5
- import { DynamicLayout } from '../types/types';
5
+ import { DynamicLayout, PageVariant } from '../types/types';
6
6
  import { ImageGalleryLayout } from '../../ImageGallery/types/types';
7
7
  import { PromptButtonVariant } from '../../PromptButton/types';
8
8
  import { PromptCarouselRows } from '../../PromptCarousel/types/types';
9
9
  import { WidgetWrapperVariant } from '../../WidgetWrapper/types/types';
10
10
  import { Theme } from '../../Tokens';
11
+ import { SOCIAL_PROOF_COUNT_KEY } from '../hooks';
12
+
13
+ const COUNT_KEY_MOCK = 'test-social-proof';
11
14
 
12
15
  const mockUseCheckIsMobile = vi.fn(() => ({ isMobile: false, viewportWidth: 1024 }));
13
16
  vi.mock('../../utils/useCheckIsMobile', () => ({
@@ -26,12 +29,35 @@ vi.mock('src/components/utils/useGetContentSize', () => ({
26
29
  }),
27
30
  }));
28
31
 
32
+ const localStorageMock = (() => {
33
+ let store: Record<string, string> = {};
34
+ return {
35
+ getItem: (key: string) => store[key] || null,
36
+ setItem: (key: string, value: string) => {
37
+ store[key] = value.toString();
38
+ },
39
+ removeItem: (key: string) => {
40
+ delete store[key];
41
+ },
42
+ clear: () => {
43
+ store = {};
44
+ },
45
+ };
46
+ })();
47
+
48
+ Object.defineProperty(window, 'localStorage', {
49
+ value: localStorageMock,
50
+ });
51
+
29
52
  describe('SocialProof', () => {
30
53
  const defaultProps = {
31
- baseProps: {},
54
+ baseProps: {
55
+ id: 'test-social-proof',
56
+ pageVariant: PageVariant.PageVisit,
57
+ countKey: COUNT_KEY_MOCK,
58
+ },
32
59
  widgetContentProps: {
33
60
  titleLabel: 'Shopping Assistant',
34
- numberOfCustomersText: '114 customers',
35
61
  customerQueryText: 'asked which products are best for gifting...',
36
62
  primaryButtonText: 'This is a prompt button',
37
63
  secondaryButtonTitleText: 'What else are customers asking?',
@@ -61,14 +87,37 @@ describe('SocialProof', () => {
61
87
  beforeEach(() => {
62
88
  vi.clearAllMocks();
63
89
  mockUseCheckIsMobile.mockReturnValue({ isMobile: false, viewportWidth: 1024 });
90
+ localStorageMock.clear();
64
91
  });
65
92
 
66
93
  describe('Basic rendering', () => {
67
- it('should render with default props', () => {
94
+ it('should render with default props', async () => {
68
95
  render(<SocialProof {...defaultProps} />);
69
- expect(screen.getByText('114 customers')).toBeInTheDocument();
96
+ // Customer count should be between 100-200 and formatted as "{number} customers"
97
+ const customerCountText = screen.getByText(/\d+ customers/);
98
+ expect(customerCountText).toBeInTheDocument();
99
+ const match = customerCountText.textContent?.match(/(\d+)/);
100
+ if (match) {
101
+ const count = parseInt(match[1], 10);
102
+ expect(count).toBeGreaterThanOrEqual(100);
103
+ expect(count).toBeLessThanOrEqual(200);
104
+ }
70
105
  expect(screen.getByText('asked which products are best for gifting...')).toBeInTheDocument();
71
106
  expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
107
+
108
+ // Verify persistence of customer count in localStorage:
109
+ await waitFor(() => {
110
+ const storedData = localStorageMock.getItem(SOCIAL_PROOF_COUNT_KEY);
111
+ expect(storedData).not.toBeNull();
112
+ if (storedData) {
113
+ const customerCountMap = JSON.parse(storedData);
114
+ expect(customerCountMap).toHaveProperty(PageVariant.PageVisit);
115
+ expect(customerCountMap[PageVariant.PageVisit]).toHaveProperty(COUNT_KEY_MOCK);
116
+ const storedCount = customerCountMap[PageVariant.PageVisit][COUNT_KEY_MOCK];
117
+ expect(storedCount).toBeGreaterThanOrEqual(100);
118
+ expect(storedCount).toBeLessThanOrEqual(200);
119
+ }
120
+ });
72
121
  });
73
122
 
74
123
  it('should apply id attribute when provided', () => {
@@ -124,7 +173,7 @@ describe('SocialProof', () => {
124
173
  widgetStyleProps={{ imageGalleryLayout: ImageGalleryLayout.FOUR_GRID }}
125
174
  />,
126
175
  );
127
- expect(screen.getByText('114 customers')).toBeInTheDocument();
176
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
128
177
  expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
129
178
  });
130
179
 
@@ -135,7 +184,7 @@ describe('SocialProof', () => {
135
184
  widgetStyleProps={{ imageGalleryLayout: ImageGalleryLayout.FOUR_HORIZONTAL }}
136
185
  />,
137
186
  );
138
- expect(screen.getByText('114 customers')).toBeInTheDocument();
187
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
139
188
  expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
140
189
  });
141
190
 
@@ -146,7 +195,7 @@ describe('SocialProof', () => {
146
195
  widgetStyleProps={{ imageGalleryLayout: ImageGalleryLayout.SINGLE }}
147
196
  />,
148
197
  );
149
- expect(screen.getByText('114 customers')).toBeInTheDocument();
198
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
150
199
  expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
151
200
  });
152
201
 
@@ -158,7 +207,7 @@ describe('SocialProof', () => {
158
207
  widgetStyleProps={{ imageGalleryLayout: ImageGalleryLayout.FOUR_GRID }}
159
208
  />,
160
209
  );
161
- expect(screen.getByText('114 customers')).toBeInTheDocument();
210
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
162
211
  expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
163
212
  });
164
213
 
@@ -172,7 +221,7 @@ describe('SocialProof', () => {
172
221
  }}
173
222
  />,
174
223
  );
175
- expect(screen.getByText('114 customers')).toBeInTheDocument();
224
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
176
225
  expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
177
226
  });
178
227
  });
@@ -199,7 +248,7 @@ describe('SocialProof', () => {
199
248
  widgetStyleProps={{ hideImage: false, imageGalleryLayout: ImageGalleryLayout.FOUR_GRID }}
200
249
  />,
201
250
  );
202
- expect(screen.getByText('114 customers')).toBeInTheDocument();
251
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
203
252
  });
204
253
 
205
254
  it('should hide textfield when hideTextField is true', () => {
@@ -311,7 +360,7 @@ describe('SocialProof', () => {
311
360
  widgetStyleProps={{ theme, imageGalleryLayout: ImageGalleryLayout.FOUR_GRID }}
312
361
  />,
313
362
  );
314
- expect(screen.getByText('114 customers')).toBeInTheDocument();
363
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
315
364
  unmount();
316
365
  });
317
366
  });
@@ -331,7 +380,7 @@ describe('SocialProof', () => {
331
380
  widgetStyleProps={{ variant, imageGalleryLayout: ImageGalleryLayout.FOUR_GRID }}
332
381
  />,
333
382
  );
334
- expect(screen.getByText('114 customers')).toBeInTheDocument();
383
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
335
384
  unmount();
336
385
  });
337
386
  });
@@ -416,7 +465,7 @@ describe('SocialProof', () => {
416
465
  }}
417
466
  />,
418
467
  );
419
- expect(screen.getByText('114 customers')).toBeInTheDocument();
468
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
420
469
  });
421
470
 
422
471
  it('should render with dynamicLayout WIDE', () => {
@@ -429,7 +478,7 @@ describe('SocialProof', () => {
429
478
  }}
430
479
  />,
431
480
  );
432
- expect(screen.getByText('114 customers')).toBeInTheDocument();
481
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
433
482
  });
434
483
  });
435
484
 
@@ -450,7 +499,7 @@ describe('SocialProof', () => {
450
499
  widgetEventProps={{ handleTextFieldClick: vi.fn() }}
451
500
  />,
452
501
  );
453
- expect(screen.getByText('114 customers')).toBeInTheDocument();
502
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
454
503
  });
455
504
 
456
505
  it('should render with empty secondaryButtonTexts array', () => {
@@ -463,7 +512,7 @@ describe('SocialProof', () => {
463
512
  }}
464
513
  />,
465
514
  );
466
- expect(screen.getByText('114 customers')).toBeInTheDocument();
515
+ expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
467
516
  });
468
517
  });
469
518
  });
@@ -0,0 +1,2 @@
1
+ export { useSocialProofCount } from './useSocialProofCount';
2
+ export { SOCIAL_PROOF_COUNT_KEY } from './useSocialProofCount';
@@ -0,0 +1,67 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { PageVariant } from '../types/types';
3
+
4
+ const RANDOM_NUMBER_MIN = 100;
5
+ const RANDOM_NUMBER_MAX = 200;
6
+ export const SOCIAL_PROOF_COUNT_KEY = 'v3_social_proof_values';
7
+
8
+ type SocialProofCount = Record<string, Record<string, number>>;
9
+
10
+ interface UseSocialProofCountParams {
11
+ pageVariant?: PageVariant;
12
+ countKey?: string;
13
+ id?: string;
14
+ }
15
+
16
+ export const useSocialProofCount = ({
17
+ pageVariant,
18
+ countKey,
19
+ id,
20
+ }: UseSocialProofCountParams): string => {
21
+ const [customerCount, setCustomerCount] = useState<number>(() =>
22
+ Math.floor(Math.random() * (RANDOM_NUMBER_MAX - RANDOM_NUMBER_MIN + 1) + RANDOM_NUMBER_MIN),
23
+ );
24
+
25
+ useEffect(() => {
26
+ const variant = pageVariant || PageVariant.PageVisit;
27
+ const key = countKey || id || 'default';
28
+
29
+ try {
30
+ const storedData = localStorage.getItem(SOCIAL_PROOF_COUNT_KEY);
31
+ let customerCountMap: SocialProofCount = {};
32
+
33
+ if (storedData) {
34
+ try {
35
+ customerCountMap = JSON.parse(storedData) as SocialProofCount;
36
+ } catch (parseError) {
37
+ console.warn('Failed to parse social proof count from localStorage:', parseError);
38
+ return;
39
+ }
40
+ }
41
+
42
+ if (customerCountMap[variant]?.[key]) {
43
+ setCustomerCount(customerCountMap[variant][key]);
44
+ } else {
45
+ const randomCount = Math.floor(
46
+ Math.random() * (RANDOM_NUMBER_MAX - RANDOM_NUMBER_MIN + 1) + RANDOM_NUMBER_MIN,
47
+ );
48
+
49
+ if (!customerCountMap[variant]) {
50
+ customerCountMap[variant] = {};
51
+ }
52
+ customerCountMap[variant][key] = randomCount;
53
+
54
+ try {
55
+ localStorage.setItem(SOCIAL_PROOF_COUNT_KEY, JSON.stringify(customerCountMap));
56
+ setCustomerCount(randomCount);
57
+ } catch (storageError) {
58
+ console.warn('Failed to save social proof count to localStorage:', storageError);
59
+ }
60
+ }
61
+ } catch (error) {
62
+ console.warn('Error managing social proof count:', error);
63
+ }
64
+ }, [pageVariant, countKey, id]);
65
+
66
+ return `${customerCount} customers`;
67
+ };
@@ -1,3 +1,4 @@
1
1
  export { SocialProof } from './SocialProof';
2
2
  export type { SocialProofProps } from './types/types';
3
- export { DynamicLayout } from './types/types';
3
+ export { DynamicLayout, PageVariant } from './types/types';
4
+ export { useSocialProofCount } from './hooks';
@@ -9,6 +9,12 @@ export enum DynamicLayout {
9
9
  WIDE = 'wide',
10
10
  }
11
11
 
12
+ export enum PageVariant {
13
+ PLP = 'PLP',
14
+ PDP = 'PDP',
15
+ PageVisit = 'PageVisit',
16
+ }
17
+
12
18
  /**
13
19
  * Base props for the SocialProof component container.
14
20
  *
@@ -34,6 +40,18 @@ export type BaseProps = {
34
40
  * Inline styles to apply to the container.
35
41
  */
36
42
  style?: React.CSSProperties;
43
+
44
+ /**
45
+ * Page variant for localStorage persistence of customer counts (PLP, PDP, or PageVisit).
46
+ */
47
+ pageVariant?: PageVariant;
48
+
49
+ /**
50
+ * Specific identifier for the pageVariant (e.g., productId for PDP, plpId for PLP, category for PageVisit).
51
+ * Used as the key for localStorage persistence.
52
+ * Falls back to the `id` prop if not provided.
53
+ */
54
+ countKey?: string;
37
55
  };
38
56
 
39
57
  /**
@@ -53,12 +71,6 @@ export type WidgetContentProps = {
53
71
  */
54
72
  titleLabel: string;
55
73
 
56
- /**
57
- * Text displaying the number of customers (e.g., "114 customers").
58
- * Displayed in the headline section.
59
- */
60
- numberOfCustomersText?: string;
61
-
62
74
  /**
63
75
  * Text displaying what customers asked (e.g., "asked which products are best for gifting...").
64
76
  * Displayed in the headline section alongside the customer count.