@athoscommerce/snap-preact 1.2.3-beta.4 → 1.2.3-beta.6

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 (214) hide show
  1. package/README.md +16 -0
  2. package/dist/cjs/components/src/components/Atoms/TemplateSelect/TemplateSelect.d.ts +3 -3
  3. package/dist/cjs/components/src/components/Atoms/TemplateSelect/TemplateSelect.d.ts.map +1 -1
  4. package/dist/cjs/components/src/components/Atoms/TemplateSelect/TemplateSelect.js +7 -8
  5. package/dist/cjs/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.d.ts +1 -1
  6. package/dist/cjs/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.d.ts.map +1 -1
  7. package/dist/cjs/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.js +3 -3
  8. package/dist/cjs/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts +2 -0
  9. package/dist/cjs/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts.map +1 -1
  10. package/dist/cjs/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.js +24 -25
  11. package/dist/cjs/components/src/components/Molecules/Filter/Filter.d.ts +1 -1
  12. package/dist/cjs/components/src/components/Molecules/Filter/Filter.d.ts.map +1 -1
  13. package/dist/cjs/components/src/components/Molecules/Result/Result.d.ts.map +1 -1
  14. package/dist/cjs/components/src/components/Molecules/Result/Result.js +11 -6
  15. package/dist/cjs/components/src/components/Molecules/SearchInput/SearchInput.d.ts +4 -1
  16. package/dist/cjs/components/src/components/Molecules/SearchInput/SearchInput.d.ts.map +1 -1
  17. package/dist/cjs/components/src/components/Molecules/SearchInput/SearchInput.js +3 -3
  18. package/dist/cjs/components/src/components/Molecules/TemplatesEditor/Components/AbstractedControls.js +5 -5
  19. package/dist/cjs/components/src/components/Molecules/TemplatesEditor/Components/Control.d.ts.map +1 -1
  20. package/dist/cjs/components/src/components/Molecules/TemplatesEditor/Components/Control.js +31 -31
  21. package/dist/cjs/components/src/components/Molecules/TemplatesEditor/TemplatesEditor.d.ts.map +1 -1
  22. package/dist/cjs/components/src/components/Molecules/TemplatesEditor/TemplatesEditor.js +22 -36
  23. package/dist/cjs/components/src/components/Organisms/Chat/Chat.d.ts +7 -0
  24. package/dist/cjs/components/src/components/Organisms/Chat/Chat.d.ts.map +1 -1
  25. package/dist/cjs/components/src/components/Organisms/Chat/Chat.js +638 -431
  26. package/dist/cjs/components/src/components/Organisms/Chat/ChatResult.d.ts.map +1 -1
  27. package/dist/cjs/components/src/components/Organisms/Chat/ChatResult.js +4 -3
  28. package/dist/cjs/components/src/components/Organisms/Chat/MessageText.d.ts +3 -1
  29. package/dist/cjs/components/src/components/Organisms/Chat/MessageText.d.ts.map +1 -1
  30. package/dist/cjs/components/src/components/Organisms/Chat/MessageText.js +22 -19
  31. package/dist/cjs/components/src/components/Organisms/Chat/MessageUser.d.ts +3 -1
  32. package/dist/cjs/components/src/components/Organisms/Chat/MessageUser.d.ts.map +1 -1
  33. package/dist/cjs/components/src/components/Organisms/Chat/MessageUser.js +39 -21
  34. package/dist/cjs/components/src/components/Organisms/Chat/ResultsDisplay.d.ts +1 -1
  35. package/dist/cjs/components/src/components/Organisms/Chat/ResultsDisplay.d.ts.map +1 -1
  36. package/dist/cjs/components/src/components/Organisms/Chat/ResultsDisplay.js +7 -11
  37. package/dist/cjs/components/src/components/Organisms/FilterSummary/FilterSummary.d.ts +2 -2
  38. package/dist/cjs/components/src/components/Organisms/FilterSummary/FilterSummary.d.ts.map +1 -1
  39. package/dist/cjs/components/src/components/Organisms/ProductQuickView/ProductQuickView.d.ts +11 -0
  40. package/dist/cjs/components/src/components/Organisms/ProductQuickView/ProductQuickView.d.ts.map +1 -0
  41. package/dist/cjs/components/src/components/Organisms/ProductQuickView/ProductQuickView.js +461 -0
  42. package/dist/cjs/components/src/components/Organisms/ProductQuickView/index.d.ts +2 -0
  43. package/dist/cjs/components/src/components/Organisms/ProductQuickView/index.d.ts.map +1 -0
  44. package/dist/cjs/components/src/components/Organisms/ProductQuickView/index.js +17 -0
  45. package/dist/cjs/components/src/components/Templates/AutocompleteModal/AutocompleteModal.d.ts.map +1 -1
  46. package/dist/cjs/components/src/components/Templates/AutocompleteModal/AutocompleteModal.js +0 -2
  47. package/dist/cjs/components/src/hooks/useAcRenderedInput.d.ts.map +1 -1
  48. package/dist/cjs/components/src/hooks/useAcRenderedInput.js +65 -15
  49. package/dist/cjs/components/src/hooks/useMediaQuery.d.ts.map +1 -1
  50. package/dist/cjs/components/src/hooks/useMediaQuery.js +3 -1
  51. package/dist/cjs/components/src/index.d.ts +1 -0
  52. package/dist/cjs/components/src/index.d.ts.map +1 -1
  53. package/dist/cjs/components/src/index.js +1 -0
  54. package/dist/cjs/components/src/providers/theme.d.ts +1 -1
  55. package/dist/cjs/components/src/providers/theme.d.ts.map +1 -1
  56. package/dist/cjs/components/src/themes/base/base.js +3 -3
  57. package/dist/cjs/components/src/utilities/Colour/Colour.d.ts +11 -0
  58. package/dist/cjs/components/src/utilities/Colour/Colour.d.ts.map +1 -1
  59. package/dist/cjs/components/src/utilities/Colour/Colour.js +32 -0
  60. package/dist/cjs/src/Instantiators/RecommendationInstantiator.d.ts +3 -1
  61. package/dist/cjs/src/Instantiators/RecommendationInstantiator.d.ts.map +1 -1
  62. package/dist/cjs/src/Instantiators/RecommendationInstantiator.js +162 -123
  63. package/dist/cjs/src/Snap.d.ts +1 -1
  64. package/dist/cjs/src/Snap.d.ts.map +1 -1
  65. package/dist/cjs/src/Snap.js +18 -6
  66. package/dist/cjs/src/SnapHybrid.d.ts.map +1 -1
  67. package/dist/cjs/src/Templates/SnapTemplates.d.ts +13 -72
  68. package/dist/cjs/src/Templates/SnapTemplates.d.ts.map +1 -1
  69. package/dist/cjs/src/Templates/SnapTemplates.js +123 -72
  70. package/dist/cjs/src/Templates/Stores/TargetStore.d.ts +7 -6
  71. package/dist/cjs/src/Templates/Stores/TargetStore.d.ts.map +1 -1
  72. package/dist/cjs/src/Templates/Stores/TargetStore.js +14 -8
  73. package/dist/cjs/src/Templates/Stores/TemplateEditor/TemplateEditorStore.d.ts +58 -8
  74. package/dist/cjs/src/Templates/Stores/TemplateEditor/TemplateEditorStore.d.ts.map +1 -1
  75. package/dist/cjs/src/Templates/Stores/TemplateEditor/TemplateEditorStore.js +467 -96
  76. package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.d.ts +1 -0
  77. package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.d.ts.map +1 -1
  78. package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.js +123 -70
  79. package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/configUI.d.ts.map +1 -1
  80. package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/configUI.js +9 -3
  81. package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.d.ts +1 -0
  82. package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.d.ts.map +1 -1
  83. package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.js +86 -1
  84. package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/themeUI.d.ts.map +1 -1
  85. package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/themeUI.js +33 -14
  86. package/dist/cjs/src/Templates/Stores/TemplateStore.d.ts +93 -30
  87. package/dist/cjs/src/Templates/Stores/TemplateStore.d.ts.map +1 -1
  88. package/dist/cjs/src/Templates/Stores/TemplateStore.js +33 -41
  89. package/dist/cjs/src/Templates/Stores/ThemeStore.d.ts +2 -8
  90. package/dist/cjs/src/Templates/Stores/ThemeStore.d.ts.map +1 -1
  91. package/dist/cjs/src/Templates/Stores/ThemeStore.js +3 -28
  92. package/dist/cjs/src/Templates/index.d.ts +1 -1
  93. package/dist/cjs/src/Templates/index.d.ts.map +1 -1
  94. package/dist/cjs/src/create/createChatController.js +1 -1
  95. package/dist/cjs/src/index.d.ts +1 -0
  96. package/dist/cjs/src/index.d.ts.map +1 -1
  97. package/dist/cjs/src/setupEvents.d.ts +13 -0
  98. package/dist/cjs/src/setupEvents.d.ts.map +1 -1
  99. package/dist/cjs/src/setupEvents.js +56 -8
  100. package/dist/cjs/src/types.d.ts +3 -1
  101. package/dist/cjs/src/types.d.ts.map +1 -1
  102. package/dist/cjs/src/utils/combineMerge.d.ts +2 -0
  103. package/dist/cjs/src/utils/combineMerge.d.ts.map +1 -0
  104. package/dist/cjs/src/utils/combineMerge.js +22 -0
  105. package/dist/cjs/src/utils/index.d.ts +1 -0
  106. package/dist/cjs/src/utils/index.d.ts.map +1 -1
  107. package/dist/cjs/src/utils/index.js +3 -1
  108. package/dist/esm/components/src/components/Atoms/TemplateSelect/TemplateSelect.d.ts +3 -3
  109. package/dist/esm/components/src/components/Atoms/TemplateSelect/TemplateSelect.d.ts.map +1 -1
  110. package/dist/esm/components/src/components/Atoms/TemplateSelect/TemplateSelect.js +7 -8
  111. package/dist/esm/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.d.ts +1 -1
  112. package/dist/esm/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.d.ts.map +1 -1
  113. package/dist/esm/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.js +3 -3
  114. package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts +2 -0
  115. package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts.map +1 -1
  116. package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.js +24 -26
  117. package/dist/esm/components/src/components/Molecules/Filter/Filter.d.ts +1 -1
  118. package/dist/esm/components/src/components/Molecules/Filter/Filter.d.ts.map +1 -1
  119. package/dist/esm/components/src/components/Molecules/Result/Result.d.ts.map +1 -1
  120. package/dist/esm/components/src/components/Molecules/Result/Result.js +9 -4
  121. package/dist/esm/components/src/components/Molecules/SearchInput/SearchInput.d.ts +4 -1
  122. package/dist/esm/components/src/components/Molecules/SearchInput/SearchInput.d.ts.map +1 -1
  123. package/dist/esm/components/src/components/Molecules/SearchInput/SearchInput.js +3 -3
  124. package/dist/esm/components/src/components/Molecules/TemplatesEditor/Components/AbstractedControls.js +5 -5
  125. package/dist/esm/components/src/components/Molecules/TemplatesEditor/Components/Control.d.ts.map +1 -1
  126. package/dist/esm/components/src/components/Molecules/TemplatesEditor/Components/Control.js +29 -29
  127. package/dist/esm/components/src/components/Molecules/TemplatesEditor/TemplatesEditor.d.ts.map +1 -1
  128. package/dist/esm/components/src/components/Molecules/TemplatesEditor/TemplatesEditor.js +22 -35
  129. package/dist/esm/components/src/components/Organisms/Chat/Chat.d.ts +7 -0
  130. package/dist/esm/components/src/components/Organisms/Chat/Chat.d.ts.map +1 -1
  131. package/dist/esm/components/src/components/Organisms/Chat/Chat.js +557 -359
  132. package/dist/esm/components/src/components/Organisms/Chat/ChatResult.d.ts.map +1 -1
  133. package/dist/esm/components/src/components/Organisms/Chat/ChatResult.js +4 -3
  134. package/dist/esm/components/src/components/Organisms/Chat/MessageText.d.ts +3 -1
  135. package/dist/esm/components/src/components/Organisms/Chat/MessageText.d.ts.map +1 -1
  136. package/dist/esm/components/src/components/Organisms/Chat/MessageText.js +21 -19
  137. package/dist/esm/components/src/components/Organisms/Chat/MessageUser.d.ts +3 -1
  138. package/dist/esm/components/src/components/Organisms/Chat/MessageUser.d.ts.map +1 -1
  139. package/dist/esm/components/src/components/Organisms/Chat/MessageUser.js +36 -21
  140. package/dist/esm/components/src/components/Organisms/Chat/ResultsDisplay.d.ts +1 -1
  141. package/dist/esm/components/src/components/Organisms/Chat/ResultsDisplay.d.ts.map +1 -1
  142. package/dist/esm/components/src/components/Organisms/Chat/ResultsDisplay.js +7 -11
  143. package/dist/esm/components/src/components/Organisms/FilterSummary/FilterSummary.d.ts +2 -2
  144. package/dist/esm/components/src/components/Organisms/FilterSummary/FilterSummary.d.ts.map +1 -1
  145. package/dist/esm/components/src/components/Organisms/ProductQuickView/ProductQuickView.d.ts +11 -0
  146. package/dist/esm/components/src/components/Organisms/ProductQuickView/ProductQuickView.d.ts.map +1 -0
  147. package/dist/esm/components/src/components/Organisms/ProductQuickView/ProductQuickView.js +436 -0
  148. package/dist/esm/components/src/components/Organisms/ProductQuickView/index.d.ts +2 -0
  149. package/dist/esm/components/src/components/Organisms/ProductQuickView/index.d.ts.map +1 -0
  150. package/dist/esm/components/src/components/Organisms/ProductQuickView/index.js +1 -0
  151. package/dist/esm/components/src/components/Templates/AutocompleteModal/AutocompleteModal.d.ts.map +1 -1
  152. package/dist/esm/components/src/components/Templates/AutocompleteModal/AutocompleteModal.js +0 -2
  153. package/dist/esm/components/src/hooks/useAcRenderedInput.d.ts.map +1 -1
  154. package/dist/esm/components/src/hooks/useAcRenderedInput.js +61 -11
  155. package/dist/esm/components/src/hooks/useMediaQuery.d.ts.map +1 -1
  156. package/dist/esm/components/src/hooks/useMediaQuery.js +3 -1
  157. package/dist/esm/components/src/index.d.ts +1 -0
  158. package/dist/esm/components/src/index.d.ts.map +1 -1
  159. package/dist/esm/components/src/index.js +1 -0
  160. package/dist/esm/components/src/providers/theme.d.ts +1 -1
  161. package/dist/esm/components/src/providers/theme.d.ts.map +1 -1
  162. package/dist/esm/components/src/themes/base/base.js +3 -3
  163. package/dist/esm/components/src/utilities/Colour/Colour.d.ts +11 -0
  164. package/dist/esm/components/src/utilities/Colour/Colour.d.ts.map +1 -1
  165. package/dist/esm/components/src/utilities/Colour/Colour.js +30 -0
  166. package/dist/esm/src/Instantiators/RecommendationInstantiator.d.ts +3 -1
  167. package/dist/esm/src/Instantiators/RecommendationInstantiator.d.ts.map +1 -1
  168. package/dist/esm/src/Instantiators/RecommendationInstantiator.js +131 -84
  169. package/dist/esm/src/Snap.d.ts +1 -1
  170. package/dist/esm/src/Snap.d.ts.map +1 -1
  171. package/dist/esm/src/Snap.js +21 -6
  172. package/dist/esm/src/SnapHybrid.d.ts.map +1 -1
  173. package/dist/esm/src/Templates/SnapTemplates.d.ts +13 -72
  174. package/dist/esm/src/Templates/SnapTemplates.d.ts.map +1 -1
  175. package/dist/esm/src/Templates/SnapTemplates.js +137 -78
  176. package/dist/esm/src/Templates/Stores/TargetStore.d.ts +7 -6
  177. package/dist/esm/src/Templates/Stores/TargetStore.d.ts.map +1 -1
  178. package/dist/esm/src/Templates/Stores/TargetStore.js +14 -8
  179. package/dist/esm/src/Templates/Stores/TemplateEditor/TemplateEditorStore.d.ts +58 -8
  180. package/dist/esm/src/Templates/Stores/TemplateEditor/TemplateEditorStore.d.ts.map +1 -1
  181. package/dist/esm/src/Templates/Stores/TemplateEditor/TemplateEditorStore.js +447 -89
  182. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.d.ts +1 -0
  183. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.d.ts.map +1 -1
  184. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.js +118 -66
  185. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/configUI.d.ts.map +1 -1
  186. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/configUI.js +9 -3
  187. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.d.ts +1 -0
  188. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.d.ts.map +1 -1
  189. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.js +82 -1
  190. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/themeUI.d.ts.map +1 -1
  191. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/themeUI.js +27 -8
  192. package/dist/esm/src/Templates/Stores/TemplateStore.d.ts +93 -30
  193. package/dist/esm/src/Templates/Stores/TemplateStore.d.ts.map +1 -1
  194. package/dist/esm/src/Templates/Stores/TemplateStore.js +29 -38
  195. package/dist/esm/src/Templates/Stores/ThemeStore.d.ts +2 -8
  196. package/dist/esm/src/Templates/Stores/ThemeStore.d.ts.map +1 -1
  197. package/dist/esm/src/Templates/Stores/ThemeStore.js +3 -26
  198. package/dist/esm/src/Templates/index.d.ts +1 -1
  199. package/dist/esm/src/Templates/index.d.ts.map +1 -1
  200. package/dist/esm/src/create/createChatController.js +1 -1
  201. package/dist/esm/src/index.d.ts +1 -0
  202. package/dist/esm/src/index.d.ts.map +1 -1
  203. package/dist/esm/src/setupEvents.d.ts +13 -0
  204. package/dist/esm/src/setupEvents.d.ts.map +1 -1
  205. package/dist/esm/src/setupEvents.js +25 -8
  206. package/dist/esm/src/types.d.ts +3 -1
  207. package/dist/esm/src/types.d.ts.map +1 -1
  208. package/dist/esm/src/utils/combineMerge.d.ts +2 -0
  209. package/dist/esm/src/utils/combineMerge.d.ts.map +1 -0
  210. package/dist/esm/src/utils/combineMerge.js +16 -0
  211. package/dist/esm/src/utils/index.d.ts +1 -0
  212. package/dist/esm/src/utils/index.d.ts.map +1 -1
  213. package/dist/esm/src/utils/index.js +1 -0
  214. package/package.json +20 -14
