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

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 (284) 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.cjs +1 -1
  6. package/dist/Carousel/Carousel.d.cts +2 -2
  7. package/dist/Carousel/Carousel.d.ts +2 -2
  8. package/dist/Carousel/Carousel.js +1 -1
  9. package/dist/Carousel/components/Container.cjs +2 -2
  10. package/dist/Carousel/components/Container.js +2 -2
  11. package/dist/ChatFooter/ChatFooter.cjs +7 -3
  12. package/dist/ChatFooter/ChatFooter.d.cts +7 -3
  13. package/dist/ChatFooter/ChatFooter.d.ts +5 -1
  14. package/dist/ChatFooter/ChatFooter.js +7 -3
  15. package/dist/ChatFooter/components/Layout.cjs +2 -2
  16. package/dist/ChatFooter/components/Layout.js +2 -2
  17. package/dist/ChatFooter/components/index.d.cts +10 -6
  18. package/dist/ChatFooter/components/index.d.ts +7 -3
  19. package/dist/ChatFooter/types/types.d.cts +16 -0
  20. package/dist/ChatFooter/types/types.d.ts +16 -0
  21. package/dist/ChatHeader/ChatHeader.cjs +2 -1
  22. package/dist/ChatHeader/ChatHeader.d.cts +2 -2
  23. package/dist/ChatHeader/ChatHeader.d.ts +2 -2
  24. package/dist/ChatHeader/ChatHeader.js +2 -1
  25. package/dist/ChatHeader/components/Handle.cjs +4 -4
  26. package/dist/ChatHeader/components/Handle.js +4 -4
  27. package/dist/ChatHeader/components/Toggle.cjs +3 -3
  28. package/dist/ChatHeader/components/Toggle.js +3 -3
  29. package/dist/ChatHeader/hooks/useGetHandleProperties.cjs +8 -6
  30. package/dist/ChatHeader/hooks/useGetHandleProperties.js +8 -6
  31. package/dist/ChatHeader/hooks/useGetToggleOptionProperties.cjs +1 -1
  32. package/dist/ChatHeader/hooks/useGetToggleOptionProperties.js +1 -1
  33. package/dist/ChatPreview/ChatPreview.cjs +7 -4
  34. package/dist/ChatPreview/ChatPreview.d.cts +2 -2
  35. package/dist/ChatPreview/ChatPreview.js +7 -4
  36. package/dist/ChatPreview/index.d.cts +2 -2
  37. package/dist/ChatPreview/index.d.ts +2 -2
  38. package/dist/ChatPreview/types/types.d.cts +13 -1
  39. package/dist/ChatPreview/types/types.d.ts +13 -1
  40. package/dist/ChatPreviewComparison/ChatPreviewComparison.cjs +7 -4
  41. package/dist/ChatPreviewComparison/ChatPreviewComparison.d.cts +2 -2
  42. package/dist/ChatPreviewComparison/ChatPreviewComparison.d.ts +2 -2
  43. package/dist/ChatPreviewComparison/ChatPreviewComparison.js +7 -4
  44. package/dist/ChatPreviewComparison/components/Headline.cjs +2 -2
  45. package/dist/ChatPreviewComparison/components/Headline.js +2 -2
  46. package/dist/ChatPreviewComparison/components/Layout.cjs +4 -4
  47. package/dist/ChatPreviewComparison/components/Layout.js +4 -4
  48. package/dist/ChatPreviewComparison/components/Message.cjs +2 -2
  49. package/dist/ChatPreviewComparison/components/Message.js +2 -2
  50. package/dist/ChatPreviewComparison/index.d.cts +2 -2
  51. package/dist/ChatPreviewComparison/index.d.ts +2 -2
  52. package/dist/ChatPreviewComparison/types/types.d.cts +13 -1
  53. package/dist/ChatPreviewComparison/types/types.d.ts +13 -1
  54. package/dist/ChatPreviewLoading/ChatPreviewLoading.cjs +7 -2
  55. package/dist/ChatPreviewLoading/ChatPreviewLoading.d.cts +4 -3
  56. package/dist/ChatPreviewLoading/ChatPreviewLoading.d.ts +4 -3
  57. package/dist/ChatPreviewLoading/ChatPreviewLoading.js +7 -2
  58. package/dist/ChatPreviewLoading/types/types.d.cts +4 -0
  59. package/dist/ChatPreviewLoading/types/types.d.ts +4 -0
  60. package/dist/Container/Container.d.cts +172 -172
  61. package/dist/Container/Container.d.ts +172 -172
  62. package/dist/DesignTokens/DesignTokensComponent.d.cts +2 -2
  63. package/dist/DesignTokens/DesignTokensComponent.d.ts +2 -2
  64. package/dist/Disclaimer/components/Container.cjs +2 -2
  65. package/dist/Disclaimer/components/Container.js +2 -2
  66. package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.cts +2 -2
  67. package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.ts +2 -2
  68. package/dist/DocumentRetrievalCard/components/Layout.cjs +2 -2
  69. package/dist/DocumentRetrievalCard/components/Layout.js +2 -2
  70. package/dist/DocumentRetrievalCard/components/ViewArticleButton/components/Icon.cjs +1 -1
  71. package/dist/DocumentRetrievalCard/components/ViewArticleButton/components/Icon.js +1 -1
  72. package/dist/FloatingButton/FloatingButton.d.cts +2 -2
  73. package/dist/FloatingButton/FloatingButton.d.ts +2 -2
  74. package/dist/FloatingChat/FloatingChat.cjs +27 -4
  75. package/dist/FloatingChat/FloatingChat.d.cts +2 -2
  76. package/dist/FloatingChat/FloatingChat.d.ts +2 -2
  77. package/dist/FloatingChat/FloatingChat.js +28 -5
  78. package/dist/FloatingChat/components/AgentMessage.cjs +2 -2
  79. package/dist/FloatingChat/components/AgentMessage.js +2 -2
  80. package/dist/FloatingChat/components/ChatMessages.cjs +1 -1
  81. package/dist/FloatingChat/components/ChatMessages.js +1 -1
  82. package/dist/FloatingChat/components/Layout.cjs +3 -3
  83. package/dist/FloatingChat/components/Layout.js +3 -3
  84. package/dist/FloatingChat/components/ResultsGridView.cjs +1 -1
  85. package/dist/FloatingChat/components/ResultsGridView.js +1 -1
  86. package/dist/FloatingChat/components/SalesAgentBadgeContent.cjs +1 -1
  87. package/dist/FloatingChat/components/SalesAgentBadgeContent.js +1 -1
  88. package/dist/FloatingChat/hooks/useChatSuggestions.cjs +3 -5
  89. package/dist/FloatingChat/hooks/useChatSuggestions.js +4 -6
  90. package/dist/FullPageSalesAgent/FullPageSalesAgent.cjs +25 -3
  91. package/dist/FullPageSalesAgent/FullPageSalesAgent.d.cts +5 -3
  92. package/dist/FullPageSalesAgent/FullPageSalesAgent.d.ts +5 -3
  93. package/dist/FullPageSalesAgent/FullPageSalesAgent.js +26 -4
  94. package/dist/Image/Image.d.cts +2 -2
  95. package/dist/Image/Image.d.ts +2 -2
  96. package/dist/ImageGallery/ImageGallery.d.cts +2 -2
  97. package/dist/ImageGallery/ImageGallery.d.ts +2 -2
  98. package/dist/ImageGallery/components/Layout.cjs +1 -1
  99. package/dist/ImageGallery/components/Layout.js +1 -1
  100. package/dist/MarkdownProcessor/MarkdownProcessor.d.cts +2 -2
  101. package/dist/MarkdownProcessor/MarkdownProcessor.d.ts +2 -2
  102. package/dist/Message/components/LinkButton.cjs +1 -1
  103. package/dist/Message/components/LinkButton.js +1 -1
  104. package/dist/OrderLookupCard/OrderLookupCard.cjs +1 -1
  105. package/dist/OrderLookupCard/OrderLookupCard.js +1 -1
  106. package/dist/ProductCard/ProductCard.cjs +7 -3
  107. package/dist/ProductCard/ProductCard.d.cts +6 -3
  108. package/dist/ProductCard/ProductCard.d.ts +6 -3
  109. package/dist/ProductCard/ProductCard.js +7 -3
  110. package/dist/ProductCard/index.d.cts +2 -2
  111. package/dist/ProductCard/index.d.ts +2 -2
  112. package/dist/ProductCard/types/index.d.cts +7 -1
  113. package/dist/ProductCard/types/index.d.ts +7 -1
  114. package/dist/PromptButton/PromptButton.d.cts +2 -2
  115. package/dist/PromptButton/PromptButton.d.ts +2 -2
  116. package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.cjs +5 -2
  117. package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.cts +6 -3
  118. package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.ts +6 -3
  119. package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.js +5 -2
  120. package/dist/PromptButtonCarouselWithImage/components/PromptButtonsCarousel.cjs +1 -1
  121. package/dist/PromptButtonCarouselWithImage/components/PromptButtonsCarousel.js +1 -1
  122. package/dist/PromptButtonCarouselWithImage/types/types.d.cts +12 -0
  123. package/dist/PromptButtonCarouselWithImage/types/types.d.ts +12 -0
  124. package/dist/PromptCarousel/PromptCarousel.cjs +3 -3
  125. package/dist/PromptCarousel/PromptCarousel.d.cts +2 -2
  126. package/dist/PromptCarousel/PromptCarousel.d.ts +2 -2
  127. package/dist/PromptCarousel/PromptCarousel.js +3 -3
  128. package/dist/ReviewCard/ReviewCard.d.cts +2 -2
  129. package/dist/ReviewCard/ReviewCard.d.ts +2 -2
  130. package/dist/ReviewCard/components/Container.cjs +2 -2
  131. package/dist/ReviewCard/components/Container.js +2 -2
  132. package/dist/ReviewCard/components/Rating.cjs +0 -1
  133. package/dist/ReviewCard/components/Rating.js +0 -1
  134. package/dist/ReviewCard/components/ReadMoreButton.cjs +1 -1
  135. package/dist/ReviewCard/components/ReadMoreButton.js +1 -1
  136. package/dist/ReviewCard/components/index.d.cts +4 -4
  137. package/dist/ReviewCard/components/index.d.ts +6 -6
  138. package/dist/SalesAgentProductCard/SalesAgentProductCard.d.cts +2 -2
  139. package/dist/SalesAgentProductCard/SalesAgentProductCard.d.ts +2 -2
  140. package/dist/SalesAgentProductCard/components/Container.cjs +2 -2
  141. package/dist/SalesAgentProductCard/components/Container.js +2 -2
  142. package/dist/SalesAgentProductCard/components/index.d.cts +6 -6
  143. package/dist/SalesAgentProductCard/components/index.d.ts +8 -8
  144. package/dist/SocialProof/SocialProof.cjs +7 -4
  145. package/dist/SocialProof/SocialProof.d.cts +2 -2
  146. package/dist/SocialProof/SocialProof.js +7 -4
  147. package/dist/SocialProof/components/Headline.cjs +3 -3
  148. package/dist/SocialProof/components/Headline.js +3 -3
  149. package/dist/SocialProof/components/LayoutFourHorizontal.cjs +1 -1
  150. package/dist/SocialProof/components/LayoutFourHorizontal.js +1 -1
  151. package/dist/SocialProof/components/Subheadline.cjs +1 -1
  152. package/dist/SocialProof/components/Subheadline.js +1 -1
  153. package/dist/SocialProof/components/Textfield.cjs +5 -2
  154. package/dist/SocialProof/components/Textfield.js +5 -2
  155. package/dist/SocialProof/index.d.cts +2 -2
  156. package/dist/SocialProof/index.d.ts +2 -2
  157. package/dist/SocialProof/types/types.d.cts +13 -1
  158. package/dist/SocialProof/types/types.d.ts +13 -1
  159. package/dist/SparkleAnimation/SparkleAnimation.d.cts +2 -2
  160. package/dist/SparkleAnimation/SparkleAnimation.d.ts +2 -2
  161. package/dist/Stack/Stack.d.cts +2 -2
  162. package/dist/Stack/Stack.d.ts +2 -2
  163. package/dist/TextField/TextField.cjs +34 -2
  164. package/dist/TextField/TextField.d.cts +5 -1
  165. package/dist/TextField/TextField.d.ts +5 -1
  166. package/dist/TextField/TextField.js +34 -2
  167. package/dist/TextField/components/Layout.cjs +10 -7
  168. package/dist/TextField/components/Layout.js +10 -7
  169. package/dist/TextField/components/VoiceInputButton.cjs +45 -0
  170. package/dist/TextField/components/VoiceInputButton.js +39 -0
  171. package/dist/TextField/components/index.cjs +3 -1
  172. package/dist/TextField/components/index.js +3 -1
  173. package/dist/TextField/hooks/useGetMicButtonContainerProperties.cjs +20 -0
  174. package/dist/TextField/hooks/useGetMicButtonContainerProperties.js +19 -0
  175. package/dist/TextField/hooks/useGetSkeletonProperties.cjs +1 -1
  176. package/dist/TextField/hooks/useGetSkeletonProperties.js +1 -1
  177. package/dist/TextField/hooks/useVoiceInput.cjs +59 -0
  178. package/dist/TextField/hooks/useVoiceInput.js +57 -0
  179. package/dist/TextField/types/index.d.cts +11 -0
  180. package/dist/TextField/types/index.d.ts +11 -0
  181. package/dist/TextField/utils/getLayoutStateProperties.cjs +9 -1
  182. package/dist/TextField/utils/getLayoutStateProperties.js +8 -1
  183. package/dist/TitledPromptCarousel/TitledPromptCarousel.cjs +1 -1
  184. package/dist/TitledPromptCarousel/TitledPromptCarousel.d.cts +2 -2
  185. package/dist/TitledPromptCarousel/TitledPromptCarousel.d.ts +2 -2
  186. package/dist/TitledPromptCarousel/TitledPromptCarousel.js +1 -1
  187. package/dist/Tokens/index.cjs +1 -1
  188. package/dist/Tokens/index.js +1 -1
  189. package/dist/TypingAnimation/TypingAnimation.cjs +8 -4
  190. package/dist/TypingAnimation/TypingAnimation.d.cts +2 -2
  191. package/dist/TypingAnimation/TypingAnimation.js +8 -4
  192. package/dist/TypingAnimation/hooks/useGetTypographyVariant.cjs +1 -1
  193. package/dist/TypingAnimation/hooks/useGetTypographyVariant.js +1 -1
  194. package/dist/TypingAnimation/index.d.cts +2 -2
  195. package/dist/TypingAnimation/index.d.ts +2 -2
  196. package/dist/TypingAnimation/types/index.d.cts +13 -1
  197. package/dist/TypingAnimation/types/index.d.ts +13 -1
  198. package/dist/Typography/Typography.d.cts +4 -4
  199. package/dist/Typography/Typography.d.ts +4 -4
  200. package/dist/WelcomeMessage/components/Container.cjs +2 -2
  201. package/dist/WelcomeMessage/components/Container.js +2 -2
  202. package/dist/WidgetTextField/WidgetTextField.cjs +40 -8
  203. package/dist/WidgetTextField/WidgetTextField.d.cts +7 -3
  204. package/dist/WidgetTextField/WidgetTextField.d.ts +7 -3
  205. package/dist/WidgetTextField/WidgetTextField.js +34 -3
  206. package/dist/WidgetTextField/components/Container.cjs +33 -27
  207. package/dist/WidgetTextField/components/Container.js +33 -27
  208. package/dist/WidgetTextField/components/Icon.cjs +1 -1
  209. package/dist/WidgetTextField/components/Icon.js +1 -1
  210. package/dist/WidgetTextField/hooks/useGetContainerProperties.cjs +5 -3
  211. package/dist/WidgetTextField/hooks/useGetContainerProperties.js +5 -3
  212. package/dist/WidgetTextField/hooks/useGetMicWidgetButtonProperties.cjs +20 -0
  213. package/dist/WidgetTextField/hooks/useGetMicWidgetButtonProperties.js +19 -0
  214. package/dist/WidgetTextField/types/types.d.cts +21 -0
  215. package/dist/WidgetTextField/types/types.d.ts +21 -0
  216. package/dist/WidgetWrapper/WidgetWrapper.d.cts +2 -2
  217. package/dist/WidgetWrapper/WidgetWrapper.d.ts +2 -2
  218. package/dist/WidgetWrapper/hooks/useGetWrapperProperties.cjs +1 -1
  219. package/dist/WidgetWrapper/hooks/useGetWrapperProperties.js +1 -1
  220. package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.cts +2 -2
  221. package/dist/node_modules/jotai/esm/react.cjs +87 -0
  222. package/dist/node_modules/jotai/esm/react.js +88 -2
  223. package/dist/node_modules/jotai/esm/vanilla/internals.cjs +2 -1
  224. package/dist/node_modules/jotai/esm/vanilla/internals.js +1 -1
  225. package/dist/styles.css +1 -1
  226. package/package.json +2 -1
  227. package/src/components/ChatFooter/ChatFooter.tsx +8 -0
  228. package/src/components/ChatFooter/__tests__/ChatFooter.test.tsx +43 -0
  229. package/src/components/ChatFooter/components/TextField.tsx +12 -0
  230. package/src/components/ChatFooter/types/types.ts +17 -0
  231. package/src/components/ChatHeader/ChatHeader.tsx +1 -0
  232. package/src/components/ChatHeader/components/Handle.tsx +7 -2
  233. package/src/components/ChatHeader/hooks/useGetHandleProperties.ts +9 -5
  234. package/src/components/ChatHeader/hooks/useGetToggleOptionProperties.ts +1 -1
  235. package/src/components/ChatHeader/types/index.ts +1 -0
  236. package/src/components/ChatPreview/ChatPreview.tsx +13 -2
  237. package/src/components/ChatPreview/__tests__/ChatPreview.test.tsx +44 -0
  238. package/src/components/ChatPreview/index.ts +1 -1
  239. package/src/components/ChatPreview/types/types.ts +13 -0
  240. package/src/components/ChatPreviewComparison/ChatPreviewComparison.tsx +6 -0
  241. package/src/components/ChatPreviewComparison/__tests__/ChatPreviewComparison.test.tsx +44 -0
  242. package/src/components/ChatPreviewComparison/index.ts +1 -1
  243. package/src/components/ChatPreviewComparison/types/types.ts +13 -0
  244. package/src/components/ChatPreviewLoading/ChatPreviewLoading.tsx +5 -3
  245. package/src/components/ChatPreviewLoading/__tests__/ChatPreviewLoading.test.tsx +40 -0
  246. package/src/components/ChatPreviewLoading/types/types.ts +5 -0
  247. package/src/components/FloatingChat/FloatingChat.tsx +38 -7
  248. package/src/components/FloatingChat/hooks/useChatSuggestions.ts +8 -12
  249. package/src/components/FullPageSalesAgent/FullPageSalesAgent.tsx +32 -1
  250. package/src/components/ProductCard/ProductCard.tsx +7 -0
  251. package/src/components/ProductCard/__tests__/ProductCard.test.tsx +33 -0
  252. package/src/components/ProductCard/index.ts +1 -1
  253. package/src/components/ProductCard/types/index.ts +6 -0
  254. package/src/components/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.tsx +6 -0
  255. package/src/components/PromptButtonCarouselWithImage/__tests__/PromptButtonCarouselWithImage.test.tsx +34 -0
  256. package/src/components/PromptButtonCarouselWithImage/types/types.ts +12 -0
  257. package/src/components/ReviewCard/components/Rating.tsx +0 -1
  258. package/src/components/SocialProof/SocialProof.tsx +6 -0
  259. package/src/components/SocialProof/__tests__/SocialProof.test.tsx +58 -0
  260. package/src/components/SocialProof/components/Textfield.tsx +9 -0
  261. package/src/components/SocialProof/index.ts +1 -1
  262. package/src/components/SocialProof/types/types.ts +13 -0
  263. package/src/components/TextField/TextField.tsx +49 -0
  264. package/src/components/TextField/__tests__/TextField.test.tsx +3 -3
  265. package/src/components/TextField/__tests__/VoiceInputButton.test.tsx +175 -0
  266. package/src/components/TextField/components/Layout.tsx +24 -17
  267. package/src/components/TextField/components/VoiceInputButton.tsx +69 -0
  268. package/src/components/TextField/components/index.ts +2 -0
  269. package/src/components/TextField/hooks/useGetMicButtonContainerProperties.ts +38 -0
  270. package/src/components/TextField/hooks/useGetSkeletonProperties.ts +1 -1
  271. package/src/components/TextField/hooks/useVoiceInput.ts +77 -0
  272. package/src/components/TextField/types/index.ts +11 -0
  273. package/src/components/TextField/utils/getLayoutStateProperties.ts +8 -0
  274. package/src/components/TypingAnimation/TypingAnimation.tsx +7 -0
  275. package/src/components/TypingAnimation/__tests__/TypingAnimation.test.tsx +47 -0
  276. package/src/components/TypingAnimation/index.ts +1 -1
  277. package/src/components/TypingAnimation/types/index.ts +14 -1
  278. package/src/components/WidgetTextField/WidgetTextField.tsx +47 -0
  279. package/src/components/WidgetTextField/__tests__/WidgetTextField.test.tsx +119 -4
  280. package/src/components/WidgetTextField/components/Container.tsx +40 -27
  281. package/src/components/WidgetTextField/hooks/useGetContainerProperties.ts +16 -4
  282. package/src/components/WidgetTextField/hooks/useGetMicWidgetButtonProperties.ts +38 -0
  283. package/src/components/WidgetTextField/types/types.ts +21 -0
  284. package/src/components/WidgetWrapper/hooks/useGetWrapperProperties.ts +1 -1
