@envive-ai/react-toolkit-v3 0.3.26 → 0.3.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/dist/AnimatedText/AnimatedText.d.cts +3 -3
  2. package/dist/AnimatedText/AnimatedText.d.ts +3 -3
  3. package/dist/CSSVariablesEditor/CssVariablesEditorComponent.d.ts +2 -2
  4. package/dist/Carousel/Carousel.d.cts +2 -2
  5. package/dist/Carousel/Carousel.d.ts +2 -2
  6. package/dist/ChatFooter/ChatFooter.cjs +1 -0
  7. package/dist/ChatFooter/ChatFooter.d.cts +2 -2
  8. package/dist/ChatFooter/ChatFooter.d.ts +2 -2
  9. package/dist/ChatFooter/ChatFooter.js +1 -0
  10. package/dist/ChatFooter/components/Layout.cjs +2 -2
  11. package/dist/ChatFooter/components/Layout.d.cts +1 -0
  12. package/dist/ChatFooter/components/Layout.d.ts +1 -0
  13. package/dist/ChatFooter/components/Layout.js +2 -2
  14. package/dist/ChatFooter/components/index.d.cts +3 -2
  15. package/dist/ChatFooter/components/index.d.ts +6 -5
  16. package/dist/ChatHeader/ChatHeader.d.cts +2 -2
  17. package/dist/ChatHeader/ChatHeader.d.ts +2 -2
  18. package/dist/ChatPreview/ChatPreview.d.cts +2 -2
  19. package/dist/ChatPreview/ChatPreview.d.ts +2 -2
  20. package/dist/ChatPreviewComparison/ChatPreviewComparison.d.cts +2 -2
  21. package/dist/ChatPreviewComparison/ChatPreviewComparison.d.ts +2 -2
  22. package/dist/ChatPreviewLoading/ChatPreviewLoading.d.cts +2 -2
  23. package/dist/ChatPreviewLoading/ChatPreviewLoading.d.ts +2 -2
  24. package/dist/Container/Container.d.cts +175 -175
  25. package/dist/Container/Container.d.ts +175 -175
  26. package/dist/DesignTokens/DesignTokensComponent.d.cts +2 -2
  27. package/dist/DesignTokens/DesignTokensComponent.d.ts +2 -2
  28. package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.cts +2 -2
  29. package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.ts +2 -2
  30. package/dist/DocumentRetrievalCard/components/ViewArticleButton.cjs +1 -1
  31. package/dist/DocumentRetrievalCard/components/ViewArticleButton.js +1 -1
  32. package/dist/FloatingButton/FloatingButton.d.cts +2 -2
  33. package/dist/FloatingButton/FloatingButton.d.ts +2 -2
  34. package/dist/FloatingChat/FloatingChat.d.cts +2 -2
  35. package/dist/FloatingChat/FloatingChat.d.ts +2 -2
  36. package/dist/FloatingChat/components/SalesAgentBadgeContent.cjs +5 -1
  37. package/dist/FloatingChat/components/SalesAgentBadgeContent.js +5 -1
  38. package/dist/FloatingChat/components/SalesAgentProductCardsCarousel.cjs +2 -1
  39. package/dist/FloatingChat/components/SalesAgentProductCardsCarousel.js +2 -1
  40. package/dist/FullPageSalesAgent/FullPageSalesAgent.cjs +89 -25
  41. package/dist/FullPageSalesAgent/FullPageSalesAgent.d.cts +5 -7
  42. package/dist/FullPageSalesAgent/FullPageSalesAgent.d.ts +5 -7
  43. package/dist/FullPageSalesAgent/FullPageSalesAgent.js +90 -26
  44. package/dist/FullPageSalesAgent/components/Layout.cjs +34 -27
  45. package/dist/FullPageSalesAgent/components/Layout.js +34 -27
  46. package/dist/FullPageSalesAgent/components/WelcomeOverlay.cjs +102 -0
  47. package/dist/FullPageSalesAgent/components/WelcomeOverlay.js +100 -0
  48. package/dist/FullPageSalesAgent/components/index.cjs +1 -0
  49. package/dist/FullPageSalesAgent/components/index.js +1 -0
  50. package/dist/FullPageSalesAgent/hooks/useGetFooterStyles.cjs +16 -6
  51. package/dist/FullPageSalesAgent/hooks/useGetFooterStyles.js +16 -6
  52. package/dist/FullPageSalesAgent/hooks/useWelcomeOverlayProducts.cjs +43 -0
  53. package/dist/FullPageSalesAgent/hooks/useWelcomeOverlayProducts.js +41 -0
  54. package/dist/Image/Image.d.cts +2 -2
  55. package/dist/ImageGallery/ImageGallery.d.cts +2 -2
  56. package/dist/ImageGallery/ImageGallery.d.ts +2 -2
  57. package/dist/MarkdownProcessor/MarkdownProcessor.d.cts +2 -2
  58. package/dist/MarkdownProcessor/MarkdownProcessor.d.ts +2 -2
  59. package/dist/Message/components/LinkButton.cjs +1 -1
  60. package/dist/Message/components/LinkButton.js +1 -1
  61. package/dist/ProductCard/ProductCard.d.cts +2 -2
  62. package/dist/ProductCard/ProductCard.d.ts +2 -2
  63. package/dist/PromptButton/PromptButton.d.cts +2 -2
  64. package/dist/PromptButton/PromptButton.d.ts +2 -2
  65. package/dist/PromptButton/hooks/useGetLayoutBaseProperties.cjs +1 -1
  66. package/dist/PromptButton/hooks/useGetLayoutBaseProperties.js +1 -1
  67. package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.cts +2 -2
  68. package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.ts +2 -2
  69. package/dist/PromptCarousel/PromptCarousel.d.cts +2 -2
  70. package/dist/PromptCarousel/PromptCarousel.d.ts +2 -2
  71. package/dist/ReviewCard/ReviewCard.d.cts +2 -2
  72. package/dist/ReviewCard/ReviewCard.d.ts +2 -2
  73. package/dist/ReviewCard/components/index.d.cts +6 -6
  74. package/dist/ReviewCard/components/index.d.ts +6 -6
  75. package/dist/SalesAgentProductCard/SalesAgentProductCard.d.cts +2 -2
  76. package/dist/SalesAgentProductCard/SalesAgentProductCard.d.ts +2 -2
  77. package/dist/SalesAgentProductCard/components/Price.cjs +2 -2
  78. package/dist/SalesAgentProductCard/components/Price.js +2 -2
  79. package/dist/SalesAgentProductCard/components/Rate.cjs +1 -1
  80. package/dist/SalesAgentProductCard/components/Rate.js +1 -1
  81. package/dist/SalesAgentProductCard/components/index.d.cts +8 -8
  82. package/dist/SalesAgentProductCard/components/index.d.ts +8 -8
  83. package/dist/SocialProof/SocialProof.cjs +4 -3
  84. package/dist/SocialProof/SocialProof.d.cts +2 -2
  85. package/dist/SocialProof/SocialProof.d.ts +2 -2
  86. package/dist/SocialProof/SocialProof.js +4 -3
  87. package/dist/SocialProof/components/Headline.cjs +1 -1
  88. package/dist/SocialProof/components/Headline.js +1 -1
  89. package/dist/SocialProof/components/LayoutSingle.cjs +3 -4
  90. package/dist/SocialProof/components/LayoutSingle.js +3 -4
  91. package/dist/SocialProof/hooks/useSocialProofCount.cjs +3 -2
  92. package/dist/SocialProof/hooks/useSocialProofCount.d.cts +2 -0
  93. package/dist/SocialProof/hooks/useSocialProofCount.d.ts +2 -0
  94. package/dist/SocialProof/hooks/useSocialProofCount.js +3 -2
  95. package/dist/SocialProof/types/types.d.cts +5 -0
  96. package/dist/SocialProof/types/types.d.ts +5 -0
  97. package/dist/SparkleAnimation/SparkleAnimation.d.cts +2 -2
  98. package/dist/SparkleAnimation/SparkleAnimation.d.ts +2 -2
  99. package/dist/Stack/Stack.d.cts +2 -2
  100. package/dist/Stack/Stack.d.ts +2 -2
  101. package/dist/TextField/TextField.cjs +3 -0
  102. package/dist/TextField/TextField.js +3 -0
  103. package/dist/TextField/hooks/useVoiceInput.cjs +9 -1
  104. package/dist/TextField/hooks/useVoiceInput.js +9 -1
  105. package/dist/TextField/types/index.d.cts +12 -0
  106. package/dist/TextField/types/index.d.ts +12 -0
  107. package/dist/TitledPromptCarousel/TitledPromptCarousel.d.cts +2 -2
  108. package/dist/TitledPromptCarousel/TitledPromptCarousel.d.ts +2 -2
  109. package/dist/TypingAnimation/TypingAnimation.d.cts +2 -2
  110. package/dist/TypingAnimation/TypingAnimation.d.ts +2 -2
  111. package/dist/Typography/Typography.d.cts +4 -4
  112. package/dist/Typography/Typography.d.ts +4 -4
  113. package/dist/WidgetTextField/WidgetTextField.d.cts +2 -2
  114. package/dist/WidgetTextField/WidgetTextField.d.ts +2 -2
  115. package/dist/WidgetWrapper/WidgetWrapper.d.cts +2 -2
  116. package/dist/WidgetWrapper/WidgetWrapper.d.ts +2 -2
  117. package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.cts +2 -2
  118. package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.ts +2 -2
  119. package/dist/styles.css +1 -1
  120. package/package.json +1 -1
  121. package/src/components/ChatFooter/ChatFooter.tsx +1 -0
  122. package/src/components/ChatFooter/components/Layout.tsx +3 -1
  123. package/src/components/FloatingChat/components/SalesAgentBadgeContent.tsx +8 -0
  124. package/src/components/FloatingChat/components/SalesAgentProductCardsCarousel.tsx +3 -0
  125. package/src/components/FullPageSalesAgent/FullPageSalesAgent.tsx +139 -49
  126. package/src/components/FullPageSalesAgent/components/Layout.tsx +10 -3
  127. package/src/components/FullPageSalesAgent/components/WelcomeOverlay.tsx +121 -0
  128. package/src/components/FullPageSalesAgent/components/index.ts +2 -0
  129. package/src/components/FullPageSalesAgent/hooks/useGetFooterStyles.ts +15 -5
  130. package/src/components/FullPageSalesAgent/hooks/useWelcomeOverlayProducts.ts +51 -0
  131. package/src/components/PromptButton/hooks/useGetLayoutBaseProperties.ts +3 -1
  132. package/src/components/SalesAgentProductCard/components/Price.tsx +2 -2
  133. package/src/components/SalesAgentProductCard/components/Rate.tsx +1 -1
  134. package/src/components/SocialProof/SocialProof.tsx +4 -2
  135. package/src/components/SocialProof/components/Headline.tsx +1 -1
  136. package/src/components/SocialProof/components/LayoutSingle.tsx +6 -5
  137. package/src/components/SocialProof/hooks/useSocialProofCount.ts +8 -1
  138. package/src/components/SocialProof/types/types.ts +6 -0
  139. package/src/components/TextField/TextField.tsx +10 -2
  140. package/src/components/TextField/__tests__/VoiceInputButton.test.tsx +22 -58
  141. package/src/components/TextField/hooks/useVoiceInput.ts +8 -0
  142. package/src/components/TextField/types/index.ts +12 -0