@@ -4,7 +4,7 @@ import classnames from 'classnames';
4
4
  import deepmerge from 'deepmerge';
5
5
  import { observer } from 'mobx-react-lite';
6
6
  import { useTheme, CacheProvider, useTreePath } from '../../../providers';
7
- import { mergeProps, mergeStyles } from '../../../utilities';
7
+ import { Colour, mergeProps, mergeStyles } from '../../../utilities';
8
8
  import { Button } from '../../Atoms/Button';
9
9
  import { useRef, useEffect, useMemo, useState } from 'preact/hooks';
10
10
  import { MessageUser } from './MessageUser';
@@ -13,16 +13,27 @@ import { SuggestedQuestions } from './SuggestedQuestions';
13
13
  import { ChatAttachmentContext } from './ChatAttachmentContext';
14
14
  import { Image } from '../../Atoms/Image';
15
15
  import { ChatLoadingIndicator } from '../../Atoms/ChatLoadingIndicator';
16
- import { Dropdown, Icon, Overlay, useMediaQuery } from '../../..';
16
+ import { Dropdown, FacetSlider, Icon, Overlay, useMediaQuery } from '../../..';
17
17
  import { ChatInspirationResultMessage } from '../../Molecules/ChatInspirationResultMessage';
18
18
  import { ChatProductComparisonMessage } from '../../Molecules/ChatProductComparisonMessage/ChatProductComparisonMessage';
19
19
  import { ChatProductQueryMessage } from '../../Molecules/ChatProductQueryMessage/ChatProductQueryMessage';