@@ -326,4 +326,51 @@ describe('TypingAnimation', () => {
326
326
  expect(handleButtonClick).toHaveBeenNthCalledWith(3, mockPromptButtonTexts[2]);
327
327
  });
328
328
  });
329
+
330
+ describe('Voice input', () => {
331
+ it('should render with voiceInputEnabled set to true', () => {
332
+ render(
333
+ <TypingAnimation
334
+ {...defaultProps}
335
+ widgetContentProps={{
336
+ ...defaultProps.widgetContentProps,
337
+ voiceInputEnabled: true,
338
+ hintText: 'Type something...',
339
+ }}
340
+ widgetStyleProps={{ showTextField: true }}
341
+ />,
342
+ );
343
+ expect(screen.getByText('Type something...')).toBeInTheDocument();
344
+ });
345
+
346
+ it('should render with voiceInputEnabled set to false', () => {
347
+ render(
348
+ <TypingAnimation
349
+ {...defaultProps}
350
+ widgetContentProps={{
351
+ ...defaultProps.widgetContentProps,
352
+ voiceInputEnabled: false,
353
+ hintText: 'Type something...',
354
+ }}
355
+ widgetStyleProps={{ showTextField: true }}
356
+ />,
357
+ );
358
+ expect(screen.getByText('Type something...')).toBeInTheDocument();
359
+ });
360
+
361
+ it('should render with voiceInputEnabled undefined (default)', () => {
362
+ render(
363
+ <TypingAnimation
364
+ {...defaultProps}
365
+ widgetContentProps={{
366
+ ...defaultProps.widgetContentProps,
367
+ voiceInputEnabled: undefined,
368
+ hintText: 'Type something...',
369
+ }}
370
+ widgetStyleProps={{ showTextField: true }}
371
+ />,
372
+ );
373
+ expect(screen.getByText('Type something...')).toBeInTheDocument();
374
+ });
375
+ });
329
376
  });