@@ -9,13 +9,16 @@ type SocialProofCount = Record<string, Record<string, number>>;
9
9
 
10
10
  interface UseSocialProofCountParams {
11
11
  pageVariant?: PageVariant;
12
+ numberOfCustomersText?: string;
12
13
  countKey?: string;
13
14
  id?: string;
14
15
  }
16
+ const DEFAULT_CUSTOMER_TEXT = '{count} customers';
15
17
 
16
18
  export const useSocialProofCount = ({
17
19
  pageVariant,
18
20
  countKey,
21
+ numberOfCustomersText = DEFAULT_CUSTOMER_TEXT,
19
22
  id,
20
23
  }: UseSocialProofCountParams): string => {
21
24
  const [customerCount, setCustomerCount] = useState<number>(() =>
@@ -63,5 +66,9 @@ export const useSocialProofCount = ({
63
66
  }
64
67
  }, [pageVariant, countKey, id]);
65
68
 
66
- return `${customerCount} customers`;
69
+ // For safety ensure that the replacement string occurs in the string for now
70
+ const finalCustomerText = numberOfCustomersText.includes('{count}')
71
+ ? numberOfCustomersText
72
+ : DEFAULT_CUSTOMER_TEXT;
73
+ return finalCustomerText.replace('{count}', customerCount.toString());
67
74
  };