20
- const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
21
- const colorPrimary = '#253B80';
20
+ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight, primaryColorBg, primaryColorFg, primaryAccentColorBg, primaryAccentColorFg, secondaryAccentColorBg, secondaryAccentColorFg, position, }) => {
21
+ const isRight = position === 'right';
22
+ // horizontal anchor for the root + bubble + suggested questions
23
+ const horizontalAnchor = isRight ? 'right' : 'left';
24
+ const colorPrimary = primaryColorBg;
25
+ const colorPrimaryText = primaryColorFg;
26
+ const colorPrimaryHover = new Colour(primaryColorBg).darkenHex();
27
+ const colorPrimaryAccent = primaryAccentColorBg;
28
+ const colorPrimaryAccentText = primaryAccentColorFg;
29
+ const colorPrimaryAccentHover = new Colour(primaryAccentColorBg).darkenHex();
30
+ const colorSecondaryAccent = secondaryAccentColorBg;
31
+ const colorSecondaryAccentText = secondaryAccentColorFg;
32
+ const colorSecondaryAccentHover = new Colour(secondaryAccentColorBg).darkenHex();
22
33
  const offsetValue = offset !== undefined ? (typeof offset === 'number' ? `${offset}px` : offset) : undefined;
23
34
  return css({
24
35
  position: 'fixed',
25
- left: '20px',
36
+ [horizontalAnchor]: '20px',
26
37
  bottom: '20px',
27
38
  zIndex: 1002,
28
39
  color: '#333',
@@ -40,7 +51,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
40
51
  flexDirection: 'column',
41
52
  justifyContent: 'flex-end',
42
53
  overflow: 'hidden',
43
- order: 1,
54
+ order: isRight ? 2 : 1,
44
55
  '.ss__chat__header__title': {
45
56
  gap: '22px',
46
57
  },
@@ -60,7 +71,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
60
71
  display: 'flex',
61
72
  flexDirection: 'column',
62
73
  overflow: 'hidden',
63
- order: 2,
74
+ order: isRight ? 1 : 2,
64
75
  ...(mobile
65
76
  ? {
66
77
  position: 'absolute',
@@ -121,7 +132,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
121
132
  background: 'none',
122
133
  color: 'inherit',
123
134
  '&:not(.ss__button--disabled):hover': {
124
- background: '#dfeaf6',
135
+ background: new Colour(colorPrimary).lightenHex(0.85),
125
136
  },
126
137
  svg: {
127
138
  fill: colorPrimary,
@@ -131,12 +142,12 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
131
142
  '.ss__chat__bubble': {
132
143
  position: mobile ? 'fixed' : 'absolute',
133
144
  bottom: mobile ? '20px' : 0,
134
- left: mobile ? '20px' : 0,
145
+ [horizontalAnchor]: mobile ? '20px' : 0,
135
146
  width: '60px',
136
147
  height: '60px',
137
148
  borderRadius: '50%',
138
149
  background: colorPrimary,
139
- color: 'white',
150
+ color: colorPrimaryText,
140
151
  display: 'flex',
141
152
  alignItems: 'center',
142
153
  justifyContent: 'center',
@@ -145,20 +156,20 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
145
156
  boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
146
157
  zIndex: 10,
147
158
  '&:hover': {
148
- background: '#0052a3',
159
+ background: colorPrimaryHover,
149
160
  transform: 'scale(1.05)',
150
161
  },
151
162
  '.ss__icon': {
152
163
  height: '33px',
153
164
  width: '33px',
154
- fill: '#fff',
155
- stroke: '#fff',
165
+ fill: colorPrimaryText,
166
+ stroke: colorPrimaryText,
156
167
  },
157
168
  },
158
169
  '.ss__chat__suggested-questions': {
159
170
  position: mobile ? 'fixed' : 'absolute',
160
171
  bottom: mobile ? '90px' : '70px',
161
- left: mobile ? '20px' : 0,
172
+ [horizontalAnchor]: mobile ? '20px' : 0,
162
173
  display: 'flex',
163
174
  flexDirection: 'column',
164
175
  gap: '8px',
@@ -197,7 +208,10 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
197
208
  height: offsetValue ? `calc(100% - ${offsetValue})` : '100%',
198
209
  }
199
210
  : {
200
- width: hasSideChat ? 'calc(100vw - 60px)' : 'auto',
211
+ // Hug the content width — two 600px panels + 12px gap — so the
212
+ // container stays anchored to its side instead of stretching to
213
+ // the opposite viewport edge when the side chat opens.
214
+ width: hasSideChat ? 'min(calc(100vw - 60px), 1212px)' : 'auto',
201
215
  maxWidth: 'calc(100vw - 60px)',
202
216
  maxHeight: 'calc(100vh - 40px)',
203
217
  }),
@@ -212,7 +226,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
212
226
  fontSize: '16px',
213
227
  position: 'relative',
214
228
  padding: '10px 15px',
215
- color: '#fff',
229
+ color: colorPrimaryText,
216
230
  background: colorPrimary,
217
231
  borderTopLeftRadius: mobile ? 0 : '12px',
218
232
  borderTopRightRadius: mobile ? 0 : '12px',
@@ -246,8 +260,8 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
246
260
  backgroundColor: 'transparent',
247
261
  },
248
262
  svg: {
249
- fill: '#fff',
250
- stroke: '#fff',
263
+ fill: colorPrimaryText,
264
+ stroke: colorPrimaryText,
251
265
  },
252
266
  },
253
267
  },
@@ -302,6 +316,8 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
302
316
  display: 'flex',
303
317
  flexDirection: 'column-reverse',
304
318
  gap: 5,
319
+ maxHeight: '300px',
320
+ overflowY: 'auto',
305
321
  '.ss__chat__history__chats__chat': {
306
322
  '.ss__button': {
307
323
  borderRadius: '12px',
@@ -325,16 +341,16 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
325
341
  alignItems: 'center',
326
342
  gap: '10px',
327
343
  padding: '8px 15px',
328
- background: '#40528e',
329
- color: '#fff',
344
+ background: new Colour(colorPrimary).darkenHex(0.1),
345
+ color: colorPrimaryText,
330
346
  fontSize: '14px',
331
347
  '.ss__chat__session-feedback__icon': {
332
348
  flex: '0 0 auto',
333
349
  display: 'flex',
334
350
  alignItems: 'center',
335
351
  svg: {
336
- fill: '#fff',
337
- stroke: '#fff',
352
+ fill: colorPrimaryText,
353
+ stroke: colorPrimaryText,
338
354
  },
339
355
  },
340
356
  '.ss__chat__session-feedback__label': {
@@ -343,25 +359,32 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
343
359
  },
344
360
  '.ss__chat__session-feedback__actions': {
345
361
  display: 'flex',
346
- gap: '10px',
362
+ gap: '6px',
347
363
  alignItems: 'center',
348
364
  '> span': {
349
365
  display: 'flex',
350
366
  alignItems: 'center',
351
367
  justifyContent: 'center',
352
- },
353
- svg: {
354
368
  cursor: 'pointer',
355
- fill: '#fff',
356
- stroke: '#fff',
357
- opacity: 0.7,
369
+ opacity: 0.85,
370
+ padding: '4px',
371
+ borderRadius: '4px',
372
+ border: '1px solid transparent',
373
+ transition: 'opacity 0.15s ease, border-color 0.15s ease',
358
374
  '&:hover': {
359
375
  opacity: 1,
360
376
  },
361
377
  },
362
- '&.ss__chat__session-feedback__actions--rated svg': {
378
+ svg: {
379
+ fill: colorPrimaryText,
380
+ stroke: colorPrimaryText,
381
+ },
382
+ '&.ss__chat__session-feedback__actions--rated > span': {
363
383
  opacity: 1,
364
384
  cursor: 'default',
385
+ '&:hover': {
386
+ borderColor: 'transparent',
387
+ },
365
388
  },
366
389
  },
367
390
  '.ss__chat__session-feedback__close': {
@@ -369,13 +392,14 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
369
392
  display: 'flex',
370
393
  alignItems: 'center',
371
394
  cursor: 'pointer',
395
+ opacity: 0.85,
396
+ transition: 'opacity 0.15s ease',
397
+ '&:hover': {
398
+ opacity: 1,
399
+ },
372
400
  svg: {
373
- fill: '#fff',
374
- stroke: '#fff',
375
- opacity: 0.7,
376
- '&:hover': {
377
- opacity: 1,
378
- },
401
+ fill: colorPrimaryText,
402
+ stroke: colorPrimaryText,
379
403
  },
380
404
  },
381
405
  },
@@ -385,7 +409,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
385
409
  overflow: 'hidden',
386
410
  display: 'flex',
387
411
  flexDirection: 'column',
388
- border: '1px solid #0066cc',
412
+ border: `1px solid ${colorPrimary}`,
389
413
  borderTop: 'none',
390
414
  marginTop: '-1px',
391
415
  borderBottomRightRadius: mobile ? 0 : '12px',
@@ -415,7 +439,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
415
439
  display: 'flex',
416
440
  flexDirection: 'column',
417
441
  gap: '1em',
418
- background: '#f4f4ff',
442
+ background: new Colour(colorPrimary).lightenHex(0.95),
419
443
  padding: '1em',
420
444
  '.ss__chat__content__header__comparisons__header': {
421
445
  display: 'flex',
@@ -430,7 +454,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
430
454
  background: colorPrimary,
431
455
  borderRadius: '50%',
432
456
  padding: '5px',
433
- fill: '#fff',
457
+ fill: colorPrimaryText,
434
458
  height: '25px',
435
459
  width: '25px',
436
460
  },
@@ -503,11 +527,11 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
503
527
  borderRadius: '1em',
504
528
  padding: '0.5em 1em',
505
529
  background: colorPrimary,
506
- color: '#fff',
530
+ color: colorPrimaryText,
507
531
  textAlign: 'center',
508
532
  svg: {
509
- fill: '#fff',
510
- stroke: '#fff',
533
+ fill: colorPrimaryText,
534
+ stroke: colorPrimaryText,
511
535
  },
512
536
  },
513
537
  },
@@ -535,7 +559,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
535
559
  width: 'fit-content',
536
560
  padding: '6px 16px',
537
561
  background: colorPrimary,
538
- color: '#fff',
562
+ color: colorPrimaryText,
539
563
  borderRadius: '999px',
540
564
  fontSize: '13px',
541
565
  fontWeight: 500,
@@ -543,11 +567,11 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
543
567
  boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
544
568
  zIndex: 5,
545
569
  '&:hover': {
546
- background: '#1a2a5c',
570
+ background: colorPrimaryHover,
547
571
  },
548
572
  svg: {
549
- fill: '#fff',
550
- stroke: '#fff',
573
+ fill: colorPrimaryText,
574
+ stroke: colorPrimaryText,
551
575
  },
552
576
  },
553
577
  '.ss__chat__message': {
@@ -599,8 +623,8 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
599
623
  flexDirection: 'column',
600
624
  gap: '6px',
601
625
  padding: '8px 10px',
602
- background: '#f4f4ff',
603
- border: '1px solid #e3e3f5',
626
+ background: new Colour(colorPrimary).lightenHex(0.95),
627
+ border: `1px solid ${new Colour(colorPrimary).lightenHex(0.85)}`,
604
628
  borderRadius: '8px',
605
629
  },
606
630
  '.ss__chat__actions--title': {
@@ -620,7 +644,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
620
644
  fontSize: '14px',
621
645
  color: '#333',
622
646
  '&:hover': {
623
- background: '#f9f9ff',
647
+ background: new Colour(colorPrimary).lightenHex(0.97),
624
648
  },
625
649
  },
626
650
  },
@@ -720,8 +744,8 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
720
744
  visibility: 'visible',
721
745
  },
722
746
  '.ss__button': {
723
- background: '#253B80',
724
- color: '#fff',
747
+ background: colorPrimary,
748
+ color: colorPrimaryText,
725
749
  border: 'none',
726
750
  borderRadius: '999px',
727
751
  padding: '2px 10px',
@@ -729,7 +753,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
729
753
  lineHeight: '1.4',
730
754
  cursor: 'pointer',
731
755
  '&:not(.ss__button--disabled):hover': {
732
- background: '#1a2a5c',
756
+ background: colorPrimaryHover,
733
757
  },
734
758
  '&.ss__button--disabled': {
735
759
  opacity: 0.5,
@@ -752,8 +776,8 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
752
776
  flexDirection: 'column',
753
777
  gap: '6px',
754
778
  padding: '8px 10px',
755
- background: '#f4f4ff',
756
- border: '1px solid #e3e3f5',
779
+ background: new Colour(colorPrimary).lightenHex(0.95),
780
+ border: `1px solid ${new Colour(colorPrimary).lightenHex(0.85)}`,
757
781
  borderRadius: '8px',
758
782
  '.ss__chat__attachment-context__label': {
759
783
  fontSize: '14px',
@@ -889,20 +913,39 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
889
913
  flexDirection: 'column',
890
914
  gap: '8px',
891
915
  flexShrink: 0,
916
+ position: 'relative',
892
917
  ...(mobile
893
918
  ? {
894
- position: 'relative',
895
919
  zIndex: 11,
896
920
  background: '#fff',
897
921
  }
898
922
  : {}),
923
+ '.ss__chat__content__footer__drop-overlay': {
924
+ position: 'absolute',
925
+ inset: 0,
926
+ display: 'flex',
927
+ alignItems: 'center',
928
+ justifyContent: 'center',
929
+ gap: '8px',
930
+ borderRadius: '6px',
931
+ border: `2px dashed ${colorPrimary}`,
932
+ backgroundColor: new Colour(colorPrimary).lightenHex(0.9),
933
+ color: colorPrimary,
934
+ fontWeight: 'bold',
935
+ pointerEvents: 'none',
936
+ zIndex: 12,
937
+ svg: {
938
+ fill: colorPrimary,
939
+ stroke: colorPrimary,
940
+ },
941
+ },
899
942
  },
900
943
  '.ss__chat__topic-drift': {
901
944
  display: 'flex',
902
945
  alignItems: 'center',
903
946
  gap: '12px',
904
947
  padding: '12px 16px',
905
- border: '1px solid #93C5FD',
948
+ border: `1px solid ${new Colour(colorPrimary).lightenHex(0.6)}`,
906
949
  borderRadius: '8px',
907
950
  backgroundColor: '#fff',
908
951
  '.ss__chat__topic-drift__icon--info': {
@@ -932,7 +975,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
932
975
  '.ss__chat__topic-drift__button': {
933
976
  flex: '0 0 auto',
934
977
  backgroundColor: colorPrimary,
935
- color: '#fff',
978
+ color: colorPrimaryText,
936
979
  borderRadius: '6px',
937
980
  padding: '8px 14px',
938
981
  fontSize: '13px',
@@ -940,7 +983,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
940
983
  cursor: 'pointer',
941
984
  whiteSpace: 'nowrap',
942
985
  '&:not(.ss__button--disabled):hover': {
943
- background: '#1a2a5c',
986
+ background: colorPrimaryHover,
944
987
  },
945
988
  },
946
989
  '.ss__chat__topic-drift__icon--close': {
@@ -978,7 +1021,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
978
1021
  },
979
1022
  '&:focus': {
980
1023
  outline: 'none',
981
- borderColor: '#0066cc',
1024
+ borderColor: colorPrimary,
982
1025
  },
983
1026
  },
984
1027
  '.ss__button': {
@@ -994,18 +1037,20 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
994
1037
  '.ss__chat__input__actions': {
995
1038
  '.ss__button': {
996
1039
  backgroundColor: colorPrimary,
1040
+ color: colorPrimaryText,
997
1041
  borderRadius: '50%',
998
1042
  height: '3em',
999
1043
  width: '3em',
1000
1044
  cursor: 'pointer',
1001
1045
  justifyContent: 'center',
1046
+ boxSizing: 'border-box',
1002
1047
  '&:disabled': {
1003
1048
  opacity: 0.5,
1004
1049
  cursor: 'not-allowed',
1005
1050
  },
1006
1051
  svg: {
1007
- fill: '#fff',
1008
- stroke: '#fff',
1052
+ fill: colorPrimaryText,
1053
+ stroke: colorPrimaryText,
1009
1054
  },
1010
1055
  },
1011
1056
  },
@@ -1016,6 +1061,55 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
1016
1061
  textAlign: 'center',
1017
1062
  flexShrink: 0,
1018
1063
  },
1064
+ '.ss__chat__result__image__icons__icon--cart': {
1065
+ backgroundColor: `${colorPrimaryAccent} !important`,
1066
+ svg: {
1067
+ fill: `${colorPrimaryAccentText} !important`,
1068
+ stroke: `${colorPrimaryAccentText} !important`,
1069
+ },
1070
+ },
1071
+ '.ss__chat-product-query-message__header__product__actions__add-to-cart .ss__button': {
1072
+ background: `${colorPrimaryAccent} !important`,
1073
+ color: `${colorPrimaryAccentText} !important`,
1074
+ '&:not(.ss__button--disabled):hover': {
1075
+ background: `${colorPrimaryAccentHover} !important`,
1076
+ },
1077
+ },
1078
+ // Secondary accent — applied to the productQuery button (ChatResult inquire icon)
1079
+ // and the "Show similar" button (ChatProductQueryMessage). Both elements live in
1080
+ // child components but their styling overrides are intentionally scoped here so
1081
+ // the Chat-level theme can drive them.
1082
+ '.ss__chat__result__image__icons__icon--inquire': {
1083
+ backgroundColor: `${colorSecondaryAccent} !important`,
1084
+ svg: {
1085
+ fill: `${colorSecondaryAccentText} !important`,
1086
+ stroke: `${colorSecondaryAccentText} !important`,
1087
+ },
1088
+ },
1089
+ '.ss__chat-product-query-message__header__product__actions__show-similar .ss__button, .ss__chat-product-query-message__header__product__actions__discuss-product .ss__button': {
1090
+ background: `${colorSecondaryAccent} !important`,
1091
+ color: `${colorSecondaryAccentText} !important`,
1092
+ border: `1px solid ${colorSecondaryAccentText} !important`,
1093
+ '&:not(.ss__button--disabled):hover': {
1094
+ background: `${colorSecondaryAccentHover} !important`,
1095
+ },
1096
+ },
1097
+ '.ss__chat__expired': {
1098
+ display: 'flex',
1099
+ flexDirection: 'column',
1100
+ alignItems: 'center',
1101
+ justifyContent: 'center',
1102
+ gap: '12px',
1103
+ padding: '16px',
1104
+ textAlign: 'center',
1105
+ color: '#6A7282',
1106
+ '.ss__chat__expired__message': {
1107
+ fontSize: '14px',
1108
+ },
1109
+ '.ss__chat__expired__button': {
1110
+ alignSelf: 'center',
1111
+ },
1112
+ },
1019
1113
  },
1020
1114
  });
1021
1115
  };
@@ -1027,12 +1121,26 @@ export const Chat = observer((properties) => {
1027
1121
  treePath: globalTreePath,
1028
1122
  logo: 'https://cdn.athoscommerce.net/snap/images/Athos%20Commerce_Icon_white.svg',
1029
1123
  title: 'Athos Conversational Assistant',
1030
- subtitle: 'Ready to assist you',
1124
+ subtitle: 'Your Guided Discovery Expert',
1031
1125
  multiselectFacets: true,
1032
1126
  disableBubbleSuggestedQuestions: false,
1127
+ primaryColorBg: '#253B80',
1128
+ primaryColorFg: '#fff',
1129
+ primaryAccentColorBg: '#feeeae',
1130
+ primaryAccentColorFg: '#000000',
1131
+ secondaryAccentColorBg: '#000000',
1132
+ secondaryAccentColorFg: '#ffffff',
1133
+ position: 'right',
1033
1134
  };
1034
1135
  let props = mergeProps('facets', globalTheme, defaultProps, properties);
1035
- const { className, internalClassName, controller, logo, title, subtitle, offset, multiselectFacets, disableBubbleSuggestedQuestions } = props;
1136
+ const { className, internalClassName, controller, logo, title, subtitle, offset, multiselectFacets, disableBubbleSuggestedQuestions, primaryColorBg, primaryColorFg, primaryAccentColorBg, primaryAccentColorFg, secondaryAccentColorBg, secondaryAccentColorFg, position, } = props;
1137
+ const colorPrimary = primaryColorBg;
1138
+ const colorPrimaryText = primaryColorFg;
1139
+ const colorPrimaryAccent = primaryAccentColorBg;
1140
+ const colorPrimaryAccentText = primaryAccentColorFg;
1141
+ const colorSecondaryAccent = secondaryAccentColorBg;
1142
+ const colorSecondaryAccentText = secondaryAccentColorFg;
1143
+ const chatPosition = position === 'right' ? 'right' : 'left';
1036
1144
  const { store } = controller;
1037
1145
  const themeDefaults = {
1038
1146
  components: {},
@@ -1048,6 +1156,7 @@ export const Chat = observer((properties) => {
1048
1156
  const messagesContainerRef = useRef(null);
1049
1157
  const headerRef = useRef(null);
1050
1158
  const footerRef = useRef(null);
1159
+ const chatRef = useRef(null);
1051
1160
  // Swipe-to-dismiss state for mobile secondary panel
1052
1161
  const secondaryRef = useRef(null);
1053
1162
  const swipeStartY = useRef(0);
@@ -1061,6 +1170,10 @@ export const Chat = observer((properties) => {
1061
1170
  const [showNewMessages, setShowNewMessages] = useState(false);
1062
1171
  const [messagesOverflow, setMessagesOverflow] = useState(false);
1063
1172
  const isNearBottomRef = useRef(true);
1173
+ // Drag-and-drop image upload onto the footer. `dragenter`/`dragleave` fire on every
1174
+ // child crossing, so use a counter to know when the pointer has truly left the footer.
1175
+ const [isDraggingFile, setIsDraggingFile] = useState(false);
1176
+ const dragCounterRef = useRef(0);
1064
1177
  const updateSwipeOffset = (value) => {
1065
1178
  swipeOffsetRef.current = value;
1066
1179
  setSwipeOffsetRaw(value);
@@ -1195,7 +1308,19 @@ export const Chat = observer((properties) => {
1195
1308
  ? ['inspirationResult', ...(isFirstMobileComparison ? ['productComparison'] : []), ...(mobileProductInfoOpen ? ['productQuery'] : [])]
1196
1309
  : ['inspirationResult', 'productComparison', 'productQuery'];
1197
1310
  const shouldShowSideChat = activeMessage && sideChatTypes.includes(activeMessage?.messageType) && store.currentChat?.dismissedSideChatMessageId !== activeMessage.id;
1198
- const styling = mergeStyles({ mobile: isMobile, offset, hasSideChat: !!shouldShowSideChat, footerHeight }, defaultStyles);
1311
+ const styling = mergeStyles({
1312
+ mobile: isMobile,
1313
+ offset,
1314
+ hasSideChat: !!shouldShowSideChat,
1315
+ footerHeight,
1316
+ primaryColorBg: colorPrimary,
1317
+ primaryColorFg: colorPrimaryText,
1318
+ primaryAccentColorBg: colorPrimaryAccent,
1319
+ primaryAccentColorFg: colorPrimaryAccentText,
1320
+ secondaryAccentColorBg: colorSecondaryAccent,
1321
+ secondaryAccentColorFg: colorSecondaryAccentText,
1322
+ position: chatPosition,
1323
+ }, defaultStyles);
1199
1324
  // Lock body scroll while chat is open so touch/wheel scrolls don't leak to the page behind
1200
1325
  useEffect(() => {
1201
1326
  if (!store.open)
@@ -1241,6 +1366,17 @@ export const Chat = observer((properties) => {
1241
1366
  })() }), _jsx("div", { className: "ss__chat__history__chat__button__date", children: chat.createdAt.toLocaleString() })] }) }, chat.id))) })) : null] }));
1242
1367
  const FacetButton = (props) => _jsx(Button, { icon: props.open ? 'angle-down' : 'angle-up', children: props.label });