@@ -1,2 +1,2 @@
1
1
  export { TypingAnimation } from './TypingAnimation';
2
- export type { TypingAnimationProps } from './types';
2
+ export type { TypingAnimationProps, WidgetEventProps } from './types';
@@ -1,7 +1,7 @@
1
- import { WidgetWrapperVariant } from '../../WidgetWrapper';
2
1
  import { PromptButtonVariant } from '../../PromptButton/types';
3
2
  import { PromptCarouselRows } from '../../PromptCarousel/types/types';
4
3
  import { Theme } from '../../Tokens';
4
+ import { WidgetWrapperVariant } from '../../WidgetWrapper';
5
5
 
6
6
  /**
7
7
  * Base props for the TypingAnimation component container.
@@ -73,6 +73,11 @@ export type WidgetContentProps = {
73
73
  * When `true`, hides the logo in the title even if logoSrc is provided.
74
74
  */
75
75
  hideLogo?: boolean;
76
+
77
+ /**
78
+ * Whether to enable voice input.
79
+ */
80
+ voiceInputEnabled?: boolean;
76
81
  };
77
82
 
78
83
  /**
@@ -166,6 +171,14 @@ export type WidgetEventProps = {
166
171
  * Callback function invoked when the TextField is clicked.
167
172
  */