@@ -82,6 +82,12 @@ export type WidgetContentProps = {
82
82
  */
83
83
  customerQueryText?: string;
84
84
 
85
+ /**
86
+ * Text displaying how many customers asked the customerQueryText question (e.g., "123 customers")
87
+ * Utilizes replacement to replace the value {count} with the replaced value
88
+ */
89
+ numberOfCustomersText?: string;
90
+
85
91
  /**
86
92
  * Text label for the primary prompt button.
87
93
  * Displayed prominently in the headline section.
@@ -48,7 +48,7 @@ export const TextField = ({
48
48
  resetValue,
49
49
  );
50
50
 
51
- const handleVoiceTranscript = useCallback(
51
+ const handleVoiceTranscriptCompleted = useCallback(
52
52
  (transcript: string) => {
53
53
  resetValue();
54
54
  handleChange(transcript);
@@ -57,6 +57,13 @@ export const TextField = ({
57
57
  [handleChange, resetValue, onTranscriptionCompleted],
58
58
  );
59
59
 
60
+ const handleVoiceTranscription = useCallback(
61
+ (transcript: string) => {
62
+ handleChange(transcript);
63
+ },
64
+ [handleChange],
65
+ );
66
+
60
67
  const {
61
68
  isListening,
62
69
  handleToggleListening,
@@ -64,7 +71,8 @@ export const TextField = ({
64
71
  browserSupportsSpeechRecognition,
65
72
  } = useVoiceInput({
66
73
  onTranscriptionStarted,
67
- onTranscriptionCompleted: handleVoiceTranscript,
74
+ onTranscriptionCompleted: handleVoiceTranscriptCompleted,
75
+ onTranscription: handleVoiceTranscription,
68
76
  disabled,
69
77
  });
70
78
 
@@ -57,83 +57,62 @@ vi.mock('jotai', () => ({
57
57
  }));
58
58
 
59
59
  describe('useVoiceInput', () => {
60
- // Reset mocks before each test to ensure clean state
61
60
  beforeEach(() => {
62
61
  vi.clearAllMocks();
63
- // Reset the implementation to default successful behavior
64
62
  spies.mockStartListening.mockImplementation(() => Promise.resolve());
63
+ sharedState = '';
65
64
  });
66
65
 
67
66
  describe('Basic initialization', () => {
68
67
  it('should initialize with isListening as false', () => {
69
68
  const { result } = renderHook(() => useVoiceInput({}));
70
- // Voice input should not be active when the hook first mounts
71
69
  expect(result.current.isListening).toBe(false);
72
70
  });
73
71
 
74
72
  it('should report browser supports speech recognition', () => {
75
73
  const { result } = renderHook(() => useVoiceInput({}));
76
- // Check if the browser has speech recognition support
77
74
  expect(result.current.browserSupportsSpeechRecognition).toBe(true);
78
75
  });
79
76
  });
80
77
 
81
- describe('Start listening', () => {
82
- it('should start listening when button is clicked', async () => {
83
- const { result } = renderHook(() => useVoiceInput({}));
84
-
85
- await act(async () => {
86
- // Call handleToggleListening to start listening
87
- result.current.handleToggleListening();
88
- });
78
+ describe('onTranscriptionStarted callback', () => {
79
+ it('should accept onTranscriptionStarted prop', () => {
80
+ const onTranscriptionStarted = vi.fn();
89
81
 
90
- // Verify that listening state changed to active
91
- expect(result.current.isListening).toBe(true);
82
+ renderHook(() =>
83
+ useVoiceInput({
84
+ onTranscriptionStarted,
85
+ }),
86
+ );
92
87
  });
88
+ });
93
89
 
94
- it('should delete previous transcription when starting to listen', async () => {
95
- const { result } = renderHook(() => useVoiceInput({}));
96
-
97
- await act(async () => {
98
- result.current.handleToggleListening();
99
- });
90
+ describe('onTranscription callback', () => {
91
+ it('should accept onTranscription prop', () => {
92
+ const onTranscription = vi.fn();
100
93
 
101
- // Verify resetTranscript was called BEFORE starting new listening session
102
- // This ensures previous transcription is cleared when starting fresh
103
- expect(spies.mockResetTranscript).toHaveBeenCalled();
94
+ renderHook(() =>
95
+ useVoiceInput({
96
+ onTranscription,
97
+ }),
98
+ );
104
99
  });
105
100
  });
106
101
 
107
- describe('Stop listening', () => {
108
- it('should stop listening and call onTranscript with current transcript', async () => {
102
+ describe('onTranscriptionCompleted callback', () => {
103
+ it('should accept onTranscriptionCompleted prop', () => {
109
104
  const onTranscriptionCompleted = vi.fn();
110
105
 
111
- const { result } = renderHook(() =>
106
+ renderHook(() =>
112
107
  useVoiceInput({
113
108
  onTranscriptionCompleted,
114
109
  }),
115
110
  );
116
-
117
- // First toggle: start listening
118
- await act(async () => {
119
- result.current.handleToggleListening();
120
- });
121
-
122
- // Second toggle: stop listening - this should call onTranscript callback
123
- await act(async () => {
124
- result.current.handleToggleListening();
125
- });
126
-
127
- // Verify that stopListening was called to stop speech recognition
128
- expect(spies.mockStopListening).toHaveBeenCalled();
129
- // Verify that the onTranscript callback was called with current transcript
130
- expect(onTranscriptionCompleted).toHaveBeenCalledWith('');
131
111
  });
132
112
  });
133
113
 
134
114
  describe('Mic permission handling', () => {
135
115
  it('should handle mic permission denied error', async () => {
136
- // Configure the mock to throw an error simulating permission denial
137
116
  spies.mockStartListening.mockImplementationOnce(() => {
138
117
  throw new Error('Permission denied');
139
118
  });
@@ -144,43 +123,28 @@ describe('useVoiceInput', () => {
144
123
  result.current.handleToggleListening();
145
124
  });
146
125
 
147
- // The hook should catch the error and set isListening back to false
148
126
  expect(result.current.isListening).toBe(false);
149
127
  });
150
128
 
151
129
  it('should not start listening when disabled', () => {
152
- // When disabled prop is true, the hook should not attempt to start listening
153
130
  const { result } = renderHook(() => useVoiceInput({ disabled: true }));
154
131
 
155
132
  result.current.handleToggleListening();
156
133
 
157
- // isListening should remain false
158
134
  expect(result.current.isListening).toBe(false);
159
- // Verify that startListening was never called
160
135
  expect(spies.mockStartListening).not.toHaveBeenCalled();
161
136
  });
162
137
  });
163
138
 
164
139
  describe('Abort listening', () => {
165
- it('should abort listening and reset state', async () => {
140
+ it('should abort listening when handleAbortListening is called', async () => {
166
141
  const { result } = renderHook(() => useVoiceInput({}));
167
142
 
168
- // Start listening first
169
- await act(async () => {
170
- result.current.handleToggleListening();
171
- });
172
-
173
- expect(result.current.isListening).toBe(true);
174
-
175
- // Call abort to stop listening immediately without collecting transcript
176
143
  await act(async () => {
177
144
  result.current.handleAbortListening();
178
145
  });
179
146
 
180
- // Verify abortListening was called to immediately stop speech recognition
181
147
  expect(spies.mockAbortListening).toHaveBeenCalled();
182
- // Verify state is reset to false
183
- expect(result.current.isListening).toBe(false);
184
148
  });
185
149
  });
186
150
  });
@@ -6,6 +6,7 @@ import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognitio
6
6
  export type UseVoiceInputProps = {
7
7
  onTranscriptionStarted?: () => void;
8
8
  onTranscriptionCompleted?: (transcript: string) => void;
9
+ onTranscription?: (transcript: string) => void;
9
10
  disabled?: boolean;
10
11
  };
11
12
 
@@ -19,6 +20,7 @@ export type UseVoiceInputReturn = {
19
20
  export const useVoiceInput = ({
20
21
  onTranscriptionCompleted,
21
22
  onTranscriptionStarted,
23
+ onTranscription,
22
24
  disabled = false,
23
25
  }: UseVoiceInputProps): UseVoiceInputReturn => {
24
26
  const [listeningToSpeech, setListeningToSpeech] = useAtom(listeningToSpeechAtom);
@@ -78,6 +80,12 @@ export const useVoiceInput = ({
78
80
  }
79
81
  }, [listeningToSpeech]);
80
82
 
83
+ useEffect(() => {
84
+ if (!disabled && listeningToSpeech === 'start' && transcript) {
85
+ onTranscription?.(transcript);
86
+ }
87
+ }, [transcript, listeningToSpeech, disabled, onTranscription]);
88
+
81
89
  return {
82
90
  isListening: listeningToSpeech === 'start',
83
91
  handleToggleListening,
@@ -52,6 +52,18 @@ export type TextFieldProps = {
52
52
  * @default false
53
53
  */
54
54
  enableVoiceInput?: boolean;
55
+ /**
56
+ * Callback function invoked when voice transcription begins.
57
+ */
55
58
  onTranscriptionStarted?: () => void;
59
+ /**
60
+ * Callback function invoked when voice transcription completes.
61
+ * @param transcript - The transcribed text from voice input.
62
+ */
56
63
  onTranscriptionCompleted?: (transcript: string) => void;
64
+ /**
65
+ * Callback function invoked during voice transcription as audio is processed.
66
+ * @param transcript - The current transcribed text from voice input.
67
+ */
68
+ onTranscription?: (transcript: string) => void;
57
69
  };