1243
1368
  const getFacetButtonLabel = (facet) => {
1369
+ const base = facet.label || facet.field;
1370
+ // Slider facets show the active low-high range in the button when narrowed.
1371
+ if (facet.type === 'range') {
1372
+ const rangeFacet = facet;
1373
+ const active = rangeFacet.active;
1374
+ const range = rangeFacet.range;
1375
+ if (active && range && (active.low !== range.low || active.high !== range.high)) {
1376
+ return `${base} (${active.low ?? '*'}-${active.high ?? '*'})`;
1377
+ }
1378
+ return base;
1379
+ }
1244
1380
  const applied = new Set();
1245
1381
  // Count values marked as filtered (already applied on the server)
1246
1382
  (facet.values || []).forEach((value) => {
@@ -1257,9 +1393,42 @@ export const Chat = observer((properties) => {
1257
1393
  (controller.store.currentChat?.attachments.items || [])
1258
1394
  .filter((item) => item.type === 'facet' && item.key === facet.field && (item.state === 'active' || item.state === 'attached'))
1259
1395
  .forEach((item) => applied.add(item.value));
1260
- const base = facet.label || facet.field;
1261
1396
  return applied.size > 0 ? `${base} (${applied.size})` : base;
1262
1397
  };
1398
+ // Slider dropdown grows to fill the remaining chat width from its anchor,
1399
+ // so the price range slider isn't cramped inside a 150px-wide dropdown.
1400
+ const SliderFacetDropdown = (props) => {
1401
+ const anchorRef = useRef(null);
1402
+ const [width, setWidth] = useState(null);
1403
+ useEffect(() => {
1404
+ const compute = () => {
1405
+ if (!anchorRef.current || !chatRef.current)
1406
+ return;
1407
+ const anchor = anchorRef.current.getBoundingClientRect();
1408
+ const chat = chatRef.current.getBoundingClientRect();
1409
+ const remaining = chat.right - anchor.left - 16;
1410
+ setWidth(Math.max(220, remaining));
1411
+ };
1412
+ compute();
1413
+ const ro = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(compute) : null;
1414
+ if (ro && chatRef.current)
1415
+ ro.observe(chatRef.current);
1416
+ window.addEventListener('resize', compute);
1417
+ return () => {
1418
+ if (ro)
1419
+ ro.disconnect();
1420
+ window.removeEventListener('resize', compute);
1421
+ };
1422
+ }, []);
1423
+ return (_jsx("div", { ref: anchorRef, className: "ss__chat__actions__facet ss__chat__actions__facet--range", children: _jsx(Dropdown, { usePortal: true, dropUp: true, button: _jsx(FacetButton, { label: props.label }), style: {
1424
+ '.ss__dropdown__content': {
1425
+ width: width ? `${width}px` : 'auto',
1426
+ background: 'white',
1427
+ boxShadow: '0px 3px 6px 0px rgba(0, 0, 0, 0.2)',
1428
+ borderRadius: '6px',
1429
+ },
1430
+ }, children: _jsx("div", { className: "ss__chat__actions__facet__options", children: _jsx("div", { className: "ss__chat__actions__facet__slider", style: { padding: '12px 16px' }, children: _jsx(FacetSlider, { facet: props.facet }) }) }) }) }));
1431
+ };
1263
1432
  // TODO: if starting a new chat and it's expired, this button would then disappear
1264
1433
  if (!controller.store.chatEnabled) {
1265
1434
  return _jsx(_Fragment, {});
@@ -1344,7 +1513,7 @@ export const Chat = observer((properties) => {
1344
1513
  return undefined;
1345
1514
  }
1346
1515
  }, [requestType]);
1347
- return (_jsx(CacheProvider, { children: _jsxs(_Fragment, { children: [_jsxs("div", { className: classnames('ss__chat', {
1516
+ return (_jsx(CacheProvider, { children: _jsxs(_Fragment, { children: [_jsxs("div", { ref: chatRef, className: classnames('ss__chat', {
1348
1517
  'ss__chat--open': store.open,
1349
1518
  'ss__chat--minimized': !store.open,
1350
1519
  'ss__chat--mobile': isMobile,
@@ -1375,9 +1544,9 @@ export const Chat = observer((properties) => {
1375
1544
  setMobileProductInfoOpen(false);
1376
1545
  store.currentChat?.dismissSideChat();
1377
1546
  } }) })] }), _jsx("div", { className: "ss__chat__content", children: _jsx("div", { className: 'ss__chat__messages', children: {
1378
- inspirationResult: (_jsx(ChatInspirationResultMessage, { chatItem: activeMessage, controller: controller, onViewProduct: isMobile ? () => setMobileProductInfoOpen(true) : undefined })),
1547
+ inspirationResult: (_jsx(ChatInspirationResultMessage, { chatItem: activeMessage, controller: controller, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined })),
1379
1548
  productComparison: (_jsx(ChatProductComparisonMessage, { chatItem: activeMessage, controller: controller })),
1380
- productQuery: (_jsx(ChatProductQueryMessage, { chatItem: activeMessage, controller: controller, displayFields: controller.config.settings?.displayFields })),
1549
+ productQuery: (_jsx(ChatProductQueryMessage, { chatItem: activeMessage, controller: controller, displayFields: controller.config.settings?.quickview?.displayFields, primaryColor: colorPrimary, primaryColorText: colorPrimaryText })),
1381
1550
  }[activeMessage.messageType] || null }) })] })) : null, store.open ? (_jsxs("div", { className: 'ss__chat__primary', children: [_jsxs("div", { className: 'ss__chat__header', children: [_jsxs("div", { className: "ss__chat__header__title", children: [logo ? _jsx("img", { className: "ss__chat__header__title__logo", src: logo }) : null, _jsxs("div", { className: "ss__chat__header__title__text", children: [title ? _jsx("div", { className: "ss__chat__header__title__text__primary", children: title }) : null, subtitle ? _jsx("div", { className: "ss__chat__header__title__text__secondary", children: subtitle }) : null] })] }), _jsxs("div", { className: "ss__chat__header__buttons", children: [_jsx(Button
1382
1551
  // disabled={store.currentChat?.chat && store.currentChat.chat.length <= 1}
1383
1552
  , {
@@ -1391,7 +1560,7 @@ export const Chat = observer((properties) => {
1391
1560
  systemMessages.length >= feedbackAfterMessages &&
1392
1561
  !store.currentChat?.feedbackDismissed &&
1393
1562
  (!hasRated || store.currentChat?.feedbackJustGiven);
1394
- return shouldShowFeedback ? (_jsxs("div", { className: "ss__chat__session-feedback", children: [_jsx("div", { className: "ss__chat__session-feedback__icon", children: _jsx(Icon, { icon: "chat", size: "16px" }) }), _jsx("span", { className: "ss__chat__session-feedback__label", children: hasRated ? 'Thank you for your feedback' : "How's your experience so far?" }), _jsxs("div", { className: `ss__chat__session-feedback__actions${hasRated ? ' ss__chat__session-feedback__actions--rated' : ''}`, children: [(!hasRated || currentRating === 'UP') && (_jsx("span", { onClick: () => !hasRated && controller.handleFeedback('UP'), children: _jsx(Icon, { icon: 'thumbs-up', title: 'Thumbs Up' }) })), (!hasRated || currentRating === 'DOWN') && (_jsx("span", { onClick: () => !hasRated && controller.handleFeedback('DOWN'), children: _jsx(Icon, { icon: 'thumbs-down', title: 'Thumbs Down' }) }))] }), !hasRated && (_jsx("span", { className: "ss__chat__session-feedback__close", onClick: () => {
1563
+ return shouldShowFeedback ? (_jsxs("div", { className: "ss__chat__session-feedback", children: [_jsx("div", { className: "ss__chat__session-feedback__icon", children: _jsx(Icon, { icon: "chat", size: "16px" }) }), _jsx("span", { className: "ss__chat__session-feedback__label", children: hasRated ? 'Thank you for your feedback' : "How's your experience so far?" }), _jsxs("div", { className: `ss__chat__session-feedback__actions${hasRated ? ' ss__chat__session-feedback__actions--rated' : ''}`, children: [(!hasRated || currentRating === 'UP') && (_jsx("span", { onClick: () => !hasRated && controller.handleFeedback('UP'), children: _jsx(Icon, { icon: 'thumbs-up', size: "16px", title: 'Thumbs Up' }) })), (!hasRated || currentRating === 'DOWN') && (_jsx("span", { onClick: () => !hasRated && controller.handleFeedback('DOWN'), children: _jsx(Icon, { icon: 'thumbs-down', size: "16px", title: 'Thumbs Down' }) }))] }), !hasRated && (_jsx("span", { className: "ss__chat__session-feedback__close", onClick: () => {
1395
1564
  if (store.currentChat) {
1396
1565
  store.currentChat.feedbackDismissed = true;
1397
1566
  store.currentChat.save();
@@ -1405,11 +1574,11 @@ export const Chat = observer((properties) => {
1405
1574
  'ss__chat__content__header__comparisons__content__comparison--placeholder': !comparisonItem,
1406
1575
  }), children: comparisonItem ? (_jsxs(_Fragment, { children: [_jsx(Image
1407
1576
  // onClick={() => {
1408
- // controller?.viewProduct(product as any);
1577
+ // controller?.productQuickView(product as any);
1409
1578
  // }}
1410
1579
  , {
1411
1580
  // onClick={() => {
1412
- // controller?.viewProduct(product as any);
1581
+ // controller?.productQuickView(product as any);
1413
1582
  // }}
1414
1583
  alt: (comparisonItem?.result?.display || comparisonItem?.result)?.mappings?.core?.name || '', src: (comparisonItem?.result?.display || comparisonItem?.result)?.mappings?.core?.imageUrl || '' }), _jsx("div", { className: "ss__chat__content__header__comparisons__content__comparison__remove", onClick: () => {
1415
1584
  store.currentChat?.comparisons.remove(comparisonItem.result.id);
@@ -1419,324 +1588,353 @@ export const Chat = observer((properties) => {
1419
1588
  }), children: _jsx(Button, { onClick: () => controller.search(), icon: { icon: 'compare', title: 'Compare' }, children: "Compare" }) })] })] })) }), _jsxs("div", { className: 'ss__chat__messages', ref: messagesContainerRef, style: visibleChatLength ? { scrollbarGutter: 'stable' } : undefined, children: [(!store.currentChat?.chat || store.currentChat.chat.length === 0) && store.welcomeMessage && !store.currentChat?.isExpired && (_jsxs("div", { className: "ss__chat__welcome", children: [_jsx("div", { className: "ss__chat__welcome__message", children: store.welcomeMessage }), _jsx(SuggestedQuestions, { questions: store.suggestedQuestions, controller: controller })] })), store.currentChat?.chat
1420
1589
  .filter((chatItem) => chatItem.messageType !== 'productQuery')
1421
1590
  .map((chatItem, index) => (_jsx("div", { className: `ss__chat__message ss__chat__message--${chatItem.messageType}`, children: {
1422
- user: (_jsx(MessageUser, { chatItem: chatItem, controller: controller, onViewProduct: isMobile ? () => setMobileProductInfoOpen(true) : undefined })),
1423
- text: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onViewProduct: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat })),
1424
- content: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onViewProduct: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat })),
1425
- productSearchResult: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onViewProduct: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat })),
1426
- inspirationResult: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onViewProduct: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat })),
1427
- productAnswer: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onViewProduct: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat })),
1591
+ user: (_jsx(MessageUser, { chatItem: chatItem, controller: controller, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined, primaryColor: colorPrimary, primaryColorText: colorPrimaryText })),
1592
+ text: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText })),
1593
+ content: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText })),
1594
+ productSearchResult: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText })),
1595
+ inspirationResult: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText })),
1596
+ productAnswer: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText })),
1428
1597
  productComparison: (() => {
1429
1598
  // On mobile, only the first productComparison in the session
1430
1599
  // auto-opens the secondary panel. Subsequent ones get a
1431
1600
  // prominent "Show Details" button instead.
1432
1601
  const comparisonMessages = (store.currentChat?.chat || []).filter((m) => m.messageType === 'productComparison');
1433
1602
  const isFirst = comparisonMessages.length > 0 && comparisonMessages[0].id === chatItem.id;
1434
- return (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onViewProduct: isMobile ? () => setMobileProductInfoOpen(true) : undefined, showDetailsButton: isMobile && !isFirst, sideChatOpen: !!shouldShowSideChat }));
1603
+ return (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined, showDetailsButton: isMobile && !isFirst, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText }));
1435
1604
  })(),
1436
- productRecommendation: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onViewProduct: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat })),
1605
+ productRecommendation: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText })),
1437
1606
  actions: _jsx(SuggestedQuestions, { actions: chatItem.actions, controller: controller }),
1438
- errorResponse: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, sideChatOpen: !!shouldShowSideChat })),
1439
- topicDrift: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, sideChatOpen: !!shouldShowSideChat })),
1607
+ errorResponse: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText })),
1608
+ topicDrift: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText })),
1440
1609
  productQuery: null,
1441
1610
  }[chatItem.messageType] || null }, index))), _jsx("div", { className: "ss__chat__messages__end", ref: messagesEndRef }), showNewMessages && messagesOverflow && (_jsxs("div", { className: "ss__chat__new-messages", onClick: () => {
1442
1611
  scrollToBottom();
1443
1612
  setShowNewMessages(false);
1444
- }, children: [_jsx(Icon, { icon: "angle-down", size: "12px" }), _jsx("span", { children: "New messages" })] }))] }), _jsx(ChatLoadingIndicator, { loading: store.loading, verbs: loadingVerbs }), !store.currentChat?.isExpired ? (_jsxs("div", { className: "ss__chat__content__footer", ref: footerRef, children: [store.error && _jsx("div", { className: "ss__chat__error", children: store.error.message }), store.currentChat?.sessionLimitReached && (_jsxs("div", { className: 'ss__chat__topic-drift', children: [_jsx(Icon, { icon: "info", size: "18px", className: 'ss__chat__topic-drift__icon--info' }), _jsxs("div", { className: 'ss__chat__topic-drift__text', children: [_jsx("span", { children: "Session limit reached" }), _jsx("span", { children: "This chat has reached its maximum number of interactions. Start a new session to continue." })] }), _jsx(Button, { className: 'ss__chat__topic-drift__button', onClick: () => {
1445
- controller.store.createChat();
1446
- }, children: "New Session" })] })), store.currentChat?.actions && store.currentChat.actions.length > 0 && (_jsx("div", { className: 'ss__chat__actions', children: store.currentChat?.actions.map((action, index) => (_jsx("div", { className: "ss__chat__actions__wrap", children: {
1447
- facets: action.data.length ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "ss__chat__actions__facets-header", children: [_jsx("div", { className: "ss__chat__actions--title", children: "Filter by:" }), multiselectFacets && (_jsx("div", { className: `ss__chat__actions__facets-apply${store.currentChat?.attachments.attached.some((item) => item.type === 'facet') ||
1448
- (store.currentChat?.removedFacets && store.currentChat.removedFacets.length > 0)
1449
- ? ' ss__chat__actions__facets-apply--active'
1450
- : ''}`, children: _jsx(Button, { onClick: () => {
1451
- controller.search();
1452
- }, children: "Apply" }) }))] }), _jsx("div", { className: "ss__chat__actions--facets", children: action.data.slice(0, 10).map((facet, idx) => {
1453
- if (!facet.values?.length)
1454
- return null;
1455
- return (_jsx("div", { className: `ss__chat__actions__facet ss__chat__actions__facet--${facet.type}`, children: _jsx(Dropdown, { usePortal: true, dropUp: true, button: _jsx(FacetButton, { label: getFacetButtonLabel(facet) }), style: {
1456
- '.ss__dropdown__content': {
1457
- width: '150px',
1458
- maxHeight: '200px',
1459
- overflowY: 'auto',
1460
- background: 'white',
1461
- boxShadow: '0px 3px 6px 0px rgba(0, 0, 0, 0.2)',
1462
- borderRadius: '6px',
1463
- ...(multiselectFacets
1464
- ? {
1465
- '.ss__chat__actions__facet__option--checkbox': {
1613
+ }, children: [_jsx(Icon, { icon: "angle-down", size: "12px" }), _jsx("span", { children: "New messages" })] }))] }), _jsx(ChatLoadingIndicator, { loading: store.loading, verbs: loadingVerbs }), !store.currentChat?.isExpired ? ((() => {
1614
+ const dropEnabled = store.features.imageSearch.enabled && !store.loading && !store.blocked && !store.currentChat?.sessionLimitReached;
1615
+ const hasFiles = (e) => Array.from(e.dataTransfer?.types || []).includes('Files');
1616
+ return (_jsxs("div", { className: "ss__chat__content__footer", ref: footerRef, onDragEnter: (e) => {
1617
+ if (!dropEnabled || !hasFiles(e))
1618
+ return;
1619
+ e.preventDefault();
1620
+ dragCounterRef.current += 1;
1621
+ setIsDraggingFile(true);
1622
+ }, onDragOver: (e) => {
1623
+ if (!dropEnabled || !hasFiles(e))
1624
+ return;
1625
+ // Required to allow the drop event to fire
1626
+ e.preventDefault();
1627
+ if (e.dataTransfer)
1628
+ e.dataTransfer.dropEffect = 'copy';
1629
+ }, onDragLeave: (e) => {
1630
+ if (!dropEnabled || !hasFiles(e))
1631
+ return;
1632
+ dragCounterRef.current = Math.max(0, dragCounterRef.current - 1);
1633
+ if (dragCounterRef.current === 0)
1634
+ setIsDraggingFile(false);
1635
+ }, onDrop: async (e) => {
1636
+ if (!dropEnabled || !hasFiles(e))
1637
+ return;
1638
+ e.preventDefault();
1639
+ dragCounterRef.current = 0;
1640
+ setIsDraggingFile(false);
1641
+ const dropped = Array.from(e.dataTransfer?.files || []);
1642
+ const images = dropped.filter((f) => f.type.startsWith('image/'));
1643
+ if (images.length === 0)
1644
+ return;
1645
+ // Reconstruct a FileList — controller.upload expects FileList | null
1646
+ const dt = new DataTransfer();
1647
+ images.forEach((f) => dt.items.add(f));
1648
+ await controller.upload(dt.files);
1649
+ }, children: [store.error && _jsx("div", { className: "ss__chat__error", children: store.error.message }), store.currentChat?.sessionLimitReached && (_jsxs("div", { className: 'ss__chat__topic-drift', children: [_jsx(Icon, { icon: "info", size: "18px", className: 'ss__chat__topic-drift__icon--info' }), _jsxs("div", { className: 'ss__chat__topic-drift__text', children: [_jsx("span", { children: "Session limit reached" }), _jsx("span", { children: "This chat has reached its maximum number of interactions. Start a new session to continue." })] }), _jsx(Button, { className: 'ss__chat__topic-drift__button', onClick: () => {
1650
+ controller.store.createChat();
1651
+ }, children: "New Session" })] })), store.facets && store.facets.length > 0 && (_jsx("div", { className: 'ss__chat__actions', children: _jsxs("div", { className: "ss__chat__actions__wrap", children: [_jsxs("div", { className: "ss__chat__actions__facets-header", children: [_jsx("div", { className: "ss__chat__actions--title", children: "Filter by:" }), multiselectFacets && store.hasPendingFacetChanges && (_jsx("div", { className: 'ss__chat__actions__facets-apply ss__chat__actions__facets-apply--active', children: _jsx(Button, { onClick: () => {
1652
+ controller.search();
1653
+ }, children: "Apply" }) }))] }), _jsx("div", { className: "ss__chat__actions--facets", children: store.facets.slice(0, 10).map((facet, idx) => {
1654
+ // range/slider facets render via FacetSlider; everything else needs at least one value to be useful
1655
+ if (facet.type !== 'range' && !facet.values?.length)
1656
+ return null;
1657
+ if (facet.type === 'range') {
1658
+ return _jsx(SliderFacetDropdown, { facet: facet, label: getFacetButtonLabel(facet) }, idx);
1659
+ }
1660
+ return (_jsx("div", { className: `ss__chat__actions__facet ss__chat__actions__facet--${facet.type}`, children: _jsx(Dropdown, { usePortal: true, dropUp: true, button: _jsx(FacetButton, { label: getFacetButtonLabel(facet) }), style: {
1661
+ '.ss__dropdown__content': {
1662
+ width: '150px',
1663
+ maxHeight: '200px',
1664
+ overflowY: 'auto',
1665
+ background: 'white',
1666
+ boxShadow: '0px 3px 6px 0px rgba(0, 0, 0, 0.2)',
1667
+ borderRadius: '6px',
1668
+ ...(multiselectFacets
1669
+ ? {
1670
+ '.ss__chat__actions__facet__option--checkbox': {
1671
+ display: 'flex',
1672
+ alignItems: 'center',
1673
+ gap: '8px',
1674
+ padding: '6px 10px',
1675
+ cursor: 'pointer',
1676
+ width: '100%',
1677
+ boxSizing: 'border-box',
1678
+ background: '#fff',
1679
+ border: 'none',
1680
+ borderBottom: '1px solid #f0f0f0',
1681
+ '&:hover': {
1682
+ background: new Colour(colorPrimary).lightenHex(0.95),
1683
+ },
1684
+ '&:last-child': {
1685
+ borderBottom: 'none',
1686
+ },
1687
+ '.ss__chat__actions__facet__option__checkbox': {
1688
+ width: '16px',
1689
+ height: '16px',
1690
+ borderRadius: '3px',
1691
+ border: '2px solid #ccc',
1466
1692
  display: 'flex',
1467
1693
  alignItems: 'center',
1468
- gap: '8px',
1469
- padding: '6px 10px',
1470
- cursor: 'pointer',
1471
- width: '100%',
1472
- boxSizing: 'border-box',
1473
- background: '#fff',
1474
- border: 'none',
1475
- borderBottom: '1px solid #f0f0f0',
1476
- '&:hover': {
1477
- background: '#f4f4ff',
1478
- },
1479
- '&:last-child': {
1480
- borderBottom: 'none',
1481
- },
1482
- '.ss__chat__actions__facet__option__checkbox': {
1483
- width: '16px',
1484
- height: '16px',
1485
- borderRadius: '3px',
1486
- border: '2px solid #ccc',
1487
- display: 'flex',
1488
- alignItems: 'center',
1489
- justifyContent: 'center',
1490
- flexShrink: 0,
1491
- '&.ss__chat__actions__facet__option__checkbox--checked': {
1492
- background: '#253B80',
1493
- borderColor: '#253B80',
1694
+ justifyContent: 'center',
1695
+ flexShrink: 0,
1696
+ '&.ss__chat__actions__facet__option__checkbox--checked': {
1697
+ background: colorPrimary,
1698
+ borderColor: colorPrimary,
1699
+ color: colorPrimaryText,
1700
+ svg: {
1701
+ fill: colorPrimaryText,
1702
+ stroke: colorPrimaryText,
1494
1703
  },
1495
1704
  },
1496
- '.ss__chat__actions__facet__option__label': {
1497
- fontSize: '14px',
1498
- color: '#333',
1499
- flex: '1 1 auto',
1500
- textAlign: 'left',
1501
- },
1502
1705
  },
1503
- }
1504
- : {
1505
- '.ss__button': {
1506
- width: '100%',
1507
- border: 'none',
1508
- borderRadius: 0,
1509
- boxSizing: 'border-box',
1510
- background: '#fff',
1511
- '&:hover': {
1512
- background: '#f4f4ff',
1513
- },
1706
+ '.ss__chat__actions__facet__option__label': {
1707
+ fontSize: '14px',
1708
+ color: '#333',
1709
+ flex: '1 1 auto',
1710
+ textAlign: 'left',
1514
1711
  },
1515
- }),
1516
- },
1517
- }, children: _jsx("div", { className: "ss__chat__actions__facet__options", children: facet.type === 'range-buckets'
1518
- ? facet.values.map((option) => {
1519
- const rangeOption = option;
1520
- const optionValue = `${rangeOption.low ?? '*'}:${rangeOption.high ?? '*'}`;
1521
- if (multiselectFacets) {
1522
- const isSelected = (rangeOption.filtered && !controller.store.isFacetRemoved(facet.field, optionValue)) ||
1523
- controller.store.isFacetSelected(facet.field, optionValue);
1524
- return (_jsxs("div", { className: "ss__chat__actions__facet__option--checkbox", onClick: () => {
1525
- if (isSelected) {
1526
- controller.store.removeFacet(facet.field, optionValue);
1527
- }
1528
- else {
1529
- controller.store.addFacet({
1530
- key: facet.field,
1531
- facetLabel: facet.label,
1532
- value: optionValue,
1533
- label: rangeOption.label,
1534
- count: rangeOption.count,
1535
- });
1536
- }
1537
- }, children: [_jsx("div", { className: classnames('ss__chat__actions__facet__option__checkbox', {
1538
- 'ss__chat__actions__facet__option__checkbox--checked': isSelected,
1539
- }), children: isSelected && _jsx(Icon, { icon: "check-thin", size: "10px" }) }), _jsx("span", { className: "ss__chat__actions__facet__option__label", children: rangeOption.label })] }, optionValue));
1540
- }
1541
- return (_jsx(Button, { onClick: () => {
1542
- controller.store.addFacet({
1543
- key: facet.field,
1544
- facetLabel: facet.label,
1545
- value: optionValue,
1546
- label: rangeOption.label,
1547
- count: rangeOption.count,
1548
- });
1549
- controller.search();
1550
- }, children: rangeOption.label }, optionValue));
1551
- })
1552
- : facet.values.map((option) => {
1553
- const valueOption = option;
1554
- const optionValue = valueOption.value || valueOption.label;
1555
- if (multiselectFacets) {
1556
- const isSelected = (valueOption.filtered && !controller.store.isFacetRemoved(facet.field, optionValue)) ||
1557
- controller.store.isFacetSelected(facet.field, optionValue);
1558
- return (_jsxs("div", { className: "ss__chat__actions__facet__option--checkbox", onClick: () => {
1559
- if (isSelected) {
1560
- controller.store.removeFacet(facet.field, optionValue);
1561
- }
1562
- else {
1563
- controller.store.addFacet({
1564
- key: facet.field,
1565
- facetLabel: facet.label,
1566
- value: optionValue,
1567
- label: valueOption.label,
1568
- count: valueOption.count,
1569
- });
1570
- }
1571
- }, children: [_jsx("div", { className: classnames('ss__chat__actions__facet__option__checkbox', {
1572
- 'ss__chat__actions__facet__option__checkbox--checked': isSelected,
1573
- }), children: isSelected && _jsx(Icon, { icon: "check-thin", size: "10px" }) }), _jsx("span", { className: "ss__chat__actions__facet__option__label", children: valueOption.label })] }, optionValue));
1574
- }
1575
- return (_jsx(Button, { onClick: () => {
1576
- controller.store.addFacet({
1577
- key: facet.field,
1578
- facetLabel: facet.label,
1579
- value: optionValue,
1580
- label: valueOption.label,
1581
- count: valueOption.count,
1582
- });
1583
- controller.search();
1584
- }, children: valueOption.label }, optionValue));
1585
- }) }) }, facet.field) }, idx));
1586
- }) })] })) : null,
1587
- actions: (_jsx("div", { className: "ss__chat__actions--suggested" })),
1588
- }[action.type] || null }, index))) })), (() => {
1589
- const activeComparisonSearchResults = shouldShowSideChat && activeMessage?.messageType === 'productComparison'
1590
- ? activeMessage.searchResults || []
1591
- : null;
1592
- const showCommittedComparisons = !activeComparisonSearchResults &&
1593
- store.currentChat?.comparisons.committed &&
1594
- store.currentChat.comparisons.committed.length > 0 &&
1595
- (activeMessage?.messageType === 'user' ||
1596
- activeMessage?.messageType === 'productComparison' ||
1597
- activeMessage?.messageType === 'productQuery');
1598
- const visibleAttachments = store.currentChat?.attachments.attached.filter((item) => item.state === 'attached' || item.state === 'active' || item.state === 'loading' || item.state === 'error') || [];
1599
- const productAttachments = visibleAttachments.filter((item) => item.type === 'product' &&
1600
- item.requestType !== 'productSimilar' &&
1601
- item.requestType !== 'productComparison');
1602
- const imageAttachments = visibleAttachments.filter((item) => item.type === 'image');
1603
- const comparisonItems = activeComparisonSearchResults
1604
- ? activeComparisonSearchResults.map((result) => {
1605
- const d = result?.display || result;
1606
- return {
1607
- id: result?.id,
1608
- name: d?.mappings?.core?.name || '',
1609
- imageUrl: d?.mappings?.core?.thumbnailImageUrl || d?.mappings?.core?.imageUrl || '',
1610
- onClick: isMobile
1611
- ? () => {
1612
- controller.viewProduct(result);
1613
- setMobileProductInfoOpen(true);
1614
- }
1615
- : undefined,
1616
- };
1617
- })
1618
- : showCommittedComparisons
1619
- ? (store.currentChat?.comparisons.committed || []).map((comparisonItem) => {
1620
- const d = comparisonItem?.result?.display || comparisonItem?.result;
1712
+ },
1713
+ }
1714
+ : {
1715
+ '.ss__button': {
1716
+ width: '100%',
1717
+ border: 'none',
1718
+ borderRadius: 0,
1719
+ boxSizing: 'border-box',
1720
+ background: '#fff',
1721
+ '&:hover': {
1722
+ background: new Colour(colorPrimary).lightenHex(0.95),
1723
+ },
1724
+ },
1725
+ }),
1726
+ },
1727
+ }, children: _jsx("div", { className: "ss__chat__actions__facet__options", children: facet.type === 'range-buckets'
1728
+ ? facet.values.map((option) => {
1729
+ const rangeOption = option;
1730
+ const optionValue = `${rangeOption.low ?? '*'}:${rangeOption.high ?? '*'}`;
1731
+ if (multiselectFacets) {
1732
+ const isSelected = controller.store.isFacetSelected(facet.field, optionValue);
1733
+ return (_jsxs("div", { className: "ss__chat__actions__facet__option--checkbox", onClick: () => {
1734
+ if (isSelected) {
1735
+ controller.store.removeFacet(facet.field, optionValue);
1736
+ }
1737
+ else {
1738
+ controller.store.addFacet({
1739
+ key: facet.field,
1740
+ value: optionValue,
1741
+ });
1742
+ }
1743
+ }, children: [_jsx("div", { className: classnames('ss__chat__actions__facet__option__checkbox', {
1744
+ 'ss__chat__actions__facet__option__checkbox--checked': isSelected,
1745
+ }), children: isSelected && _jsx(Icon, { icon: "check-thin", size: "10px" }) }), _jsx("span", { className: "ss__chat__actions__facet__option__label", children: rangeOption.label })] }, optionValue));
1746
+ }
1747
+ return (_jsx(Button, { onClick: () => {
1748
+ controller.store.addFacet({
1749
+ key: facet.field,
1750
+ value: optionValue,
1751
+ });
1752
+ controller.search();
1753
+ }, children: rangeOption.label }, optionValue));
1754
+ })
1755
+ : facet.values.map((option) => {
1756
+ const valueOption = option;
1757
+ const optionValue = valueOption.value || valueOption.label;
1758
+ if (multiselectFacets) {
1759
+ const isSelected = controller.store.isFacetSelected(facet.field, optionValue);
1760
+ return (_jsxs("div", { className: "ss__chat__actions__facet__option--checkbox", onClick: () => {
1761
+ if (isSelected) {
1762
+ controller.store.removeFacet(facet.field, optionValue);
1763
+ }
1764
+ else {
1765
+ controller.store.addFacet({
1766
+ key: facet.field,
1767
+ value: optionValue,
1768
+ });
1769
+ }
1770
+ }, children: [_jsx("div", { className: classnames('ss__chat__actions__facet__option__checkbox', {
1771
+ 'ss__chat__actions__facet__option__checkbox--checked': isSelected,
1772
+ }), children: isSelected && _jsx(Icon, { icon: "check-thin", size: "10px" }) }), _jsx("span", { className: "ss__chat__actions__facet__option__label", children: valueOption.label })] }, optionValue));
1773
+ }
1774
+ return (_jsx(Button, { onClick: () => {
1775
+ controller.store.addFacet({
1776
+ key: facet.field,
1777
+ value: optionValue,
1778
+ });
1779
+ controller.search();
1780
+ }, children: valueOption.label }, optionValue));
1781
+ }) }) }, facet.field) }, idx));
1782
+ }) })] }) })), (() => {
1783
+ const activeComparisonSearchResults = shouldShowSideChat && activeMessage?.messageType === 'productComparison'
1784
+ ? activeMessage.searchResults || []
1785
+ : null;
1786
+ const showCommittedComparisons = !activeComparisonSearchResults &&
1787
+ store.currentChat?.comparisons.committed &&
1788
+ store.currentChat.comparisons.committed.length > 0 &&
1789
+ (activeMessage?.messageType === 'user' ||
1790
+ activeMessage?.messageType === 'productComparison' ||
1791
+ activeMessage?.messageType === 'productQuery');
1792
+ const visibleAttachments = store.currentChat?.attachments.attached.filter((item) => item.state === 'attached' || item.state === 'active' || item.state === 'loading' || item.state === 'error') || [];
1793
+ const productAttachments = visibleAttachments.filter((item) => item.type === 'product' &&
1794
+ item.requestType !== 'productSimilar' &&
1795
+ item.requestType !== 'productComparison');
1796
+ const imageAttachments = visibleAttachments.filter((item) => item.type === 'image');
1797
+ const comparisonItems = activeComparisonSearchResults
1798
+ ? activeComparisonSearchResults.map((result) => {
1799
+ const d = result?.display || result;
1621
1800
  return {
1622
- id: comparisonItem.result?.id,
1801
+ id: result?.id,
1623
1802
  name: d?.mappings?.core?.name || '',
1624
1803
  imageUrl: d?.mappings?.core?.thumbnailImageUrl || d?.mappings?.core?.imageUrl || '',
1625
1804
  onClick: isMobile
1626
1805
  ? () => {
1627
- controller.viewProduct(comparisonItem.result);
1806
+ controller.productQuickView(result);
1628
1807
  setMobileProductInfoOpen(true);
1629
1808
  }
1630
1809
  : undefined,
1631
1810
  };
1632
1811
  })
1633
- : [];
1634
- const productItems = productAttachments.map((item) => ({
1635
- id: item.id,
1636
- name: item.name || '',
1637
- imageUrl: item.thumbnailUrl || '',
1638
- onClick: isMobile
1639
- ? () => {
1640
- setMobileProductInfoOpen(true);
1641
- }
1642
- : () => {
1643
- store.currentChat?.setActiveMessage(store.currentChat?.activeMessage?.id || '');
1812
+ : showCommittedComparisons
1813
+ ? (store.currentChat?.comparisons.committed || []).map((comparisonItem) => {
1814
+ const d = comparisonItem?.result?.display || comparisonItem?.result;
1815
+ return {
1816
+ id: comparisonItem.result?.id,
1817
+ name: d?.mappings?.core?.name || '',
1818
+ imageUrl: d?.mappings?.core?.thumbnailImageUrl || d?.mappings?.core?.imageUrl || '',
1819
+ onClick: isMobile
1820
+ ? () => {
1821
+ controller.productQuickView(comparisonItem.result);
1822
+ setMobileProductInfoOpen(true);
1823
+ }
1824
+ : undefined,
1825
+ };
1826
+ })
1827
+ : [];
1828
+ const productItems = productAttachments.map((item) => ({
1829
+ id: item.id,
1830
+ name: item.name || '',
1831
+ imageUrl: item.thumbnailUrl || '',
1832
+ onClick: isMobile
1833
+ ? () => {
1834
+ setMobileProductInfoOpen(true);
1835
+ }
1836
+ : () => {
1837
+ store.currentChat?.setActiveMessage(store.currentChat?.activeMessage?.id || '');
1838
+ },
1839
+ onRemove: () => {
1840
+ store.currentChat?.attachments.remove(item.id);
1841
+ setMobileProductInfoOpen(false);
1842
+ store.currentChat?.dismissSideChat();
1644
1843
  },
1645
- onRemove: () => {
1646
- store.currentChat?.attachments.remove(item.id);
1647
- setMobileProductInfoOpen(false);
1648
- store.currentChat?.dismissSideChat();
1649
- },
1650
- }));
1651
- const imageItems = imageAttachments.map((item) => ({
1652
- id: item.id,
1653
- name: item.fileName || 'Image',
1654
- imageUrl: item.base64 || item.thumbnailUrl || '',
1655
- isLoading: item.state === 'loading',
1656
- hasError: !!item.error,
1657
- errorMessage: item.error?.message,
1658
- onRemove: () => store.currentChat?.attachments.remove(item.id),
1659
- }));
1660
- const productTitle = productItems.length > 1 ? 'Compare these products' : 'Ask about this product' + (isMobile ? '' : ' (click for details)');
1661
- const hasImageError = imageItems.some((item) => item.hasError);
1662
- const imageTitle = imageItems.length > 0 && !hasImageError ? 'Find products similar to this image:' : '';
1663
- return (_jsxs(_Fragment, { children: [comparisonItems.length > 0 && (_jsx(ChatAttachmentContext, { title: 'Compare these products', items: comparisonItems, onClose: () => {
1664
- store.currentChat?.comparisons.resetCommitted();
1665
- store.currentChat?.dismissSideChat();
1666
- } })), productItems.length > 0 && (_jsx(ChatAttachmentContext, { title: productTitle, items: productItems, onClose: () => {
1667
- productAttachments.forEach((item) => store.currentChat?.attachments.remove(item.id));
1668
- setMobileProductInfoOpen(false);
1669
- store.currentChat?.dismissSideChat();
1670
- } })), imageItems.length > 0 && _jsx(ChatAttachmentContext, { title: imageTitle, items: imageItems })] }));
1671
- })(), (() => {
1672
- const drift = store.currentChat?.topicDrift;
1673
- if (!drift)
1674
- return null;
1675
- // recommendedAction is the prescription; driftType is the diagnosis.
1676
- // Hide the banner when the backend says to keep flowing, or when no drift was detected.
1677
- if (drift.recommendedAction === 'CONTINUE' || drift.driftType === 'NO_DRIFT')
1678
- return null;
1679
- const isScopeRedirect = drift.recommendedAction === 'SCOPE_REDIRECT';
1680
- const primaryText = isScopeRedirect ? "I'm here to help with shopping" : 'Looking for something new?';
1681
- const secondaryText = isScopeRedirect
1682
- ? 'Try asking about products, comparisons, or recommendations'
1683
- : 'Start a fresh session for better assistance, or keep going in this one?';
1684
- const buttonText = isScopeRedirect ? '' : 'New Session';
1685
- return (_jsxs("div", { className: 'ss__chat__topic-drift', children: [_jsx(Icon, { icon: "info", size: "18px", className: 'ss__chat__topic-drift__icon--info' }), _jsxs("div", { className: 'ss__chat__topic-drift__text', children: [_jsx("span", { children: primaryText }), _jsx("span", { children: secondaryText })] }), buttonText && (_jsx(Button, { className: 'ss__chat__topic-drift__button', onClick: () => {
1686
- if (isScopeRedirect) {
1687
- store.currentChat?.dismissTopicDrift();
1688
- return;
1689
- }
1690
- const messageText = store.currentChat?.handleTopicDrift();
1691
- if (messageText) {
1692
- controller.store.createChat();
1693
- controller.search({ data: { message: messageText } });
1694
- }
1695
- }, children: buttonText })), _jsx("span", { onClick: () => {
1696
- store.currentChat?.dismissTopicDrift();
1697
- }, children: _jsx(Icon, { icon: "close-thin", size: "14px", className: 'ss__chat__topic-drift__icon--close' }) })] }));
1698
- })(), _jsxs("div", { className: 'ss__chat__input', children: [_jsxs("div", { className: 'ss__chat__input__input', children: [_jsx("input", { type: "text", name: "ss-chat-input", disabled: store.loading || store.blocked || store.currentChat?.sessionLimitReached, placeholder: (() => {
1699
- const comparedCount = store.currentChat?.comparisons.compared.length || 0;
1700
- const committedCount = store.currentChat?.comparisons.committed.length || 0;
1701
- const attached = store.currentChat?.attachments.attached.filter((item) => item.state === 'attached' || item.state === 'active') || [];
1702
- const attachedProducts = attached.filter((item) => item.type === 'product');
1703
- const attachedImages = attached.filter((item) => item.type === 'image' && !item.error);
1704
- if (attachedProducts.length === 1) {
1705
- return 'Ask about this product...';
1706
- }
1707
- if (comparedCount > 1 || attachedProducts.length > 1) {
1708
- return 'What would you like to compare?';
1709
- }
1710
- if (committedCount > 0) {
1711
- return 'Ask about the compared products...';
1712
- }
1713
- if (attachedImages.length > 0) {
1714
- return 'Ask about this image...';
1715
- }
1716
- if (comparedCount === 1) {
1717
- return 'Add another product to compare...';
1718
- }
1719
- return 'Type your message...';
1720
- })(), onInput: (e) => controller.handlers.input.input(e), onKeyDown: (e) => {
1721
- controller.handlers.input.enterKey(e);
1722
- if (e.keyCode === 13 && isMobile && mobileProductInfoOpen) {
1723
- setMobileProductInfoOpen(false);
1724
- }
1725
- }, value: controller.store.inputValue }), store.features.imageSearch.enabled && (_jsxs(_Fragment, { children: [_jsx(Button, { className: 'ss__chat__upload-button', disabled: store.loading || store.blocked || store.currentChat?.sessionLimitReached, onClick: () => fileInputRef.current?.click(), icon: { icon: 'image', title: 'Upload Image' } }), _jsx("input", { ref: fileInputRef, onChange: async (e) => {
1726
- await controller.upload(e.target.files);
1727
- // reset value
1728
- e.target.value = '';
1729
- }, multiple: true, type: "file", accept: "image/*", className: "ss__chat__input__input__file" })] }))] }), _jsx("div", { className: 'ss__chat__input__actions', children: (() => {
1730
- const hasImageAttachment = (store.currentChat?.attachments.attached || []).some((item) => item.type === 'image' && !item.error);
1731
- const messageEmpty = !controller.store.inputValue.trim();
1732
- const sendDisabled = store.blocked || store.currentChat?.sessionLimitReached || (hasImageAttachment && messageEmpty) || messageEmpty;
1733
- return (_jsx(Button, { className: "ss__chat__send-button", icon: { icon: 'send', title: 'Send Message' }, disabled: sendDisabled, onClick: () => {
1734
- if (sendDisabled)
1844
+ }));
1845
+ const imageItems = imageAttachments.map((item) => ({
1846
+ id: item.id,
1847
+ name: item.fileName || 'Image',
1848
+ imageUrl: item.base64 || item.thumbnailUrl || '',
1849
+ isLoading: item.state === 'loading',
1850
+ hasError: !!item.error,
1851
+ errorMessage: item.error?.message,
1852
+ onRemove: () => store.currentChat?.attachments.remove(item.id),
1853
+ }));
1854
+ const productTitle = productItems.length > 1 ? 'Compare these products' : 'Ask about this product' + (isMobile ? '' : ' (click for details)');
1855
+ const hasImageError = imageItems.some((item) => item.hasError);
1856
+ const imageTitle = imageItems.length > 0 && !hasImageError ? 'Find products similar to this image:' : '';
1857
+ return (_jsxs(_Fragment, { children: [comparisonItems.length > 0 && (_jsx(ChatAttachmentContext, { title: 'Compare these products', items: comparisonItems, onClose: () => {
1858
+ store.currentChat?.comparisons.resetCommitted();
1859
+ store.currentChat?.dismissSideChat();
1860
+ } })), productItems.length > 0 && (_jsx(ChatAttachmentContext, { title: productTitle, items: productItems, onClose: () => {
1861
+ productAttachments.forEach((item) => store.currentChat?.attachments.remove(item.id));
1862
+ setMobileProductInfoOpen(false);
1863
+ store.currentChat?.dismissSideChat();
1864
+ } })), imageItems.length > 0 && _jsx(ChatAttachmentContext, { title: imageTitle, items: imageItems })] }));
1865
+ })(), (() => {
1866
+ const drift = store.currentChat?.topicDrift;
1867
+ if (!drift)
1868
+ return null;
1869
+ // recommendedAction is the prescription; driftType is the diagnosis.
1870
+ // Hide the banner when the backend says to keep flowing, or when no drift was detected.
1871
+ if (drift.recommendedAction === 'CONTINUE' || drift.driftType === 'NO_DRIFT')
1872
+ return null;
1873
+ const isScopeRedirect = drift.recommendedAction === 'SCOPE_REDIRECT';
1874
+ const primaryText = isScopeRedirect ? "I'm here to help with shopping" : 'Looking for something new?';
1875
+ const secondaryText = isScopeRedirect
1876
+ ? 'Try asking about products, comparisons, or recommendations'
1877
+ : 'Start a fresh session for better assistance, or keep going in this one?';
1878
+ const buttonText = isScopeRedirect ? '' : 'New Session';
1879
+ return (_jsxs("div", { className: 'ss__chat__topic-drift', children: [_jsx(Icon, { icon: "info", size: "18px", className: 'ss__chat__topic-drift__icon--info' }), _jsxs("div", { className: 'ss__chat__topic-drift__text', children: [_jsx("span", { children: primaryText }), _jsx("span", { children: secondaryText })] }), buttonText && (_jsx(Button, { className: 'ss__chat__topic-drift__button', onClick: () => {
1880
+ if (isScopeRedirect) {
1881
+ store.currentChat?.dismissTopicDrift();
1735
1882
  return;
1736
- controller.search();
1737
- if (isMobile && mobileProductInfoOpen) {
1738
- setMobileProductInfoOpen(false);
1739
1883
  }
1740
- } }));
1741
- })() })] }), _jsx("div", { className: 'ss__chat__disclaimer', children: _jsxs("i", { children: ["Powered by Athos Commerce. AI-powered assistant. It sometimes make mistakes. Avoid sharing personal data.", ' ', _jsx("a", { href: "https://athoscommerce.com/legal/privacy-policy/", target: "_blank", rel: "noopener noreferrer", children: "Privacy Policy" })] }) })] })) : (_jsx("div", { children: "This chat is expired. Please start a new chat." }))] })] })) : null] }), _jsx(Overlay, { style: { zIndex: 1001 }, color: "transparent", active: store.open, onClick: () => controller.handlers.button.click() })] }) }));
1884
+ const messageText = store.currentChat?.handleTopicDrift();
1885
+ if (messageText) {
1886
+ controller.store.createChat();
1887
+ controller.search({ data: { message: messageText } });
1888
+ }
1889
+ }, children: buttonText })), _jsx("span", { onClick: () => {
1890
+ store.currentChat?.dismissTopicDrift();
1891
+ }, children: _jsx(Icon, { icon: "close-thin", size: "14px", className: 'ss__chat__topic-drift__icon--close' }) })] }));
1892
+ })(), _jsxs("div", { className: 'ss__chat__input', children: [_jsxs("div", { className: 'ss__chat__input__input', children: [_jsx("input", { type: "text", name: "ss-chat-input", disabled: store.loading || store.blocked || store.currentChat?.sessionLimitReached, placeholder: (() => {
1893
+ const comparedCount = store.currentChat?.comparisons.compared.length || 0;
1894
+ const committedCount = store.currentChat?.comparisons.committed.length || 0;
1895
+ const attached = store.currentChat?.attachments.attached.filter((item) => item.state === 'attached' || item.state === 'active') ||
1896
+ [];
1897
+ const attachedProducts = attached.filter((item) => item.type === 'product');
1898
+ const attachedImages = attached.filter((item) => item.type === 'image' && !item.error);
1899
+ if (attachedProducts.length === 1) {
1900
+ return 'Ask about this product...';
1901
+ }
1902
+ if (comparedCount > 1 || attachedProducts.length > 1) {
1903
+ return 'What would you like to compare?';
1904
+ }
1905
+ if (committedCount > 0) {
1906
+ return 'Ask about the compared products...';
1907
+ }
1908
+ if (attachedImages.length > 0) {
1909
+ return 'Ask about this image...';
1910
+ }
1911
+ if (comparedCount === 1) {
1912
+ return 'Add another product to compare...';
1913
+ }
1914
+ return 'Type your message...';
1915
+ })(), onInput: (e) => controller.handlers.input.input(e), onKeyDown: (e) => {
1916
+ controller.handlers.input.enterKey(e);
1917
+ if (e.keyCode === 13 && isMobile && mobileProductInfoOpen) {
1918
+ setMobileProductInfoOpen(false);
1919
+ }
1920
+ }, value: controller.store.inputValue }), store.features.imageSearch.enabled && (_jsxs(_Fragment, { children: [_jsx(Button, { className: 'ss__chat__upload-button', disabled: store.loading || store.blocked || store.currentChat?.sessionLimitReached, onClick: () => fileInputRef.current?.click(), icon: { icon: 'image', title: 'Upload Image' } }), _jsx("input", { ref: fileInputRef, onChange: async (e) => {
1921
+ await controller.upload(e.target.files);
1922
+ // reset value
1923
+ e.target.value = '';
1924
+ }, multiple: true, type: "file", accept: "image/*", className: "ss__chat__input__input__file" })] }))] }), _jsx("div", { className: 'ss__chat__input__actions', children: (() => {
1925
+ const hasImageAttachment = (store.currentChat?.attachments.attached || []).some((item) => item.type === 'image' && !item.error);
1926
+ const messageEmpty = !controller.store.inputValue.trim();
1927
+ const sendDisabled = store.blocked || store.currentChat?.sessionLimitReached || (hasImageAttachment && messageEmpty) || messageEmpty;
1928
+ return (_jsx(Button, { className: "ss__chat__send-button", icon: { icon: 'send', title: 'Send Message' }, disabled: sendDisabled, onClick: () => {
1929
+ if (sendDisabled)
1930
+ return;
1931
+ controller.search();
1932
+ if (isMobile && mobileProductInfoOpen) {
1933
+ setMobileProductInfoOpen(false);
1934
+ }
1935
+ } }));
1936
+ })() })] }), _jsx("div", { className: 'ss__chat__disclaimer', children: _jsxs("i", { children: ["Powered by Athos Commerce. AI-powered assistant. It sometimes make mistakes. Avoid sharing personal data.", ' ', _jsx("a", { href: "https://athoscommerce.com/legal/privacy-policy/", target: "_blank", rel: "noopener noreferrer", children: "Privacy Policy" })] }) }), isDraggingFile && (_jsxs("div", { className: "ss__chat__content__footer__drop-overlay", children: [_jsx(Icon, { icon: "image", size: "24px" }), _jsx("span", { children: "Drop image to upload" })] }))] }));
1937
+ })()) : (_jsxs("div", { className: 'ss__chat__expired', children: [_jsx("div", { className: 'ss__chat__expired__message', children: "This chat is expired. Please start a new chat." }), _jsx(Button, { className: 'ss__chat__expired__button', onClick: () => {
1938
+ controller.store.createChat();
1939
+ }, children: "New Session" })] }))] })] })) : null] }), _jsx(Overlay, { style: { zIndex: 1001 }, color: "transparent", active: store.open, onClick: () => controller.handlers.button.click() })] }) }));
1742
1940
  });