168
173
  handleTextFieldClick?: () => void;
174
+ /**
175
+ * Callback function invoked when voice transcription starts.
176
+ */
177
+ onTranscriptionStarted?: () => void;
178
+ /**
179
+ * Callback function invoked when voice transcription completes.
180
+ */
181
+ onTranscriptionCompleted?: (transcript: string) => void;
169
182
  };
170
183
 
171
184
  /**
@@ -1,7 +1,14 @@
1
+ import { listeningToSpeechAtom } from '@envive-ai/react-hooks/atoms/chat';
2
+ import classNames from 'classnames';
3
+ import { useSetAtom } from 'jotai';
1
4
  import { Theme } from '../../../tokens/theme/theme';
5
+ import { TextFieldComponents } from '../TextField/components';
6
+ import { useGetSkeletonProperties } from '../TextField/hooks/useGetSkeletonProperties';
7
+ import { useVoiceInput } from '../TextField/hooks/useVoiceInput';
2
8
  import { TypographyColor } from '../Typography/types';
3
9
  import { resolveTheme } from '../utils/resolveTheme';
4
10
  import { WidgetTextFieldComponents } from './components';
11
+ import { useGetMicWidgetButtonProperties } from './hooks/useGetMicWidgetButtonProperties';
5
12
  import { IconVariant, type WidgetTextFieldProps } from './types/types';
6
13
 
7
14
  export const WidgetTextField = ({
@@ -9,7 +16,9 @@ export const WidgetTextField = ({
9
16
  testId,
10
17
  style,
11
18
  className,
19
+ voiceInputClassName,
12
20
  theme = Theme.GLOBAL_CUSTOM,
21
+ minimalFrame = 'full',
13
22
  iconVariant = IconVariant.DEFAULT,
14
23
  textColor = TypographyColor.TEXT_SECONDARY,
15
24
  placeholder,
@@ -17,13 +26,49 @@ export const WidgetTextField = ({
17
26
  disabled,
18
27
  isLoading,
19
28
  onClick,
29
+ enableVoiceInput = false,
30
+ onTranscriptionStarted,
20
31
  }: WidgetTextFieldProps) => {
21
32
  const resolvedTheme = resolveTheme(theme);
33
+ const setListeningToSpeech = useSetAtom(listeningToSpeechAtom);
34
+ const { skeletonClass } = useGetSkeletonProperties(isLoading);
35
+
36
+ const { browserSupportsSpeechRecognition } = useVoiceInput({});
37
+
38
+ const { micWidgetButtonClasses } = useGetMicWidgetButtonProperties({
39
+ theme: resolvedTheme,
40
+ isListening: false,
41
+ });
42
+
43
+ const voiceInputButtonClassName = classNames(
44
+ micWidgetButtonClasses,
45
+ skeletonClass,
46
+ voiceInputClassName,
47
+ );
22
48
 
23
49
  if (isLoading) {
24
50
  return <WidgetTextFieldComponents.Skeleton theme={resolvedTheme} />;
25
51
  }
26
52
 
53
+ const handleToggleListening = () => {
54
+ setListeningToSpeech(true);
55
+ onTranscriptionStarted?.();
56
+ onClick();
57
+ };
58
+
59
+ const voiceInputButton =
60
+ enableVoiceInput && browserSupportsSpeechRecognition ? (
61
+ <TextFieldComponents.VoiceInputButton
62
+ theme={resolvedTheme}
63
+ isListening={false}
64
+ onToggleListening={disabled ? undefined : handleToggleListening}
65
+ ariaLabel={ariaLabel}
66
+ isLoading={isLoading}
67
+ disabled={disabled}
68
+ className={voiceInputButtonClassName}
69
+ />
70
+ ) : null;
71
+
27
72
  return (
28
73
  <WidgetTextFieldComponents.Container
29
74
  onClick={disabled ? undefined : onClick}
@@ -32,6 +77,7 @@ export const WidgetTextField = ({
32
77
  style={style}
33
78
  className={className}
34
79
  theme={resolvedTheme}
80
+ minimalFrame={minimalFrame}
35
81
  disabled={disabled}
36
82
  ariaLabel={ariaLabel}
37
83
  icon={
@@ -47,6 +93,7 @@ export const WidgetTextField = ({
47
93
  textColor={textColor}
48
94
  />
49
95
  }
96
+ voiceInputButton={voiceInputButton}
50
97
  />
51
98
  );
52
99
  };
@@ -1,11 +1,37 @@
1
1
  import '@testing-library/jest-dom';
2
- import { describe, expect, it, vi } from 'vitest';
3
2
  import { fireEvent, render, screen } from '@testing-library/react';
4
- import { WidgetTextField } from '../WidgetTextField';
3
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
5
4
  import { Theme } from '../../../../tokens/theme/theme';
6
5
  import { IconVariant } from '../types/types';
6
+ import { WidgetTextField } from '../WidgetTextField';
7
+
8
+ const { mockStartListening, mockStopListening, mockAbortListening, mockResetTranscript } =
9
+ vi.hoisted(() => ({
10
+ mockStartListening: vi.fn(() => Promise.resolve()),
11
+ mockStopListening: vi.fn(() => Promise.resolve()),
12
+ mockAbortListening: vi.fn(() => Promise.resolve()),
13
+ mockResetTranscript: vi.fn(),
14
+ }));
15
+
16
+ vi.mock('react-speech-recognition', () => ({
17
+ default: {
18
+ startListening: mockStartListening,
19
+ stopListening: mockStopListening,
20
+ abortListening: mockAbortListening,
21
+ },
22
+ useSpeechRecognition: vi.fn(() => ({
23
+ transcript: '',
24
+ browserSupportsSpeechRecognition: true,
25
+ resetTranscript: mockResetTranscript,
26
+ })),
27
+ }));
7
28
 
8
29
  describe('WidgetTextField', () => {
30
+ beforeEach(() => {
31
+ vi.clearAllMocks();
32
+ mockStartListening.mockImplementation(() => Promise.resolve());
33
+ });
34
+
9
35
  describe('Basic rendering', () => {
10
36
  it('should render with placeholder text', () => {
11
37
  render(
@@ -59,7 +85,7 @@ describe('WidgetTextField', () => {
59
85
  className="custom-class"
60
86
  />,
61
87
  );
62
- const element = container.firstChild as HTMLElement;
88
+ const element = container.querySelector('.envive-tw-w-full') as HTMLElement;
63
89
  expect(element).toHaveClass('custom-class');
64
90
  });
65
91
 
@@ -71,7 +97,7 @@ describe('WidgetTextField', () => {
71
97
  style={{ marginTop: '20px' }}
72
98
  />,
73
99
  );
74
- const element = container.firstChild as HTMLElement;
100
+ const element = container.querySelector('.envive-tw-w-full') as HTMLElement;
75
101
  expect(element).toHaveStyle({ marginTop: '20px' });
76
102
  });
77
103
  });
@@ -382,4 +408,93 @@ describe('WidgetTextField', () => {
382
408
  expect(svg).toBeInTheDocument();
383
409
  });
384
410
  });
411
+
412
+ describe('Voice input button', () => {
413
+ it('should render voice input button when enableVoiceInput is true', () => {
414
+ const { container } = render(
415
+ <WidgetTextField
416
+ placeholder="Test"
417
+ theme={Theme.STANDARD}
418
+ enableVoiceInput
419
+ />,
420
+ );
421
+ const voiceButton = container.querySelector('button');
422
+ expect(voiceButton).toBeInTheDocument();
423
+ });
424
+
425
+ it('should not render voice input button when enableVoiceInput is false', () => {
426
+ const { container } = render(
427
+ <WidgetTextField
428
+ placeholder="Test"
429
+ theme={Theme.STANDARD}
430
+ enableVoiceInput={false}
431
+ />,
432
+ );
433
+ const voiceButton = container.querySelector('button');
434
+ expect(voiceButton).not.toBeInTheDocument();
435
+ });
436
+
437
+ it('should not render voice input button when isLoading is true', () => {
438
+ const { container } = render(
439
+ <WidgetTextField
440
+ placeholder="Test"
441
+ theme={Theme.STANDARD}
442
+ enableVoiceInput
443
+ isLoading
444
+ />,
445
+ );
446
+ const voiceButton = container.querySelector('button');
447
+ expect(voiceButton).not.toBeInTheDocument();
448
+ });
449
+
450
+ it('should disable voice input button when disabled', () => {
451
+ const { container } = render(
452
+ <WidgetTextField
453
+ placeholder="Test"
454
+ theme={Theme.STANDARD}
455
+ enableVoiceInput
456
+ disabled
457
+ />,
458
+ );
459
+ const voiceButton = container.querySelector('button') as HTMLButtonElement;
460
+ expect(voiceButton).toBeDisabled();
461
+ });
462
+
463
+ it('should apply skeleton class when isLoading', () => {
464
+ const { container } = render(
465
+ <WidgetTextField
466
+ placeholder="Test"
467
+ theme={Theme.STANDARD}
468
+ enableVoiceInput
469
+ isLoading
470
+ />,
471
+ );
472
+ const element = container.querySelector('[class*="envive-tw"]');
473
+ expect(element?.className).toContain('envive-tw-animate-pulse');
474
+ });
475
+
476
+ it('should apply custom className when provided', () => {
477
+ const { container } = render(
478
+ <WidgetTextField
479
+ placeholder="Test"
480
+ theme={Theme.STANDARD}
481
+ className="custom-class"
482
+ />,
483
+ );
484
+ const element = container.querySelector('.custom-class');
485
+ expect(element).toBeInTheDocument();
486
+ });
487
+
488
+ it('should apply custom style when provided', () => {
489
+ const { container } = render(
490
+ <WidgetTextField
491
+ placeholder="Test"
492
+ theme={Theme.STANDARD}
493
+ style={{ marginTop: '20px' }}
494
+ />,
495
+ );
496
+ const element = container.querySelector('[class*="envive-tw"]');
497
+ expect(element).toHaveStyle({ marginTop: '20px' });
498
+ });
499
+ });
385
500
  });
@@ -1,7 +1,7 @@
1
1
  import classNames from 'classnames';
2
- import { Stack } from '../../Stack';
3
- import { Container as ContainerComponent } from '../../Container';
4
2
  import { Theme } from '../../../../tokens/theme/theme';
3
+ import { Container as ContainerComponent } from '../../Container';
4
+ import { Stack } from '../../Stack';
5
5
  import { useGetContainerProperties } from '../hooks/useGetContainerProperties';
6
6
  import { useHandleKeyboard } from '../hooks/useHandleKeyboard';
7
7
 
@@ -11,9 +11,11 @@ type ContainerProps = {
11
11
  style?: React.CSSProperties;
12
12
  className?: string;
13
13
  theme: Theme;
14
+ minimalFrame?: 'full' | 'bottom-only';
14
15
  ariaLabel?: string;
15
16
  icon: React.ReactNode;
16
17
  text: React.ReactNode;
18
+ voiceInputButton?: React.ReactNode;
17
19
  disabled?: boolean;
18
20
  onClick?: () => void;
19
21
  };
@@ -24,43 +26,54 @@ export const Container = ({
24
26
  style,
25
27
  className,
26
28
  theme,
29
+ minimalFrame,
27
30
  ariaLabel,
28
31
  icon,
29
32
  text,
33
+ voiceInputButton,
30
34
  disabled,
31
35
  onClick,
32
36
  }: ContainerProps) => {
33
- const { baseClassName, themeContainerClassName } = useGetContainerProperties({ theme });
37
+ const { baseClassName, themeContainerClassName, containerWrapperClassName } =
38
+ useGetContainerProperties({
39
+ theme,
40
+ minimalFrame,
41
+ });
34
42
 
35
43
  const { handleKeyDown } = useHandleKeyboard({ onClick });
36
44
 
37
45
  return (
38
- <ContainerComponent
39
- id={id}
40
- testId={testId}
46
+ <div
47
+ className={containerWrapperClassName}
41
48
  style={style}
42
- className={classNames(
43
- className,
44
- baseClassName,
45
- themeContainerClassName,
46
- disabled && 'envive-tw-pointer-events-none envive-tw-opacity-50',
47
- )}
48
- aria-label={ariaLabel}
49
- fluid
50
- onClick={onClick}
51
- onKeyDown={handleKeyDown}
52
- role="button"
53
- tabIndex={onClick ? 0 : undefined}
54
49
  >
55
- <Stack
56
- direction="row"
57
- align="center"
58
- justify="between"
59
- gap="2"
50
+ <ContainerComponent
51
+ id={id}
52
+ testId={testId}
53
+ className={classNames(
54
+ className,
55
+ baseClassName,
56
+ themeContainerClassName,
57
+ disabled && 'envive-tw-pointer-events-none envive-tw-opacity-50',
58
+ )}
59
+ aria-label={ariaLabel}
60
+ fluid
61
+ onClick={onClick}
62
+ onKeyDown={handleKeyDown}
63
+ role="button"
64
+ tabIndex={onClick ? 0 : undefined}
60
65
  >
61
- <div className="envive-tw-min-w-0 envive-tw-flex-1 envive-tw-overflow-hidden">{text}</div>
62
- <div className="envive-tw-flex-shrink-0">{icon}</div>
63
- </Stack>
64
- </ContainerComponent>
66
+ <Stack
67
+ direction="row"
68
+ align="center"
69
+ justify="between"
70
+ gap="2"
71
+ >
72
+ <div className="envive-tw-min-w-0 envive-tw-flex-1 envive-tw-overflow-hidden">{text}</div>
73
+ <div className="envive-tw-flex-shrink-0">{icon}</div>
74
+ </Stack>
75
+ </ContainerComponent>
76
+ {voiceInputButton}
77
+ </div>
65
78
  );
66
79
  };
@@ -3,21 +3,33 @@ import { Theme } from '../../../../tokens/theme/theme';
3
3
 
4
4
  export type UseGetContainerPropertiesProps = {
5
5
  theme: Theme;
6
+ minimalFrame?: 'full' | 'bottom-only';
6
7
  };
7
8
 
8
- export const useGetContainerProperties = ({ theme }: UseGetContainerPropertiesProps) => {
9
+ export const useGetContainerProperties = ({
10
+ theme,
11
+ minimalFrame = 'full',
12
+ }: UseGetContainerPropertiesProps) => {
9
13
  const baseClassName =
10
14
  'envive-tw-cursor-text envive-tw-border-solid envive-tw-px-4 envive-tw-py-2';
11
15
 
12
16
  const themeContainerClassName = useMemo(() => {
17
+ const minimalBorderClass =
18
+ minimalFrame === 'bottom-only'
19
+ ? 'envive-tw-border-b-[1px] envive-tw-border-text-light'
20
+ : 'envive-tw-border-[1px] envive-tw-border-border-light';
21
+
13
22
  const themeCotainerMap = {
14
23
  [Theme.STANDARD]:
15
24
  'envive-tw-border-[1px] envive-tw-border-border-light envive-tw-rounded-global-custom',
16
25
  [Theme.MODERN]: 'envive-tw-border-[1px] envive-tw-border-border-light envive-tw-rounded-4',
17
- [Theme.MINIMAL]: 'envive-tw-border-[1px] envive-tw-border-border-light',
26
+ [Theme.MINIMAL]: minimalBorderClass,
18
27
  };
19
28
  return themeCotainerMap[theme] ?? '';
20
- }, [theme]);
29
+ }, [theme, minimalFrame]);
30
+
31
+ const containerWrapperClassName =
32
+ 'envive-tw-gap-4 envive-tw-flex envive-tw-w-full envive-tw-flex-row';
21
33
 
22
- return { baseClassName, themeContainerClassName };
34
+ return { baseClassName, themeContainerClassName, containerWrapperClassName };
23
35
  };
@@ -0,0 +1,38 @@
1
+ import { useMemo } from 'react';
2
+ import { Theme } from '../../../../tokens/theme/theme';
3
+
4
+ export type UseGetMicWidgetButtonPropertiesProps = {
5
+ theme: Theme;
6
+ isListening?: boolean;
7
+ };
8
+
9
+ export type MicWidgetButtonProperties = {
10
+ micWidgetButtonClasses: string;
11
+ };
12
+
13
+ export const useGetMicWidgetButtonProperties = ({
14
+ theme,
15
+ isListening = false,
16
+ }: UseGetMicWidgetButtonPropertiesProps): MicWidgetButtonProperties => {
17
+ const micWidgetButtonClasses = useMemo(() => {
18
+ const micWidgetButtonClassesMap: Record<Theme, string> = {
19
+ [Theme.STANDARD]:
20
+ 'envive-tw-flex envive-tw-h-[42px] envive-tw-w-[44px] envive-tw-py-2 envive-tw-px-2 envive-tw-justify-center envive-tw-items-center envive-tw-border envive-tw-border-solid envive-tw-border-border-light envive-tw-rounded-global-custom',
21
+ [Theme.MODERN]:
22
+ 'envive-tw-flex envive-tw-h-[42px] envive-tw-w-[44px] envive-tw-py-2 envive-tw-px-2 envive-tw-justify-center envive-tw-items-center envive-tw-border envive-tw-border-solid envive-tw-border-border-light envive-tw-rounded-4',
23
+ [Theme.MINIMAL]:
24
+ 'envive-tw-flex envive-tw-h-[42px] envive-tw-w-[44px] envive-tw-py-2 envive-tw-px-2 envive-tw-justify-center envive-tw-items-center envive-tw-border envive-tw-border-solid envive-tw-border-border-light',
25
+ [Theme.GLOBAL_CUSTOM]:
26
+ 'envive-tw-flex envive-tw-h-[42px] envive-tw-w-[44px] envive-tw-py-2 envive-tw-px-2 envive-tw-justify-center envive-tw-items-center envive-tw-border envive-tw-border-solid envive-tw-border-border-light envive-tw-rounded-global-custom',
27
+ };
28
+
29
+ const baseClasses =
30
+ micWidgetButtonClassesMap[theme] ?? micWidgetButtonClassesMap[Theme.STANDARD];
31
+
32
+ return isListening
33
+ ? `${baseClasses} envive-tw-bg-[--envive-colors-text-accent]`
34
+ : `${baseClasses} envive-tw-bg-background-light`;
35
+ }, [theme, isListening]);
36
+
37
+ return { micWidgetButtonClasses };
38
+ };
@@ -30,6 +30,12 @@ export type WidgetTextFieldProps = {
30
30
  * @default Theme.GLOBAL_CUSTOM
31
31
  */
