@athoscommerce/snap-preact 1.2.3-beta.3 → 1.2.3-beta.5
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.
- package/README.md +16 -0
- package/dist/cjs/components/src/components/Atoms/TemplateSelect/TemplateSelect.d.ts +3 -3
- package/dist/cjs/components/src/components/Atoms/TemplateSelect/TemplateSelect.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Atoms/TemplateSelect/TemplateSelect.js +7 -8
- package/dist/cjs/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.d.ts +1 -1
- package/dist/cjs/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.js +3 -3
- package/dist/cjs/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts +2 -0
- package/dist/cjs/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.js +29 -27
- package/dist/cjs/components/src/components/Molecules/Filter/Filter.d.ts +1 -1
- package/dist/cjs/components/src/components/Molecules/Filter/Filter.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Molecules/Result/Result.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Molecules/Result/Result.js +11 -6
- package/dist/cjs/components/src/components/Molecules/SearchInput/SearchInput.d.ts +4 -1
- package/dist/cjs/components/src/components/Molecules/SearchInput/SearchInput.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Molecules/SearchInput/SearchInput.js +3 -3
- package/dist/cjs/components/src/components/Molecules/TemplatesEditor/Components/AbstractedControls.js +5 -5
- package/dist/cjs/components/src/components/Molecules/TemplatesEditor/Components/Control.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Molecules/TemplatesEditor/Components/Control.js +31 -31
- package/dist/cjs/components/src/components/Molecules/TemplatesEditor/TemplatesEditor.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Molecules/TemplatesEditor/TemplatesEditor.js +22 -36
- package/dist/cjs/components/src/components/Organisms/Chat/Chat.d.ts +8 -0
- package/dist/cjs/components/src/components/Organisms/Chat/Chat.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Organisms/Chat/Chat.js +715 -427
- package/dist/cjs/components/src/components/Organisms/Chat/ChatResult.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Organisms/Chat/ChatResult.js +13 -3
- package/dist/cjs/components/src/components/Organisms/Chat/MessageText.d.ts +3 -1
- package/dist/cjs/components/src/components/Organisms/Chat/MessageText.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Organisms/Chat/MessageText.js +22 -19
- package/dist/cjs/components/src/components/Organisms/Chat/MessageUser.d.ts +3 -1
- package/dist/cjs/components/src/components/Organisms/Chat/MessageUser.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Organisms/Chat/MessageUser.js +40 -23
- package/dist/cjs/components/src/components/Organisms/Chat/ResultsDisplay.d.ts +1 -1
- package/dist/cjs/components/src/components/Organisms/Chat/ResultsDisplay.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Organisms/Chat/ResultsDisplay.js +8 -7
- package/dist/cjs/components/src/components/Organisms/Facet/Facet.js +2 -1
- package/dist/cjs/components/src/components/Organisms/FacetsHorizontal/FacetsHorizontal.js +2 -1
- package/dist/cjs/components/src/components/Organisms/FilterSummary/FilterSummary.d.ts +2 -2
- package/dist/cjs/components/src/components/Organisms/FilterSummary/FilterSummary.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Organisms/ProductQuickView/ProductQuickView.d.ts +11 -0
- package/dist/cjs/components/src/components/Organisms/ProductQuickView/ProductQuickView.d.ts.map +1 -0
- package/dist/cjs/components/src/components/Organisms/ProductQuickView/ProductQuickView.js +461 -0
- package/dist/cjs/components/src/components/Organisms/ProductQuickView/index.d.ts +2 -0
- package/dist/cjs/components/src/components/Organisms/ProductQuickView/index.d.ts.map +1 -0
- package/dist/cjs/components/src/components/Organisms/ProductQuickView/index.js +17 -0
- package/dist/cjs/components/src/components/Templates/AutocompleteModal/AutocompleteModal.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Templates/AutocompleteModal/AutocompleteModal.js +0 -2
- package/dist/cjs/components/src/hooks/useAcRenderedInput.d.ts.map +1 -1
- package/dist/cjs/components/src/hooks/useAcRenderedInput.js +65 -15
- package/dist/cjs/components/src/hooks/useMediaQuery.d.ts.map +1 -1
- package/dist/cjs/components/src/hooks/useMediaQuery.js +3 -1
- package/dist/cjs/components/src/index.d.ts +1 -0
- package/dist/cjs/components/src/index.d.ts.map +1 -1
- package/dist/cjs/components/src/index.js +1 -0
- package/dist/cjs/components/src/providers/theme.d.ts +1 -1
- package/dist/cjs/components/src/providers/theme.d.ts.map +1 -1
- package/dist/cjs/components/src/themes/base/base.js +3 -3
- package/dist/cjs/components/src/utilities/Colour/Colour.d.ts +11 -0
- package/dist/cjs/components/src/utilities/Colour/Colour.d.ts.map +1 -1
- package/dist/cjs/components/src/utilities/Colour/Colour.js +32 -0
- package/dist/cjs/src/Instantiators/RecommendationInstantiator.d.ts +1 -0
- package/dist/cjs/src/Instantiators/RecommendationInstantiator.d.ts.map +1 -1
- package/dist/cjs/src/Instantiators/RecommendationInstantiator.js +161 -123
- package/dist/cjs/src/Snap.d.ts +1 -1
- package/dist/cjs/src/Snap.d.ts.map +1 -1
- package/dist/cjs/src/Snap.js +18 -6
- package/dist/cjs/src/SnapHybrid.d.ts.map +1 -1
- package/dist/cjs/src/Templates/SnapTemplates.d.ts +13 -72
- package/dist/cjs/src/Templates/SnapTemplates.d.ts.map +1 -1
- package/dist/cjs/src/Templates/SnapTemplates.js +123 -72
- package/dist/cjs/src/Templates/Stores/TargetStore.d.ts +7 -6
- package/dist/cjs/src/Templates/Stores/TargetStore.d.ts.map +1 -1
- package/dist/cjs/src/Templates/Stores/TargetStore.js +14 -8
- package/dist/cjs/src/Templates/Stores/TemplateEditor/TemplateEditorStore.d.ts +58 -8
- package/dist/cjs/src/Templates/Stores/TemplateEditor/TemplateEditorStore.d.ts.map +1 -1
- package/dist/cjs/src/Templates/Stores/TemplateEditor/TemplateEditorStore.js +467 -96
- package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.d.ts +1 -0
- package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.d.ts.map +1 -1
- package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.js +123 -70
- package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/configUI.d.ts.map +1 -1
- package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/configUI.js +9 -3
- package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.d.ts +1 -0
- package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.d.ts.map +1 -1
- package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.js +86 -1
- package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/themeUI.d.ts.map +1 -1
- package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/themeUI.js +33 -14
- package/dist/cjs/src/Templates/Stores/TemplateStore.d.ts +93 -30
- package/dist/cjs/src/Templates/Stores/TemplateStore.d.ts.map +1 -1
- package/dist/cjs/src/Templates/Stores/TemplateStore.js +33 -41
- package/dist/cjs/src/Templates/Stores/ThemeStore.d.ts +2 -8
- package/dist/cjs/src/Templates/Stores/ThemeStore.d.ts.map +1 -1
- package/dist/cjs/src/Templates/Stores/ThemeStore.js +3 -28
- package/dist/cjs/src/Templates/index.d.ts +1 -1
- package/dist/cjs/src/Templates/index.d.ts.map +1 -1
- package/dist/cjs/src/create/createChatController.js +1 -1
- package/dist/cjs/src/index.d.ts +1 -0
- package/dist/cjs/src/index.d.ts.map +1 -1
- package/dist/cjs/src/setupEvents.d.ts +13 -0
- package/dist/cjs/src/setupEvents.d.ts.map +1 -1
- package/dist/cjs/src/setupEvents.js +56 -8
- package/dist/cjs/src/types.d.ts +3 -1
- package/dist/cjs/src/types.d.ts.map +1 -1
- package/dist/cjs/src/utils/combineMerge.d.ts +2 -0
- package/dist/cjs/src/utils/combineMerge.d.ts.map +1 -0
- package/dist/cjs/src/utils/combineMerge.js +22 -0
- package/dist/cjs/src/utils/index.d.ts +1 -0
- package/dist/cjs/src/utils/index.d.ts.map +1 -1
- package/dist/cjs/src/utils/index.js +3 -1
- package/dist/esm/components/src/components/Atoms/TemplateSelect/TemplateSelect.d.ts +3 -3
- package/dist/esm/components/src/components/Atoms/TemplateSelect/TemplateSelect.d.ts.map +1 -1
- package/dist/esm/components/src/components/Atoms/TemplateSelect/TemplateSelect.js +7 -8
- package/dist/esm/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.d.ts +1 -1
- package/dist/esm/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.d.ts.map +1 -1
- package/dist/esm/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.js +3 -3
- package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts +2 -0
- package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts.map +1 -1
- package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.js +29 -28
- package/dist/esm/components/src/components/Molecules/Filter/Filter.d.ts +1 -1
- package/dist/esm/components/src/components/Molecules/Filter/Filter.d.ts.map +1 -1
- package/dist/esm/components/src/components/Molecules/Result/Result.d.ts.map +1 -1
- package/dist/esm/components/src/components/Molecules/Result/Result.js +9 -4
- package/dist/esm/components/src/components/Molecules/SearchInput/SearchInput.d.ts +4 -1
- package/dist/esm/components/src/components/Molecules/SearchInput/SearchInput.d.ts.map +1 -1
- package/dist/esm/components/src/components/Molecules/SearchInput/SearchInput.js +3 -3
- package/dist/esm/components/src/components/Molecules/TemplatesEditor/Components/AbstractedControls.js +5 -5
- package/dist/esm/components/src/components/Molecules/TemplatesEditor/Components/Control.d.ts.map +1 -1
- package/dist/esm/components/src/components/Molecules/TemplatesEditor/Components/Control.js +29 -29
- package/dist/esm/components/src/components/Molecules/TemplatesEditor/TemplatesEditor.d.ts.map +1 -1
- package/dist/esm/components/src/components/Molecules/TemplatesEditor/TemplatesEditor.js +22 -35
- package/dist/esm/components/src/components/Organisms/Chat/Chat.d.ts +8 -0
- package/dist/esm/components/src/components/Organisms/Chat/Chat.d.ts.map +1 -1
- package/dist/esm/components/src/components/Organisms/Chat/Chat.js +636 -359
- package/dist/esm/components/src/components/Organisms/Chat/ChatResult.d.ts.map +1 -1
- package/dist/esm/components/src/components/Organisms/Chat/ChatResult.js +13 -3
- package/dist/esm/components/src/components/Organisms/Chat/MessageText.d.ts +3 -1
- package/dist/esm/components/src/components/Organisms/Chat/MessageText.d.ts.map +1 -1
- package/dist/esm/components/src/components/Organisms/Chat/MessageText.js +21 -19
- package/dist/esm/components/src/components/Organisms/Chat/MessageUser.d.ts +3 -1
- package/dist/esm/components/src/components/Organisms/Chat/MessageUser.d.ts.map +1 -1
- package/dist/esm/components/src/components/Organisms/Chat/MessageUser.js +37 -23
- package/dist/esm/components/src/components/Organisms/Chat/ResultsDisplay.d.ts +1 -1
- package/dist/esm/components/src/components/Organisms/Chat/ResultsDisplay.d.ts.map +1 -1
- package/dist/esm/components/src/components/Organisms/Chat/ResultsDisplay.js +8 -7
- package/dist/esm/components/src/components/Organisms/Facet/Facet.js +1 -1
- package/dist/esm/components/src/components/Organisms/FacetsHorizontal/FacetsHorizontal.js +1 -1
- package/dist/esm/components/src/components/Organisms/FilterSummary/FilterSummary.d.ts +2 -2
- package/dist/esm/components/src/components/Organisms/FilterSummary/FilterSummary.d.ts.map +1 -1
- package/dist/esm/components/src/components/Organisms/ProductQuickView/ProductQuickView.d.ts +11 -0
- package/dist/esm/components/src/components/Organisms/ProductQuickView/ProductQuickView.d.ts.map +1 -0
- package/dist/esm/components/src/components/Organisms/ProductQuickView/ProductQuickView.js +436 -0
- package/dist/esm/components/src/components/Organisms/ProductQuickView/index.d.ts +2 -0
- package/dist/esm/components/src/components/Organisms/ProductQuickView/index.d.ts.map +1 -0
- package/dist/esm/components/src/components/Organisms/ProductQuickView/index.js +1 -0
- package/dist/esm/components/src/components/Templates/AutocompleteModal/AutocompleteModal.d.ts.map +1 -1
- package/dist/esm/components/src/components/Templates/AutocompleteModal/AutocompleteModal.js +0 -2
- package/dist/esm/components/src/hooks/useAcRenderedInput.d.ts.map +1 -1
- package/dist/esm/components/src/hooks/useAcRenderedInput.js +61 -11
- package/dist/esm/components/src/hooks/useMediaQuery.d.ts.map +1 -1
- package/dist/esm/components/src/hooks/useMediaQuery.js +3 -1
- package/dist/esm/components/src/index.d.ts +1 -0
- package/dist/esm/components/src/index.d.ts.map +1 -1
- package/dist/esm/components/src/index.js +1 -0
- package/dist/esm/components/src/providers/theme.d.ts +1 -1
- package/dist/esm/components/src/providers/theme.d.ts.map +1 -1
- package/dist/esm/components/src/themes/base/base.js +3 -3
- package/dist/esm/components/src/utilities/Colour/Colour.d.ts +11 -0
- package/dist/esm/components/src/utilities/Colour/Colour.d.ts.map +1 -1
- package/dist/esm/components/src/utilities/Colour/Colour.js +30 -0
- package/dist/esm/src/Instantiators/RecommendationInstantiator.d.ts +1 -0
- package/dist/esm/src/Instantiators/RecommendationInstantiator.d.ts.map +1 -1
- package/dist/esm/src/Instantiators/RecommendationInstantiator.js +130 -84
- package/dist/esm/src/Snap.d.ts +1 -1
- package/dist/esm/src/Snap.d.ts.map +1 -1
- package/dist/esm/src/Snap.js +21 -6
- package/dist/esm/src/SnapHybrid.d.ts.map +1 -1
- package/dist/esm/src/Templates/SnapTemplates.d.ts +13 -72
- package/dist/esm/src/Templates/SnapTemplates.d.ts.map +1 -1
- package/dist/esm/src/Templates/SnapTemplates.js +137 -78
- package/dist/esm/src/Templates/Stores/TargetStore.d.ts +7 -6
- package/dist/esm/src/Templates/Stores/TargetStore.d.ts.map +1 -1
- package/dist/esm/src/Templates/Stores/TargetStore.js +14 -8
- package/dist/esm/src/Templates/Stores/TemplateEditor/TemplateEditorStore.d.ts +58 -8
- package/dist/esm/src/Templates/Stores/TemplateEditor/TemplateEditorStore.d.ts.map +1 -1
- package/dist/esm/src/Templates/Stores/TemplateEditor/TemplateEditorStore.js +447 -89
- package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.d.ts +1 -0
- package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.d.ts.map +1 -1
- package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/autocompleteControllerUI.js +118 -66
- package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/configUI.d.ts.map +1 -1
- package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/configUI.js +9 -3
- package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.d.ts +1 -0
- package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.d.ts.map +1 -1
- package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/searchControllerUI.js +82 -1
- package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/themeUI.d.ts.map +1 -1
- package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/themeUI.js +27 -8
- package/dist/esm/src/Templates/Stores/TemplateStore.d.ts +93 -30
- package/dist/esm/src/Templates/Stores/TemplateStore.d.ts.map +1 -1
- package/dist/esm/src/Templates/Stores/TemplateStore.js +29 -38
- package/dist/esm/src/Templates/Stores/ThemeStore.d.ts +2 -8
- package/dist/esm/src/Templates/Stores/ThemeStore.d.ts.map +1 -1
- package/dist/esm/src/Templates/Stores/ThemeStore.js +3 -26
- package/dist/esm/src/Templates/index.d.ts +1 -1
- package/dist/esm/src/Templates/index.d.ts.map +1 -1
- package/dist/esm/src/create/createChatController.js +1 -1
- package/dist/esm/src/index.d.ts +1 -0
- package/dist/esm/src/index.d.ts.map +1 -1
- package/dist/esm/src/setupEvents.d.ts +13 -0
- package/dist/esm/src/setupEvents.d.ts.map +1 -1
- package/dist/esm/src/setupEvents.js +25 -8
- package/dist/esm/src/types.d.ts +3 -1
- package/dist/esm/src/types.d.ts.map +1 -1
- package/dist/esm/src/utils/combineMerge.d.ts +2 -0
- package/dist/esm/src/utils/combineMerge.d.ts.map +1 -0
- package/dist/esm/src/utils/combineMerge.js +16 -0
- package/dist/esm/src/utils/index.d.ts +1 -0
- package/dist/esm/src/utils/index.d.ts.map +1 -1
- package/dist/esm/src/utils/index.js +1 -0
- 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
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
145
|
+
[horizontalAnchor]: mobile ? '20px' : 0,
|
|
135
146
|
width: '60px',
|
|
136
147
|
height: '60px',
|
|
137
148
|
borderRadius: '50%',
|
|
138
149
|
background: colorPrimary,
|
|
139
|
-
color:
|
|
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:
|
|
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:
|
|
155
|
-
stroke:
|
|
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
|
-
|
|
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
|
|
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:
|
|
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:
|
|
250
|
-
stroke:
|
|
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:
|
|
329
|
-
color:
|
|
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:
|
|
337
|
-
stroke:
|
|
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: '
|
|
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
|
-
|
|
356
|
-
|
|
357
|
-
|
|
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
|
-
|
|
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:
|
|
374
|
-
stroke:
|
|
375
|
-
opacity: 0.7,
|
|
376
|
-
'&:hover': {
|
|
377
|
-
opacity: 1,
|
|
378
|
-
},
|
|
401
|
+
fill: colorPrimaryText,
|
|
402
|
+
stroke: colorPrimaryText,
|
|
379
403
|
},
|
|
380
404
|
},
|
|
381
405
|
},
|
|
@@ -385,13 +409,25 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
385
409
|
overflow: 'hidden',
|
|
386
410
|
display: 'flex',
|
|
387
411
|
flexDirection: 'column',
|
|
388
|
-
border:
|
|
412
|
+
border: `1px solid ${colorPrimary}`,
|
|
389
413
|
borderTop: 'none',
|
|
390
414
|
marginTop: '-1px',
|
|
391
415
|
borderBottomRightRadius: mobile ? 0 : '12px',
|
|
392
416
|
borderBottomLeftRadius: mobile ? 0 : '12px',
|
|
393
417
|
flexGrow: 1,
|
|
418
|
+
position: 'relative',
|
|
394
419
|
'.ss__chat__content__header': {
|
|
420
|
+
// In overlay mode (only applied when messages overflow), the comparisons
|
|
421
|
+
// tray floats over the messages so toggling it doesn't shift the layout
|
|
422
|
+
// or push the latest message out of view. When messages don't overflow,
|
|
423
|
+
// the tray stays in flow so older messages remain reachable above it.
|
|
424
|
+
'&.ss__chat__content__header--overlay': {
|
|
425
|
+
position: 'absolute',
|
|
426
|
+
top: 0,
|
|
427
|
+
left: 0,
|
|
428
|
+
right: 0,
|
|
429
|
+
zIndex: 20,
|
|
430
|
+
},
|
|
395
431
|
// '.ss__chat__attachments': {
|
|
396
432
|
// '.ss__chat__attachment': {
|
|
397
433
|
// borderRadius: 0,
|
|
@@ -403,7 +439,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
403
439
|
display: 'flex',
|
|
404
440
|
flexDirection: 'column',
|
|
405
441
|
gap: '1em',
|
|
406
|
-
background:
|
|
442
|
+
background: new Colour(colorPrimary).lightenHex(0.95),
|
|
407
443
|
padding: '1em',
|
|
408
444
|
'.ss__chat__content__header__comparisons__header': {
|
|
409
445
|
display: 'flex',
|
|
@@ -418,7 +454,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
418
454
|
background: colorPrimary,
|
|
419
455
|
borderRadius: '50%',
|
|
420
456
|
padding: '5px',
|
|
421
|
-
fill:
|
|
457
|
+
fill: colorPrimaryText,
|
|
422
458
|
height: '25px',
|
|
423
459
|
width: '25px',
|
|
424
460
|
},
|
|
@@ -491,11 +527,11 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
491
527
|
borderRadius: '1em',
|
|
492
528
|
padding: '0.5em 1em',
|
|
493
529
|
background: colorPrimary,
|
|
494
|
-
color:
|
|
530
|
+
color: colorPrimaryText,
|
|
495
531
|
textAlign: 'center',
|
|
496
532
|
svg: {
|
|
497
|
-
fill:
|
|
498
|
-
stroke:
|
|
533
|
+
fill: colorPrimaryText,
|
|
534
|
+
stroke: colorPrimaryText,
|
|
499
535
|
},
|
|
500
536
|
},
|
|
501
537
|
},
|
|
@@ -504,6 +540,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
504
540
|
},
|
|
505
541
|
'.ss__chat__messages': {
|
|
506
542
|
flex: '1 1 auto',
|
|
543
|
+
overflowY: 'auto',
|
|
507
544
|
overscrollBehavior: 'contain',
|
|
508
545
|
margin: 0,
|
|
509
546
|
maxHeight: '100%',
|
|
@@ -522,7 +559,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
522
559
|
width: 'fit-content',
|
|
523
560
|
padding: '6px 16px',
|
|
524
561
|
background: colorPrimary,
|
|
525
|
-
color:
|
|
562
|
+
color: colorPrimaryText,
|
|
526
563
|
borderRadius: '999px',
|
|
527
564
|
fontSize: '13px',
|
|
528
565
|
fontWeight: 500,
|
|
@@ -530,11 +567,11 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
530
567
|
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
|
|
531
568
|
zIndex: 5,
|
|
532
569
|
'&:hover': {
|
|
533
|
-
background:
|
|
570
|
+
background: colorPrimaryHover,
|
|
534
571
|
},
|
|
535
572
|
svg: {
|
|
536
|
-
fill:
|
|
537
|
-
stroke:
|
|
573
|
+
fill: colorPrimaryText,
|
|
574
|
+
stroke: colorPrimaryText,
|
|
538
575
|
},
|
|
539
576
|
},
|
|
540
577
|
'.ss__chat__message': {
|
|
@@ -563,7 +600,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
563
600
|
'.ss__chat__welcome': {
|
|
564
601
|
display: 'flex',
|
|
565
602
|
flexDirection: 'column',
|
|
566
|
-
|
|
603
|
+
minHeight: '100%',
|
|
567
604
|
'.ss__chat__welcome__message': {
|
|
568
605
|
fontSize: '15px',
|
|
569
606
|
lineHeight: 1.5,
|
|
@@ -586,8 +623,8 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
586
623
|
flexDirection: 'column',
|
|
587
624
|
gap: '6px',
|
|
588
625
|
padding: '8px 10px',
|
|
589
|
-
background:
|
|
590
|
-
border:
|
|
626
|
+
background: new Colour(colorPrimary).lightenHex(0.95),
|
|
627
|
+
border: `1px solid ${new Colour(colorPrimary).lightenHex(0.85)}`,
|
|
591
628
|
borderRadius: '8px',
|
|
592
629
|
},
|
|
593
630
|
'.ss__chat__actions--title': {
|
|
@@ -607,7 +644,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
607
644
|
fontSize: '14px',
|
|
608
645
|
color: '#333',
|
|
609
646
|
'&:hover': {
|
|
610
|
-
background:
|
|
647
|
+
background: new Colour(colorPrimary).lightenHex(0.97),
|
|
611
648
|
},
|
|
612
649
|
},
|
|
613
650
|
},
|
|
@@ -707,8 +744,8 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
707
744
|
visibility: 'visible',
|
|
708
745
|
},
|
|
709
746
|
'.ss__button': {
|
|
710
|
-
background:
|
|
711
|
-
color:
|
|
747
|
+
background: colorPrimary,
|
|
748
|
+
color: colorPrimaryText,
|
|
712
749
|
border: 'none',
|
|
713
750
|
borderRadius: '999px',
|
|
714
751
|
padding: '2px 10px',
|
|
@@ -716,7 +753,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
716
753
|
lineHeight: '1.4',
|
|
717
754
|
cursor: 'pointer',
|
|
718
755
|
'&:not(.ss__button--disabled):hover': {
|
|
719
|
-
background:
|
|
756
|
+
background: colorPrimaryHover,
|
|
720
757
|
},
|
|
721
758
|
'&.ss__button--disabled': {
|
|
722
759
|
opacity: 0.5,
|
|
@@ -739,8 +776,8 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
739
776
|
flexDirection: 'column',
|
|
740
777
|
gap: '6px',
|
|
741
778
|
padding: '8px 10px',
|
|
742
|
-
background:
|
|
743
|
-
border:
|
|
779
|
+
background: new Colour(colorPrimary).lightenHex(0.95),
|
|
780
|
+
border: `1px solid ${new Colour(colorPrimary).lightenHex(0.85)}`,
|
|
744
781
|
borderRadius: '8px',
|
|
745
782
|
'.ss__chat__attachment-context__label': {
|
|
746
783
|
fontSize: '14px',
|
|
@@ -876,20 +913,39 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
876
913
|
flexDirection: 'column',
|
|
877
914
|
gap: '8px',
|
|
878
915
|
flexShrink: 0,
|
|
916
|
+
position: 'relative',
|
|
879
917
|
...(mobile
|
|
880
918
|
? {
|
|
881
|
-
position: 'relative',
|
|
882
919
|
zIndex: 11,
|
|
883
920
|
background: '#fff',
|
|
884
921
|
}
|
|
885
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
|
+
},
|
|
886
942
|
},
|
|
887
943
|
'.ss__chat__topic-drift': {
|
|
888
944
|
display: 'flex',
|
|
889
945
|
alignItems: 'center',
|
|
890
946
|
gap: '12px',
|
|
891
947
|
padding: '12px 16px',
|
|
892
|
-
border:
|
|
948
|
+
border: `1px solid ${new Colour(colorPrimary).lightenHex(0.6)}`,
|
|
893
949
|
borderRadius: '8px',
|
|
894
950
|
backgroundColor: '#fff',
|
|
895
951
|
'.ss__chat__topic-drift__icon--info': {
|
|
@@ -919,7 +975,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
919
975
|
'.ss__chat__topic-drift__button': {
|
|
920
976
|
flex: '0 0 auto',
|
|
921
977
|
backgroundColor: colorPrimary,
|
|
922
|
-
color:
|
|
978
|
+
color: colorPrimaryText,
|
|
923
979
|
borderRadius: '6px',
|
|
924
980
|
padding: '8px 14px',
|
|
925
981
|
fontSize: '13px',
|
|
@@ -927,7 +983,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
927
983
|
cursor: 'pointer',
|
|
928
984
|
whiteSpace: 'nowrap',
|
|
929
985
|
'&:not(.ss__button--disabled):hover': {
|
|
930
|
-
background:
|
|
986
|
+
background: colorPrimaryHover,
|
|
931
987
|
},
|
|
932
988
|
},
|
|
933
989
|
'.ss__chat__topic-drift__icon--close': {
|
|
@@ -965,7 +1021,7 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
965
1021
|
},
|
|
966
1022
|
'&:focus': {
|
|
967
1023
|
outline: 'none',
|
|
968
|
-
borderColor:
|
|
1024
|
+
borderColor: colorPrimary,
|
|
969
1025
|
},
|
|
970
1026
|
},
|
|
971
1027
|
'.ss__button': {
|
|
@@ -981,18 +1037,20 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
981
1037
|
'.ss__chat__input__actions': {
|
|
982
1038
|
'.ss__button': {
|
|
983
1039
|
backgroundColor: colorPrimary,
|
|
1040
|
+
color: colorPrimaryText,
|
|
984
1041
|
borderRadius: '50%',
|
|
985
1042
|
height: '3em',
|
|
986
1043
|
width: '3em',
|
|
987
1044
|
cursor: 'pointer',
|
|
988
1045
|
justifyContent: 'center',
|
|
1046
|
+
boxSizing: 'border-box',
|
|
989
1047
|
'&:disabled': {
|
|
990
1048
|
opacity: 0.5,
|
|
991
1049
|
cursor: 'not-allowed',
|
|
992
1050
|
},
|
|
993
1051
|
svg: {
|
|
994
|
-
fill:
|
|
995
|
-
stroke:
|
|
1052
|
+
fill: colorPrimaryText,
|
|
1053
|
+
stroke: colorPrimaryText,
|
|
996
1054
|
},
|
|
997
1055
|
},
|
|
998
1056
|
},
|
|
@@ -1003,6 +1061,55 @@ const defaultStyles = ({ mobile, offset, hasSideChat, footerHeight }) => {
|
|
|
1003
1061
|
textAlign: 'center',
|
|
1004
1062
|
flexShrink: 0,
|
|
1005
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
|
+
},
|
|
1006
1113
|
},
|
|
1007
1114
|
});
|
|
1008
1115
|
};
|
|
@@ -1014,11 +1121,26 @@ export const Chat = observer((properties) => {
|
|
|
1014
1121
|
treePath: globalTreePath,
|
|
1015
1122
|
logo: 'https://cdn.athoscommerce.net/snap/images/Athos%20Commerce_Icon_white.svg',
|
|
1016
1123
|
title: 'Athos Conversational Assistant',
|
|
1017
|
-
subtitle: '
|
|
1124
|
+
subtitle: 'Your Guided Discovery Expert',
|
|
1018
1125
|
multiselectFacets: true,
|
|
1126
|
+
disableBubbleSuggestedQuestions: false,
|
|
1127
|
+
primaryColorBg: '#253B80',
|
|
1128
|
+
primaryColorFg: '#fff',
|
|
1129
|
+
primaryAccentColorBg: '#feeeae',
|
|
1130
|
+
primaryAccentColorFg: '#000000',
|
|
1131
|
+
secondaryAccentColorBg: '#000000',
|
|
1132
|
+
secondaryAccentColorFg: '#ffffff',
|
|
1133
|
+
position: 'right',
|
|
1019
1134
|
};
|
|
1020
1135
|
let props = mergeProps('facets', globalTheme, defaultProps, properties);
|
|
1021
|
-
const { className, internalClassName, controller, logo, title, subtitle, offset, multiselectFacets } = 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';
|
|
1022
1144
|
const { store } = controller;
|
|
1023
1145
|
const themeDefaults = {
|
|
1024
1146
|
components: {},
|
|
@@ -1032,7 +1154,9 @@ export const Chat = observer((properties) => {
|
|
|
1032
1154
|
const fileInputRef = useRef(null);
|
|
1033
1155
|
const messagesEndRef = useRef(null);
|
|
1034
1156
|
const messagesContainerRef = useRef(null);
|
|
1157
|
+
const headerRef = useRef(null);
|
|
1035
1158
|
const footerRef = useRef(null);
|
|
1159
|
+
const chatRef = useRef(null);
|
|
1036
1160
|
// Swipe-to-dismiss state for mobile secondary panel
|
|
1037
1161
|
const secondaryRef = useRef(null);
|
|
1038
1162
|
const swipeStartY = useRef(0);
|
|
@@ -1044,13 +1168,25 @@ export const Chat = observer((properties) => {
|
|
|
1044
1168
|
const [mobileProductInfoOpen, setMobileProductInfoOpen] = useState(false);
|
|
1045
1169
|
const [footerHeight, setFooterHeight] = useState(0);
|
|
1046
1170
|
const [showNewMessages, setShowNewMessages] = useState(false);
|
|
1171
|
+
const [messagesOverflow, setMessagesOverflow] = useState(false);
|
|
1047
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);
|
|
1048
1177
|
const updateSwipeOffset = (value) => {
|
|
1049
1178
|
swipeOffsetRef.current = value;
|
|
1050
1179
|
setSwipeOffsetRaw(value);
|
|
1051
1180
|
};
|
|
1052
1181
|
const scrollToBottom = () => {
|
|
1053
|
-
|
|
1182
|
+
// Scroll the messages container directly (instead of scrollIntoView on the
|
|
1183
|
+
// bottom anchor) so the browser never walks up the ancestor chain. On small
|
|
1184
|
+
// viewports a smooth scrollIntoView could otherwise animate the document/
|
|
1185
|
+
// visual viewport and visually push the fixed-position chat off-screen.
|
|
1186
|
+
const container = messagesContainerRef.current;
|
|
1187
|
+
if (container) {
|
|
1188
|
+
container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' });
|
|
1189
|
+
}
|
|
1054
1190
|
};
|
|
1055
1191
|
// Conditional scroll: only scrolls if the user is already near the bottom.
|
|
1056
1192
|
// Passed to child components (e.g. image onLoad) so they don't yank the user
|
|
@@ -1116,6 +1252,35 @@ export const Chat = observer((properties) => {
|
|
|
1116
1252
|
container.addEventListener('scroll', handleScroll);
|
|
1117
1253
|
return () => container.removeEventListener('scroll', handleScroll);
|
|
1118
1254
|
}, [store.open]);
|
|
1255
|
+
// Track whether the messages container is overflowing so the comparisons header
|
|
1256
|
+
// can switch between in-flow (short conversations — top content stays reachable)
|
|
1257
|
+
// and overlay (overflowing — avoid layout shift when toggling the tray).
|
|
1258
|
+
// Hysteresis: when already in overlay, only return to in-flow if the content
|
|
1259
|
+
// would still fit *with* the header re-inserted — otherwise the two states
|
|
1260
|
+
// fight each other and the layout flickers.
|
|
1261
|
+
useEffect(() => {
|
|
1262
|
+
const container = messagesContainerRef.current;
|
|
1263
|
+
if (!container || typeof ResizeObserver === 'undefined')
|
|
1264
|
+
return;
|
|
1265
|
+
const update = () => {
|
|
1266
|
+
setMessagesOverflow((prev) => {
|
|
1267
|
+
const headerHeight = headerRef.current?.offsetHeight || 0;
|
|
1268
|
+
if (prev) {
|
|
1269
|
+
// Currently overlay: header isn't taking flow space. Only switch
|
|
1270
|
+
// back to in-flow if the content would fit with the header added.
|
|
1271
|
+
return container.scrollHeight > container.clientHeight - headerHeight + 1;
|
|
1272
|
+
}
|
|
1273
|
+
// Currently in-flow: header already takes space — straightforward check.
|
|
1274
|
+
return container.scrollHeight > container.clientHeight + 1;
|
|
1275
|
+
});
|
|
1276
|
+
};
|
|
1277
|
+
update();
|
|
1278
|
+
const observer = new ResizeObserver(update);
|
|
1279
|
+
observer.observe(container);
|
|
1280
|
+
if (headerRef.current)
|
|
1281
|
+
observer.observe(headerRef.current);
|
|
1282
|
+
return () => observer.disconnect();
|
|
1283
|
+
}, [store.open, visibleChatLength]);
|
|
1119
1284
|
// Re-focus the chat input on desktop after a search completes.
|
|
1120
1285
|
// The input is disabled while loading, which causes the browser to drop focus.
|
|
1121
1286
|
// On mobile we intentionally skip this so the virtual keyboard dismisses.
|
|
@@ -1143,7 +1308,19 @@ export const Chat = observer((properties) => {
|
|
|
1143
1308
|
? ['inspirationResult', ...(isFirstMobileComparison ? ['productComparison'] : []), ...(mobileProductInfoOpen ? ['productQuery'] : [])]
|
|
1144
1309
|
: ['inspirationResult', 'productComparison', 'productQuery'];
|
|
1145
1310
|
const shouldShowSideChat = activeMessage && sideChatTypes.includes(activeMessage?.messageType) && store.currentChat?.dismissedSideChatMessageId !== activeMessage.id;
|
|
1146
|
-
const styling = mergeStyles({
|
|
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);
|
|
1147
1324
|
// Lock body scroll while chat is open so touch/wheel scrolls don't leak to the page behind
|
|
1148
1325
|
useEffect(() => {
|
|
1149
1326
|
if (!store.open)
|
|
@@ -1188,6 +1365,70 @@ export const Chat = observer((properties) => {
|
|
|
1188
1365
|
return text.length > 50 ? `${text.slice(0, 50)}...` : text;
|
|
1189
1366
|
})() }), _jsx("div", { className: "ss__chat__history__chat__button__date", children: chat.createdAt.toLocaleString() })] }) }, chat.id))) })) : null] }));
|
|
1190
1367
|
const FacetButton = (props) => _jsx(Button, { icon: props.open ? 'angle-down' : 'angle-up', children: props.label });
|
|
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
|
+
}
|
|
1380
|
+
const applied = new Set();
|
|
1381
|
+
// Count values marked as filtered (already applied on the server)
|
|
1382
|
+
(facet.values || []).forEach((value) => {
|
|
1383
|
+
if (value?.filtered) {
|
|
1384
|
+
if ('low' in value && 'high' in value) {
|
|
1385
|
+
applied.add(`${value.low ?? '*'}:${value.high ?? '*'}`);
|
|
1386
|
+
}
|
|
1387
|
+
else {
|
|
1388
|
+
applied.add(value.value);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
});
|
|
1392
|
+
// Count pending facet attachments (newly selected, not yet sent)
|
|
1393
|
+
(controller.store.currentChat?.attachments.items || [])
|
|
1394
|
+
.filter((item) => item.type === 'facet' && item.key === facet.field && (item.state === 'active' || item.state === 'attached'))
|
|
1395
|
+
.forEach((item) => applied.add(item.value));
|
|
1396
|
+
return applied.size > 0 ? `${base} (${applied.size})` : base;
|
|
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
|
+
};
|
|
1191
1432
|
// TODO: if starting a new chat and it's expired, this button would then disappear
|
|
1192
1433
|
if (!controller.store.chatEnabled) {
|
|
1193
1434
|
return _jsx(_Fragment, {});
|
|
@@ -1272,11 +1513,11 @@ export const Chat = observer((properties) => {
|
|
|
1272
1513
|
return undefined;
|
|
1273
1514
|
}
|
|
1274
1515
|
}, [requestType]);
|
|
1275
|
-
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', {
|
|
1276
1517
|
'ss__chat--open': store.open,
|
|
1277
1518
|
'ss__chat--minimized': !store.open,
|
|
1278
1519
|
'ss__chat--mobile': isMobile,
|
|
1279
|
-
}, className, internalClassName), ...styling, children: [!store.open && !store.currentChat && store.suggestedQuestions?.length > 0 && (_jsx("div", { className: "ss__chat__suggested-questions", children: store.suggestedQuestions.map((question, index) => (_jsx("div", { className: "ss__chat__suggested-questions__item", onClick: () => {
|
|
1520
|
+
}, className, internalClassName), ...styling, children: [!disableBubbleSuggestedQuestions && !store.open && !store.currentChat && store.suggestedQuestions?.length > 0 && (_jsx("div", { className: "ss__chat__suggested-questions", children: store.suggestedQuestions.map((question, index) => (_jsx("div", { className: "ss__chat__suggested-questions__item", onClick: () => {
|
|
1280
1521
|
controller.openChat(question);
|
|
1281
1522
|
}, children: question }, index))) })), _jsx("div", { className: 'ss__chat__bubble', onClick: () => controller.handlers.button.click(), children: _jsx(Icon, { icon: "chat", title: "Open Chat" }) }), store.open && shouldShowSideChat && activeMessage ? (_jsxs("div", { ref: secondaryRef, className: classnames('ss__chat__secondary'), style: isMobile
|
|
1282
1523
|
? {
|
|
@@ -1303,9 +1544,9 @@ export const Chat = observer((properties) => {
|
|
|
1303
1544
|
setMobileProductInfoOpen(false);
|
|
1304
1545
|
store.currentChat?.dismissSideChat();
|
|
1305
1546
|
} }) })] }), _jsx("div", { className: "ss__chat__content", children: _jsx("div", { className: 'ss__chat__messages', children: {
|
|
1306
|
-
inspirationResult: (_jsx(ChatInspirationResultMessage, { chatItem: activeMessage, controller: controller,
|
|
1547
|
+
inspirationResult: (_jsx(ChatInspirationResultMessage, { chatItem: activeMessage, controller: controller, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined })),
|
|
1307
1548
|
productComparison: (_jsx(ChatProductComparisonMessage, { chatItem: activeMessage, controller: controller })),
|
|
1308
|
-
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 })),
|
|
1309
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
|
|
1310
1551
|
// disabled={store.currentChat?.chat && store.currentChat.chat.length <= 1}
|
|
1311
1552
|
, {
|
|
@@ -1319,345 +1560,381 @@ export const Chat = observer((properties) => {
|
|
|
1319
1560
|
systemMessages.length >= feedbackAfterMessages &&
|
|
1320
1561
|
!store.currentChat?.feedbackDismissed &&
|
|
1321
1562
|
(!hasRated || store.currentChat?.feedbackJustGiven);
|
|
1322
|
-
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: () => {
|
|
1323
1564
|
if (store.currentChat) {
|
|
1324
1565
|
store.currentChat.feedbackDismissed = true;
|
|
1325
1566
|
store.currentChat.save();
|
|
1326
1567
|
}
|
|
1327
1568
|
}, children: _jsx(Icon, { icon: "close-thin", size: "14px" }) }))] })) : null;
|
|
1328
|
-
})(), _jsxs("div", { className: "ss__chat__content", children: [_jsx("div", {
|
|
1569
|
+
})(), _jsxs("div", { className: "ss__chat__content", children: [_jsx("div", { ref: headerRef, className: classnames('ss__chat__content__header', {
|
|
1570
|
+
'ss__chat__content__header--overlay': messagesOverflow,
|
|
1571
|
+
}), children: store.currentChat?.comparisons.compared && store.currentChat.comparisons.compared.length > 0 && (_jsxs("div", { className: 'ss__chat__content__header__comparisons', children: [_jsxs("div", { className: 'ss__chat__content__header__comparisons__header', children: [_jsxs("div", { className: 'ss__chat__content__header__comparisons__header__title', children: [_jsx(Icon, { className: 'ss__chat__content__header__comparisons__header__title__icon', icon: 'clipboard' }), _jsxs("span", { className: 'ss__chat__content__header__comparisons__header__title__text', children: ["Compare Products (", store.currentChat?.comparisons.compared.length, "/", store.currentChat?.comparisons.maxItems, ")"] })] }), _jsx("div", { className: 'ss__chat__content__header__comparisons__header__actions', children: _jsx(Button, { onClick: () => store.currentChat?.comparisons.reset(), children: "clear" }) })] }), _jsxs("div", { className: 'ss__chat__content__header__comparisons__content', children: [_jsx("div", { className: 'ss__chat__content__header__comparisons__content__items', children: Array.from({ length: store.currentChat?.comparisons.maxItems }).map((_, index) => {
|
|
1329
1572
|
const comparisonItem = store.currentChat?.comparisons.compared[index];
|
|
1330
1573
|
return (_jsx("div", { className: classnames('ss__chat__content__header__comparisons__content__comparison', {
|
|
1331
1574
|
'ss__chat__content__header__comparisons__content__comparison--placeholder': !comparisonItem,
|
|
1332
1575
|
}), children: comparisonItem ? (_jsxs(_Fragment, { children: [_jsx(Image
|
|
1333
1576
|
// onClick={() => {
|
|
1334
|
-
// controller?.
|
|
1577
|
+
// controller?.productQuickView(product as any);
|
|
1335
1578
|
// }}
|
|
1336
1579
|
, {
|
|
1337
1580
|
// onClick={() => {
|
|
1338
|
-
// controller?.
|
|
1581
|
+
// controller?.productQuickView(product as any);
|
|
1339
1582
|
// }}
|
|
1340
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: () => {
|
|
1341
1584
|
store.currentChat?.comparisons.remove(comparisonItem.result.id);
|
|
1342
1585
|
}, children: _jsx(Icon, { icon: 'close-thin', size: '12px' }) })] })) : (_jsxs(_Fragment, { children: [_jsx(Icon, { icon: 'plus-thin' }), _jsx("div", { className: 'ss__chat__content__header__comparisons__content__comparison--placeholder__text', children: "Add" })] })) }, index));
|
|
1343
1586
|
}) }), _jsx("div", { className: classnames('ss__chat__content__header__comparisons__action', {
|
|
1344
1587
|
'ss__chat__content__header__comparisons__action--hidden': (store.currentChat?.comparisons.compared.length || 0) < 2,
|
|
1345
|
-
}), children: _jsx(Button, { onClick: () => controller.search(), icon: { icon: 'compare', title: 'Compare' }, children: "Compare" }) })] })] })) }), _jsxs("div", { className: 'ss__chat__messages', ref: messagesContainerRef, style: visibleChatLength ? {
|
|
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
|
|
1346
1589
|
.filter((chatItem) => chatItem.messageType !== 'productQuery')
|
|
1347
1590
|
.map((chatItem, index) => (_jsx("div", { className: `ss__chat__message ss__chat__message--${chatItem.messageType}`, children: {
|
|
1348
|
-
user: (_jsx(MessageUser, { chatItem: chatItem, controller: controller,
|
|
1349
|
-
text: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear,
|
|
1350
|
-
content: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear,
|
|
1351
|
-
productSearchResult: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear,
|
|
1352
|
-
inspirationResult: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear,
|
|
1353
|
-
productAnswer: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear,
|
|
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 })),
|
|
1354
1597
|
productComparison: (() => {
|
|
1355
1598
|
// On mobile, only the first productComparison in the session
|
|
1356
1599
|
// auto-opens the secondary panel. Subsequent ones get a
|
|
1357
1600
|
// prominent "Show Details" button instead.
|
|
1358
1601
|
const comparisonMessages = (store.currentChat?.chat || []).filter((m) => m.messageType === 'productComparison');
|
|
1359
1602
|
const isFirst = comparisonMessages.length > 0 && comparisonMessages[0].id === chatItem.id;
|
|
1360
|
-
return (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear,
|
|
1603
|
+
return (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined, showDetailsButton: isMobile && !isFirst, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText }));
|
|
1361
1604
|
})(),
|
|
1362
|
-
productRecommendation: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear,
|
|
1605
|
+
productRecommendation: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onProductQuickView: isMobile ? () => setMobileProductInfoOpen(true) : undefined, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText })),
|
|
1363
1606
|
actions: _jsx(SuggestedQuestions, { actions: chatItem.actions, controller: controller }),
|
|
1364
|
-
errorResponse: (_jsx(MessageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, sideChatOpen: !!shouldShowSideChat })),
|
|
1365
|
-
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 })),
|
|
1366
1609
|
productQuery: null,
|
|
1367
|
-
}[chatItem.messageType] || null }, index))), _jsx("div", { className: "ss__chat__messages__end", ref: messagesEndRef }), showNewMessages && (_jsxs("div", { className: "ss__chat__new-messages", onClick: () => {
|
|
1610
|
+
}[chatItem.messageType] || null }, index))), _jsx("div", { className: "ss__chat__messages__end", ref: messagesEndRef }), showNewMessages && messagesOverflow && (_jsxs("div", { className: "ss__chat__new-messages", onClick: () => {
|
|
1368
1611
|
scrollToBottom();
|
|
1369
1612
|
setShowNewMessages(false);
|
|
1370
|
-
}, children: [_jsx(Icon, { icon: "angle-down", size: "12px" }), _jsx("span", { children: "New messages" })] }))] }), _jsx(ChatLoadingIndicator, { loading: store.loading, verbs: loadingVerbs }), !store.currentChat?.isExpired ? (
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
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',
|
|
1391
1692
|
display: 'flex',
|
|
1392
1693
|
alignItems: 'center',
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
background: '#f4f4ff',
|
|
1403
|
-
},
|
|
1404
|
-
'&:last-child': {
|
|
1405
|
-
borderBottom: 'none',
|
|
1406
|
-
},
|
|
1407
|
-
'.ss__chat__actions__facet__option__checkbox': {
|
|
1408
|
-
width: '16px',
|
|
1409
|
-
height: '16px',
|
|
1410
|
-
borderRadius: '3px',
|
|
1411
|
-
border: '2px solid #ccc',
|
|
1412
|
-
display: 'flex',
|
|
1413
|
-
alignItems: 'center',
|
|
1414
|
-
justifyContent: 'center',
|
|
1415
|
-
flexShrink: 0,
|
|
1416
|
-
'&.ss__chat__actions__facet__option__checkbox--checked': {
|
|
1417
|
-
background: '#253B80',
|
|
1418
|
-
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,
|
|
1419
1703
|
},
|
|
1420
1704
|
},
|
|
1421
|
-
'.ss__chat__actions__facet__option__label': {
|
|
1422
|
-
fontSize: '14px',
|
|
1423
|
-
color: '#333',
|
|
1424
|
-
flex: '1 1 auto',
|
|
1425
|
-
textAlign: 'left',
|
|
1426
|
-
},
|
|
1427
1705
|
},
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
borderRadius: 0,
|
|
1434
|
-
boxSizing: 'border-box',
|
|
1435
|
-
background: '#fff',
|
|
1436
|
-
'&:hover': {
|
|
1437
|
-
background: '#f4f4ff',
|
|
1438
|
-
},
|
|
1706
|
+
'.ss__chat__actions__facet__option__label': {
|
|
1707
|
+
fontSize: '14px',
|
|
1708
|
+
color: '#333',
|
|
1709
|
+
flex: '1 1 auto',
|
|
1710
|
+
textAlign: 'left',
|
|
1439
1711
|
},
|
|
1440
|
-
}
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
}
|
|
1475
|
-
:
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
activeMessage?.messageType === '
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
item.
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
id: result?.id,
|
|
1529
|
-
name: d?.mappings?.core?.name || '',
|
|
1530
|
-
imageUrl: d?.mappings?.core?.thumbnailImageUrl || d?.mappings?.core?.imageUrl || '',
|
|
1531
|
-
onClick: isMobile
|
|
1532
|
-
? () => {
|
|
1533
|
-
controller.viewProduct(result);
|
|
1534
|
-
setMobileProductInfoOpen(true);
|
|
1535
|
-
}
|
|
1536
|
-
: undefined,
|
|
1537
|
-
};
|
|
1538
|
-
})
|
|
1539
|
-
: showCommittedComparisons
|
|
1540
|
-
? (store.currentChat?.comparisons.committed || []).map((comparisonItem) => {
|
|
1541
|
-
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;
|
|
1542
1800
|
return {
|
|
1543
|
-
id:
|
|
1801
|
+
id: result?.id,
|
|
1544
1802
|
name: d?.mappings?.core?.name || '',
|
|
1545
1803
|
imageUrl: d?.mappings?.core?.thumbnailImageUrl || d?.mappings?.core?.imageUrl || '',
|
|
1546
1804
|
onClick: isMobile
|
|
1547
1805
|
? () => {
|
|
1548
|
-
controller.
|
|
1806
|
+
controller.productQuickView(result);
|
|
1549
1807
|
setMobileProductInfoOpen(true);
|
|
1550
1808
|
}
|
|
1551
1809
|
: undefined,
|
|
1552
1810
|
};
|
|
1553
1811
|
})
|
|
1554
|
-
:
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
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();
|
|
1565
1843
|
},
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
: 'Start a fresh session for better assistance, or keep going in this one?';
|
|
1605
|
-
const buttonText = isScopeRedirect ? '' : 'New Session';
|
|
1606
|
-
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: () => {
|
|
1607
|
-
if (isScopeRedirect) {
|
|
1608
|
-
store.currentChat?.dismissTopicDrift();
|
|
1609
|
-
return;
|
|
1610
|
-
}
|
|
1611
|
-
const messageText = store.currentChat?.handleTopicDrift();
|
|
1612
|
-
if (messageText) {
|
|
1613
|
-
controller.store.createChat();
|
|
1614
|
-
controller.search({ data: { message: messageText } });
|
|
1615
|
-
}
|
|
1616
|
-
}, children: buttonText })), _jsx("span", { onClick: () => {
|
|
1617
|
-
store.currentChat?.dismissTopicDrift();
|
|
1618
|
-
}, children: _jsx(Icon, { icon: "close-thin", size: "14px", className: 'ss__chat__topic-drift__icon--close' }) })] }));
|
|
1619
|
-
})(), _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: (() => {
|
|
1620
|
-
const comparedCount = store.currentChat?.comparisons.compared.length || 0;
|
|
1621
|
-
const committedCount = store.currentChat?.comparisons.committed.length || 0;
|
|
1622
|
-
const attached = store.currentChat?.attachments.attached.filter((item) => item.state === 'attached' || item.state === 'active') || [];
|
|
1623
|
-
const attachedProducts = attached.filter((item) => item.type === 'product');
|
|
1624
|
-
const attachedImages = attached.filter((item) => item.type === 'image' && !item.error);
|
|
1625
|
-
if (attachedProducts.length === 1) {
|
|
1626
|
-
return 'Ask about this product...';
|
|
1627
|
-
}
|
|
1628
|
-
if (comparedCount > 1 || attachedProducts.length > 1) {
|
|
1629
|
-
return 'What would you like to compare?';
|
|
1630
|
-
}
|
|
1631
|
-
if (committedCount > 0) {
|
|
1632
|
-
return 'Ask about the compared products...';
|
|
1633
|
-
}
|
|
1634
|
-
if (attachedImages.length > 0) {
|
|
1635
|
-
return 'Ask about this image...';
|
|
1636
|
-
}
|
|
1637
|
-
if (comparedCount === 1) {
|
|
1638
|
-
return 'Add another product to compare...';
|
|
1639
|
-
}
|
|
1640
|
-
return 'Type your message...';
|
|
1641
|
-
})(), onInput: (e) => controller.handlers.input.input(e), onKeyDown: (e) => {
|
|
1642
|
-
controller.handlers.input.enterKey(e);
|
|
1643
|
-
if (e.keyCode === 13 && isMobile && mobileProductInfoOpen) {
|
|
1644
|
-
setMobileProductInfoOpen(false);
|
|
1645
|
-
}
|
|
1646
|
-
}, 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) => {
|
|
1647
|
-
await controller.upload(e.target.files);
|
|
1648
|
-
// reset value
|
|
1649
|
-
e.target.value = '';
|
|
1650
|
-
}, multiple: true, type: "file", accept: "image/*", className: "ss__chat__input__input__file" })] }))] }), _jsx("div", { className: 'ss__chat__input__actions', children: (() => {
|
|
1651
|
-
const hasImageAttachment = (store.currentChat?.attachments.attached || []).some((item) => item.type === 'image' && !item.error);
|
|
1652
|
-
const messageEmpty = !controller.store.inputValue.trim();
|
|
1653
|
-
const sendDisabled = store.blocked || store.currentChat?.sessionLimitReached || (hasImageAttachment && messageEmpty) || messageEmpty;
|
|
1654
|
-
return (_jsx(Button, { className: "ss__chat__send-button", icon: { icon: 'send', title: 'Send Message' }, disabled: sendDisabled, onClick: () => {
|
|
1655
|
-
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();
|
|
1656
1882
|
return;
|
|
1657
|
-
controller.search();
|
|
1658
|
-
if (isMobile && mobileProductInfoOpen) {
|
|
1659
|
-
setMobileProductInfoOpen(false);
|
|
1660
1883
|
}
|
|
1661
|
-
|
|
1662
|
-
|
|
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() })] }) }));
|
|
1663
1940
|
});
|