32
32
  theme?: Theme;
33
+ /**
34
+ * When the resolved theme is MINIMAL, controls border treatment.
35
+ * `full` matches overlays (full frame). `bottom-only` matches embedded contexts like product cards.
36
+ * @default 'full'
37
+ */
38
+ minimalFrame?: 'full' | 'bottom-only';
33
39
  /** Placeholder text displayed in the text field. */
34
40
  placeholder?: string;
35
41
  /** Accessible label for screen readers. If not provided, the placeholder will be used. */
@@ -47,6 +53,21 @@ export type WidgetTextFieldProps = {
47
53
  isLoading?: boolean;
48
54
  /** Callback function invoked when the text field is clicked or activated via keyboard. */
49
55
  onClick?: () => void;
56
+ /** Enable voice input button */
57
+ enableVoiceInput?: boolean;
58
+ /** Voice input button class name */
59
+ voiceInputClassName?: string;
60
+ /**
61
+ * Callback function invoked when voice transcription starts (user begins recording).
62
+ * Use this to track when the user starts using voice input.
63
+ */
64
+ onTranscriptionStarted?: () => void;
65
+ /**
66
+ * Callback function invoked when voice transcription completes (user stops recording).
67
+ * @param transcript - The transcribed text from the voice input.
68
+ * Use this to track the completed voice transcription and the resulting text.
69
+ */
70
+ onTranscriptionCompleted?: (transcript: string) => void;
50
71
  };
51
72
 
52
73
  export enum IconVariant {
@@ -9,7 +9,7 @@ export const useGetWrapperProperties = (variant: WidgetWrapperVariant) => {
9
9
  case WidgetWrapperVariant.CARD_NO_BORDER:
10
10
  return 'envive-tw-rounded-global-custom envive-tw-bg-background-light envive-tw-md:p-6 envive-tw-p-3';
11
11
  case WidgetWrapperVariant.INLINE_WITH_BORDER:
12
- return 'envive-tw-border-t envive-tw-border-b envive-tw-border-solid envive-tw-border-border-light envive-tw-md:py-6 envive-tw-py-3';
12
+ return 'envive-tw-border-t envive-tw-border-b envive-tw-border-solid envive-tw-border-border-light envive-tw-py-6';
13
13
  case WidgetWrapperVariant.INLINE_NO_BORDER:
14
14
  return undefined;
15
15
  default: