@athoscommerce/snap-preact 1.13.3-beta.168 → 1.13.3-beta.187

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/cjs/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.js +3 -1
  2. package/dist/cjs/components/src/components/Molecules/ChatMessageText/ChatMessageText.js +2 -1
  3. package/dist/cjs/components/src/components/Molecules/ChatMessageUser/ChatMessageUser.js +4 -0
  4. package/dist/cjs/components/src/components/Molecules/ChatProductComparisonMessage/ChatProductComparisonMessage.js +1 -0
  5. package/dist/cjs/components/src/components/Molecules/ChatQuickview/ChatQuickview.js +514 -0
  6. package/dist/cjs/components/src/components/Molecules/{ChatProductQueryMessage → ChatQuickview}/index.js +1 -1
  7. package/dist/cjs/components/src/components/Molecules/ChatResultsDisplay/ChatResultsDisplay.js +2 -2
  8. package/dist/cjs/components/src/components/Molecules/Slideshow/Slideshow.js +47 -20
  9. package/dist/cjs/components/src/components/Organisms/Chat/Chat.js +12 -5
  10. package/dist/cjs/components/src/components/Organisms/Chat/Chat.lang.js +5 -0
  11. package/dist/cjs/components/src/components/Organisms/Chat/components/ChatAttachments.js +5 -4
  12. package/dist/cjs/components/src/components/Organisms/Chat/components/ChatComposer.js +3 -3
  13. package/dist/cjs/components/src/components/Organisms/Chat/components/ChatSideChat.js +3 -3
  14. package/dist/cjs/components/src/components/Organisms/Chat/components/chatAccentTheme.js +22 -20
  15. package/dist/cjs/components/src/components/Organisms/QuickviewLayout/QuickviewLayout.js +44 -11
  16. package/dist/cjs/components/src/index.js +1 -1
  17. package/dist/cjs/components/src/providers/themeComponents.js +1 -1
  18. package/dist/cjs/src/Snap.js +13 -1
  19. package/dist/cjs/src/Templates/Stores/LibraryStore.js +2 -2
  20. package/dist/cjs/src/Templates/Stores/library/languages/ar.js +45 -34
  21. package/dist/cjs/src/Templates/Stores/library/languages/de.js +45 -34
  22. package/dist/cjs/src/Templates/Stores/library/languages/es.js +45 -34
  23. package/dist/cjs/src/Templates/Stores/library/languages/fr.js +45 -34
  24. package/dist/cjs/src/Templates/Stores/library/languages/hi.js +45 -34
  25. package/dist/cjs/src/Templates/Stores/library/languages/it.js +45 -34
  26. package/dist/cjs/src/Templates/Stores/library/languages/ja.js +45 -34
  27. package/dist/cjs/src/Templates/Stores/library/languages/ko.js +45 -34
  28. package/dist/cjs/src/Templates/Stores/library/languages/nl.js +45 -34
  29. package/dist/cjs/src/Templates/Stores/library/languages/pt.js +45 -34
  30. package/dist/cjs/src/Templates/Stores/library/languages/ru.js +45 -34
  31. package/dist/cjs/src/Templates/Stores/library/languages/tr.js +45 -34
  32. package/dist/cjs/src/Templates/Stores/library/languages/vi.js +45 -34
  33. package/dist/cjs/src/Templates/Stores/library/languages/zh.js +45 -34
  34. package/dist/cjs/src/create/createChatController.js +1 -0
  35. package/dist/esm/components/src/components/Atoms/Button/Button.d.ts +1 -1
  36. package/dist/esm/components/src/components/Atoms/Button/Button.d.ts.map +1 -1
  37. package/dist/esm/components/src/components/Molecules/ChatAttachmentContext/ChatAttachmentContext.d.ts +12 -5
  38. package/dist/esm/components/src/components/Molecules/ChatAttachmentContext/ChatAttachmentContext.d.ts.map +1 -1
  39. package/dist/esm/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.d.ts +13 -2
  40. package/dist/esm/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.d.ts.map +1 -1
  41. package/dist/esm/components/src/components/Molecules/ChatInspirationResultMessage/ChatInspirationResultMessage.js +3 -1
  42. package/dist/esm/components/src/components/Molecules/ChatMessageText/ChatMessageText.d.ts.map +1 -1
  43. package/dist/esm/components/src/components/Molecules/ChatMessageText/ChatMessageText.js +2 -1
  44. package/dist/esm/components/src/components/Molecules/ChatMessageUser/ChatMessageUser.d.ts +17 -3
  45. package/dist/esm/components/src/components/Molecules/ChatMessageUser/ChatMessageUser.d.ts.map +1 -1
  46. package/dist/esm/components/src/components/Molecules/ChatMessageUser/ChatMessageUser.js +4 -0
  47. package/dist/esm/components/src/components/Molecules/ChatProductComparisonMessage/ChatProductComparisonMessage.d.ts +7 -1
  48. package/dist/esm/components/src/components/Molecules/ChatProductComparisonMessage/ChatProductComparisonMessage.d.ts.map +1 -1
  49. package/dist/esm/components/src/components/Molecules/ChatProductComparisonMessage/ChatProductComparisonMessage.js +1 -0
  50. package/dist/esm/components/src/components/Molecules/ChatQuickview/ChatQuickview.d.ts +30 -0
  51. package/dist/esm/components/src/components/Molecules/ChatQuickview/ChatQuickview.d.ts.map +1 -0
  52. package/dist/esm/components/src/components/Molecules/ChatQuickview/ChatQuickview.js +508 -0
  53. package/dist/esm/components/src/components/Molecules/ChatQuickview/index.d.ts +2 -0
  54. package/dist/esm/components/src/components/Molecules/ChatQuickview/index.d.ts.map +1 -0
  55. package/dist/esm/components/src/components/Molecules/ChatQuickview/index.js +1 -0
  56. package/dist/esm/components/src/components/Molecules/ChatResultsDisplay/ChatResultsDisplay.js +2 -2
  57. package/dist/esm/components/src/components/Molecules/Slideshow/Slideshow.d.ts.map +1 -1
  58. package/dist/esm/components/src/components/Molecules/Slideshow/Slideshow.js +47 -20
  59. package/dist/esm/components/src/components/Organisms/Chat/Chat.d.ts.map +1 -1
  60. package/dist/esm/components/src/components/Organisms/Chat/Chat.js +12 -5
  61. package/dist/esm/components/src/components/Organisms/Chat/Chat.lang.d.ts +3 -0
  62. package/dist/esm/components/src/components/Organisms/Chat/Chat.lang.d.ts.map +1 -1
  63. package/dist/esm/components/src/components/Organisms/Chat/Chat.lang.js +5 -0
  64. package/dist/esm/components/src/components/Organisms/Chat/components/ChatAttachments.d.ts.map +1 -1
  65. package/dist/esm/components/src/components/Organisms/Chat/components/ChatAttachments.js +5 -4
  66. package/dist/esm/components/src/components/Organisms/Chat/components/ChatComposer.d.ts.map +1 -1
  67. package/dist/esm/components/src/components/Organisms/Chat/components/ChatComposer.js +3 -3
  68. package/dist/esm/components/src/components/Organisms/Chat/components/ChatSideChat.d.ts.map +1 -1
  69. package/dist/esm/components/src/components/Organisms/Chat/components/ChatSideChat.js +3 -3
  70. package/dist/esm/components/src/components/Organisms/Chat/components/chatAccentTheme.d.ts +1 -1
  71. package/dist/esm/components/src/components/Organisms/Chat/components/chatAccentTheme.d.ts.map +1 -1
  72. package/dist/esm/components/src/components/Organisms/Chat/components/chatAccentTheme.js +22 -20
  73. package/dist/esm/components/src/components/Organisms/QuickviewLayout/QuickviewLayout.d.ts +5 -1
  74. package/dist/esm/components/src/components/Organisms/QuickviewLayout/QuickviewLayout.d.ts.map +1 -1
  75. package/dist/esm/components/src/components/Organisms/QuickviewLayout/QuickviewLayout.js +44 -11
  76. package/dist/esm/components/src/index.d.ts +1 -1
  77. package/dist/esm/components/src/index.d.ts.map +1 -1
  78. package/dist/esm/components/src/index.js +1 -1
  79. package/dist/esm/components/src/providers/langComponents.d.ts +2 -2
  80. package/dist/esm/components/src/providers/langComponents.d.ts.map +1 -1
  81. package/dist/esm/components/src/providers/themeComponents.d.ts +7 -7
  82. package/dist/esm/components/src/providers/themeComponents.d.ts.map +1 -1
  83. package/dist/esm/components/src/providers/themeComponents.js +1 -1
  84. package/dist/esm/src/Snap.d.ts +1 -0
  85. package/dist/esm/src/Snap.d.ts.map +1 -1
  86. package/dist/esm/src/Snap.js +13 -1
  87. package/dist/esm/src/Templates/Stores/LibraryStore.d.ts +2 -2
  88. package/dist/esm/src/Templates/Stores/LibraryStore.d.ts.map +1 -1
  89. package/dist/esm/src/Templates/Stores/LibraryStore.js +2 -2
  90. package/dist/esm/src/Templates/Stores/library/languages/ar.d.ts.map +1 -1
  91. package/dist/esm/src/Templates/Stores/library/languages/ar.js +45 -34
  92. package/dist/esm/src/Templates/Stores/library/languages/de.d.ts.map +1 -1
  93. package/dist/esm/src/Templates/Stores/library/languages/de.js +45 -34
  94. package/dist/esm/src/Templates/Stores/library/languages/es.d.ts.map +1 -1
  95. package/dist/esm/src/Templates/Stores/library/languages/es.js +45 -34
  96. package/dist/esm/src/Templates/Stores/library/languages/fr.d.ts.map +1 -1
  97. package/dist/esm/src/Templates/Stores/library/languages/fr.js +45 -34
  98. package/dist/esm/src/Templates/Stores/library/languages/hi.d.ts.map +1 -1
  99. package/dist/esm/src/Templates/Stores/library/languages/hi.js +45 -34
  100. package/dist/esm/src/Templates/Stores/library/languages/it.d.ts.map +1 -1
  101. package/dist/esm/src/Templates/Stores/library/languages/it.js +45 -34
  102. package/dist/esm/src/Templates/Stores/library/languages/ja.d.ts.map +1 -1
  103. package/dist/esm/src/Templates/Stores/library/languages/ja.js +45 -34
  104. package/dist/esm/src/Templates/Stores/library/languages/ko.d.ts.map +1 -1
  105. package/dist/esm/src/Templates/Stores/library/languages/ko.js +45 -34
  106. package/dist/esm/src/Templates/Stores/library/languages/nl.d.ts.map +1 -1
  107. package/dist/esm/src/Templates/Stores/library/languages/nl.js +45 -34
  108. package/dist/esm/src/Templates/Stores/library/languages/pt.d.ts.map +1 -1
  109. package/dist/esm/src/Templates/Stores/library/languages/pt.js +45 -34
  110. package/dist/esm/src/Templates/Stores/library/languages/ru.d.ts.map +1 -1
  111. package/dist/esm/src/Templates/Stores/library/languages/ru.js +45 -34
  112. package/dist/esm/src/Templates/Stores/library/languages/tr.d.ts.map +1 -1
  113. package/dist/esm/src/Templates/Stores/library/languages/tr.js +45 -34
  114. package/dist/esm/src/Templates/Stores/library/languages/vi.d.ts.map +1 -1
  115. package/dist/esm/src/Templates/Stores/library/languages/vi.js +45 -34
  116. package/dist/esm/src/Templates/Stores/library/languages/zh.d.ts.map +1 -1
  117. package/dist/esm/src/Templates/Stores/library/languages/zh.js +45 -34
  118. package/dist/esm/src/create/createChatController.js +1 -0
  119. package/package.json +12 -12
  120. package/dist/cjs/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.js +0 -577
  121. package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts +0 -38
  122. package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts.map +0 -1
  123. package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.js +0 -571
  124. package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/index.d.ts +0 -2
  125. package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/index.d.ts.map +0 -1
  126. package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/index.js +0 -1
@@ -1,571 +0,0 @@
1
- import { createElement as _createElement } from "@emotion/react";
2
- import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
3
- import { useEffect } from 'preact/hooks';
4
- import { observer } from 'mobx-react-lite';
5
- import { css } from '@emotion/react';
6
- import classnames from 'classnames';
7
- import deepmerge from 'deepmerge';
8
- import { useTheme, CacheProvider, useTreePath } from '../../../providers';
9
- import { Colour, defined, mergeProps, mergeStyles } from '../../../utilities';
10
- import { useLang, useCustomComponentOverride } from '../../../hooks';
11
- import { Image } from '../../Atoms/Image';
12
- import { Button } from '../../Atoms/Button';
13
- import { Price } from '../../Atoms/Price';
14
- const defaultStyles = ({ primaryColor, primaryColorText, theme }) => {
15
- const colorPrimary = primaryColor || Colour.concrete(theme?.variables?.colors?.primary) || '#253B80';
16
- const colorPrimaryText = primaryColorText || '#fff';
17
- const colorAccent = Colour.concrete(theme?.variables?.colors?.accent) || '#D4A843';
18
- const colorCta = Colour.concrete(theme?.variables?.colors?.accent) || '#feeeae';
19
- // neutral colors — no theme variable equivalents
20
- const colorText = '#374151';
21
- const colorBorder = '#E5E7EB';
22
- return css({
23
- display: 'flex',
24
- flexDirection: 'column',
25
- gap: '1em',
26
- paddingBottom: '1em',
27
- '.ss__chat-product-query-message__header__back.ss__button': {
28
- // Overlay banner pinned to the top of the secondary chat's scrollable messages
29
- // container so it stays visible while the product details scroll underneath.
30
- // Styling mirrors `.ss__chat__session-feedback` (dark primary bg, primary text,
31
- // 8px/15px padding, 10px gap, 14px font). Rendered as a direct child of the
32
- // component root (not the header) so sticky holds across the full scroll range.
33
- // Negative marginBottom cancels the root's `gap: 1em` so the banner sits flush
34
- // against the header below it.
35
- position: 'sticky',
36
- top: 0,
37
- zIndex: 2,
38
- marginBottom: '-1em',
39
- display: 'flex',
40
- flexDirection: 'row-reverse',
41
- justifyContent: 'flex-end',
42
- alignItems: 'center',
43
- gap: '10px',
44
- padding: '8px 15px',
45
- background: colorPrimary,
46
- color: colorPrimaryText,
47
- fontSize: '14px',
48
- cursor: 'pointer',
49
- border: 'none',
50
- font: 'inherit',
51
- width: 'auto',
52
- '.ss__button__content': {
53
- width: 'auto',
54
- },
55
- // pin the background so the Chat organism's generic `.ss__button:hover`
56
- // lightening rule (higher specificity) doesn't recolor the banner
57
- '&:not(.ss__button--disabled):hover': {
58
- background: colorPrimary,
59
- },
60
- '&:focus-visible': {
61
- outline: `2px solid ${colorPrimaryText}`,
62
- outlineOffset: '-2px',
63
- },
64
- svg: {
65
- fill: colorPrimaryText,
66
- stroke: colorPrimaryText,
67
- },
68
- },
69
- '.ss__chat-product-query-message__header': {
70
- background: colorPrimary,
71
- padding: '1em',
72
- display: 'flex',
73
- flexDirection: 'column',
74
- '.ss__price': {
75
- color: colorPrimaryText,
76
- },
77
- '.ss__chat-product-query-message__header__product': {
78
- display: 'flex',
79
- gap: '1em',
80
- '.ss__chat-product-query-message__header__product__image': {
81
- width: '25%',
82
- objectFit: 'contain',
83
- flexShrink: 0,
84
- borderRadius: '0.33em',
85
- overflow: 'hidden',
86
- },
87
- '.ss__chat-product-query-message__header__product__details': {
88
- display: 'flex',
89
- flexDirection: 'column',
90
- gap: '0.5em',
91
- flex: 1,
92
- justifyContent: 'space-evenly',
93
- '.ss__chat-product-query-message__header__product__details__name': {
94
- fontWeight: 'bold',
95
- fontSize: '1.2em',
96
- a: {
97
- color: colorPrimaryText,
98
- textDecoration: 'none',
99
- '&:hover': {
100
- textDecoration: 'underline',
101
- },
102
- },
103
- },
104
- '.ss__chat-product-query-message__header__product__details__price': {
105
- fontWeight: 'bold',
106
- fontSize: '1.1em',
107
- color: colorAccent,
108
- display: 'flex',
109
- gap: '0.5em',
110
- alignItems: 'center',
111
- },
112
- },
113
- '.ss__chat-product-query-message__header__product__actions': {
114
- display: 'flex',
115
- flexDirection: 'row',
116
- gap: '0.5em',
117
- '.ss__chat-product-query-message__header__product__actions__add-to-cart .ss__button': {
118
- flexDirection: 'row-reverse',
119
- borderRadius: '0.5em',
120
- padding: '0.4em 0.75em',
121
- fontWeight: 'bold',
122
- border: 'none',
123
- whiteSpace: 'nowrap',
124
- cursor: 'pointer',
125
- fontSize: '0.8em',
126
- background: colorCta,
127
- color: '#000',
128
- justifyContent: 'center',
129
- width: '100%',
130
- textAlign: 'center',
131
- svg: {
132
- fill: '#000',
133
- stroke: '#000',
134
- },
135
- '&:not(.ss__button--disabled):hover': {
136
- filter: 'brightness(0.97)',
137
- },
138
- },
139
- '.ss__chat-product-query-message__header__product__actions__show-similar .ss__button, .ss__chat-product-query-message__header__product__actions__discuss-product .ss__button': {
140
- flexDirection: 'row-reverse',
141
- borderRadius: '0.5em',
142
- padding: '0.4em 0.75em',
143
- fontWeight: 'bold',
144
- whiteSpace: 'nowrap',
145
- cursor: 'pointer',
146
- fontSize: '0.8em',
147
- background: '#000',
148
- color: '#fff',
149
- justifyContent: 'center',
150
- width: '100%',
151
- textAlign: 'center',
152
- svg: {
153
- fill: '#fff',
154
- stroke: '#fff',
155
- },
156
- },
157
- },
158
- },
159
- },
160
- '.ss__chat-product-query-message__variants': {
161
- padding: '0 2em',
162
- display: 'flex',
163
- flexDirection: 'column',
164
- gap: '1em',
165
- '.ss__chat-product-query-message__variants__label': {
166
- fontWeight: '600',
167
- fontSize: '0.9em',
168
- color: colorText,
169
- textTransform: 'uppercase',
170
- marginBottom: '0.5em',
171
- },
172
- '.ss__chat-product-query-message__variants__swatches': {
173
- display: 'flex',
174
- flexWrap: 'wrap',
175
- gap: '0.5em',
176
- '.ss__chat-product-query-message__variants__swatch.ss__button': {
177
- display: 'flex',
178
- flex: '1 1 auto',
179
- cursor: 'pointer',
180
- padding: '0.25em',
181
- borderRadius: '0.5em',
182
- border: '2px solid transparent',
183
- transition: 'border-color 0.15s ease',
184
- background: 'transparent',
185
- font: 'inherit',
186
- color: 'inherit',
187
- '.ss__button__content': {
188
- display: 'flex',
189
- flexDirection: 'column',
190
- alignItems: 'center',
191
- gap: '0.25em',
192
- },
193
- '&:not(.ss__button--disabled):hover': {
194
- borderColor: colorPrimary,
195
- },
196
- '&:focus-visible': {
197
- outline: `2px solid ${colorPrimary}`,
198
- outlineOffset: '2px',
199
- },
200
- '&[aria-disabled="true"]': {
201
- cursor: 'not-allowed',
202
- },
203
- '&.ss__chat-product-query-message__variants__swatch--selected': {
204
- borderColor: colorPrimary,
205
- borderWidth: '3px',
206
- padding: '0.15em',
207
- },
208
- '&.ss__chat-product-query-message__variants__swatch--unavailable': {
209
- opacity: 0.4,
210
- },
211
- '&.ss__chat-product-query-message__variants__swatch--text-only': {
212
- padding: '0.4em 0.75em',
213
- '&.ss__chat-product-query-message__variants__swatch--selected': {
214
- padding: '0.3em 0.65em',
215
- },
216
- '.ss__chat-product-query-message__variants__swatch__value': {
217
- fontSize: '1em',
218
- maxWidth: 'none',
219
- },
220
- },
221
- '.ss__chat-product-query-message__variants__swatch__image': {
222
- width: '48px',
223
- height: '48px',
224
- objectFit: 'cover',
225
- borderRadius: '50%',
226
- border: `1px solid ${colorBorder}`,
227
- },
228
- '.ss__chat-product-query-message__variants__swatch__value': {
229
- fontSize: '0.75em',
230
- color: colorText,
231
- textAlign: 'center',
232
- maxWidth: '60px',
233
- overflow: 'hidden',
234
- textOverflow: 'ellipsis',
235
- whiteSpace: 'nowrap',
236
- },
237
- },
238
- },
239
- },
240
- '.ss__chat-product-query-message__section': {
241
- padding: '0 1em',
242
- '.ss__chat-product-query-message__section__table': {
243
- width: '100%',
244
- maxWidth: '100%',
245
- tableLayout: 'fixed',
246
- borderCollapse: 'separate',
247
- borderSpacing: 0,
248
- fontSize: '0.9em',
249
- 'tbody tr': {
250
- transition: 'background-color 0.15s ease',
251
- },
252
- 'tbody tr:hover': {
253
- background: '#F3F4F6',
254
- },
255
- 'th, td': {
256
- padding: '0.75em 1em',
257
- verticalAlign: 'top',
258
- wordBreak: 'break-word',
259
- overflowWrap: 'anywhere',
260
- textAlign: 'left',
261
- borderBottom: `1px solid ${colorBorder}`,
262
- },
263
- 'tbody tr:last-of-type th, tbody tr:last-of-type td': {
264
- borderBottom: 'none',
265
- },
266
- 'th[scope="row"]': {
267
- fontWeight: '600',
268
- color: '#6B7280',
269
- textTransform: 'uppercase',
270
- fontSize: '0.8em',
271
- letterSpacing: '0.03em',
272
- width: '40%',
273
- },
274
- 'td:last-of-type': {
275
- textAlign: 'right',
276
- color: '#111827',
277
- fontWeight: '500',
278
- },
279
- '.ss__chat-product-query-message__section__table__availability--in-stock': {
280
- color: '#10B981',
281
- fontWeight: '600',
282
- },
283
- '.ss__chat-product-query-message__section__table__availability--out-of-stock': {
284
- color: '#DC2626',
285
- fontWeight: '600',
286
- },
287
- '.ss__chat-product-query-message__section__table__price': {
288
- display: 'flex',
289
- gap: '0.5em',
290
- alignItems: 'center',
291
- justifyContent: 'flex-end',
292
- },
293
- },
294
- },
295
- '.ss__chat-product-query-message__description': {
296
- padding: '0 1em',
297
- fontSize: '0.9em',
298
- color: colorText,
299
- lineHeight: '1.5',
300
- },
301
- });
302
- };
303
- // fields that have dedicated rendering in the product card; skip them in the info table
304
- const CARD_FIELDS = new Set([
305
- 'name',
306
- 'brand',
307
- 'price',
308
- 'msrp',
309
- 'imageUrl',
310
- 'thumbnailImageUrl',
311
- 'secureImageUrl',
312
- 'secureThumbnailImageUrl',
313
- 'url',
314
- 'addToCartUrl',
315
- 'uid',
316
- 'sku',
317
- 'parentId',
318
- 'parentImageUrl',
319
- 'description',
320
- 'caption',
321
- 'popularity',
322
- 'stockMessage',
323
- ]);
324
- // preferred ordering for the structured info table - any extras get appended after
325
- const PREFERRED_INFO_ORDER = ['material', 'fit', 'color', 'sizes', 'size', 'category', 'rating', 'availability'];
326
- const formatLabel = (key) => {
327
- return key
328
- .replace(/[_-]+/g, ' ')
329
- .replace(/([a-z])([A-Z])/g, '$1 $2')
330
- .trim();
331
- };
332
- const stripHtml = (str) => str.replace(/<[^>]*>/g, '');
333
- const formatValue = (value) => {
334
- if (Array.isArray(value)) {
335
- return stripHtml(value.filter((v) => v != null && v !== '').join(', '));
336
- }
337
- if (value == null) {
338
- return '';
339
- }
340
- return stripHtml(String(value));
341
- };
342
- const collectInfoRows = (display, availabilityLabels, displayFields) => {
343
- const core = display?.mappings?.core || {};
344
- const attributes = display?.attributes || {};
345
- const filterByDisplayFields = displayFields && displayFields.length > 0;
346
- const displayFieldsLower = filterByDisplayFields ? displayFields.map((f) => f.toLowerCase()) : [];
347
- const merged = {};
348
- // when displayFields is specified, include matching core fields that are normally skipped
349
- if (filterByDisplayFields) {
350
- Object.entries(core).forEach(([key, value]) => {
351
- if (displayFieldsLower.includes(key.toLowerCase()) && value != null) {
352
- merged[key] = value;
353
- }
354
- });
355
- }
356
- // pull selected core fields (rating + availability)
357
- if (core.rating != null) {
358
- const rating = core.rating;
359
- const ratingCount = core.ratingCount;
360
- merged.rating = ratingCount ? `${rating}/5.0 (${ratingCount} reviews)` : `${rating}/5.0`;
361
- }
362
- if (core.available != null) {
363
- merged.availability = core.available ? availabilityLabels.inStock : availabilityLabels.outOfStock;
364
- }
365
- // merge product attributes, skipping ones already shown on the card
366
- Object.entries(attributes).forEach(([key, value]) => {
367
- if (!filterByDisplayFields && CARD_FIELDS.has(key))
368
- return;
369
- const formatted = formatValue(value);
370
- if (!formatted)
371
- return;
372
- merged[key] = formatted;
373
- });
374
- const seen = new Set();
375
- const ordered = [];
376
- PREFERRED_INFO_ORDER.forEach((preferred) => {
377
- const match = Object.keys(merged).find((k) => k.toLowerCase() === preferred);
378
- if (match && !seen.has(match)) {
379
- seen.add(match);
380
- ordered.push({ key: match, rawKey: match, label: formatLabel(match), value: formatValue(merged[match]) });
381
- }
382
- });
383
- Object.keys(merged).forEach((key) => {
384
- if (seen.has(key))
385
- return;
386
- seen.add(key);
387
- ordered.push({ key, rawKey: key, label: formatLabel(key), value: formatValue(merged[key]) });
388
- });
389
- // filter and sort by displayFields order
390
- if (filterByDisplayFields) {
391
- const filtered = ordered.filter((row) => displayFieldsLower.includes(row.rawKey.toLowerCase()));
392
- filtered.sort((a, b) => displayFieldsLower.indexOf(a.rawKey.toLowerCase()) - displayFieldsLower.indexOf(b.rawKey.toLowerCase()));
393
- return filtered;
394
- }
395
- return ordered;
396
- };
397
- const resolveLangValue = (langEntry) => typeof langEntry?.value == 'function' ? langEntry.value() : langEntry?.value;
398
- export const ChatProductQueryMessage = observer((properties) => {
399
- const globalTheme = useTheme();
400
- const globalTreePath = useTreePath();
401
- const defaultProps = {
402
- treePath: globalTreePath,
403
- };
404
- const props = mergeProps('chatProductQueryMessage', globalTheme, defaultProps, properties);
405
- const { chatItem, controller, displayFields, disableStyles, className, internalClassName, treePath } = props;
406
- const { overrideElement, shouldRenderDefault } = useCustomComponentOverride('chatProductQueryMessage', props);
407
- const subProps = {
408
- image: {
409
- // inherited props
410
- ...defined({
411
- disableStyles,
412
- }),
413
- // component theme overrides
414
- theme: props?.theme,
415
- treePath,
416
- },
417
- button: {
418
- disableStyles,
419
- theme: props.theme,
420
- treePath,
421
- },
422
- };
423
- const styling = mergeStyles(props, defaultStyles);
424
- const { messageType, sourceProduct } = chatItem;
425
- const product = controller?.store.productQuickview;
426
- const productQuickviewError = controller?.store.productQuickviewError;
427
- const chatMessages = controller?.store.currentChat?.chat || [];
428
- const sourceMessage = chatItem.sourceMessageId ? chatMessages.find((m) => m.id === chatItem.sourceMessageId) : null;
429
- const cameFromInspiration = sourceMessage?.messageType === 'inspirationResult';
430
- const cameFromComparison = sourceMessage?.messageType === 'productComparison';
431
- const variants = product?.variants;
432
- const selections = variants?.selections || [];
433
- // Ensure every selection has an initial value picked. Without this, entering
434
- // the quickview from inspiration leaves all selections empty, and the first
435
- // variant click can't narrow `refineSelections` to a single variant — so the
436
- // active variant (and hero image) doesn't update until a second selection is
437
- // made. Prefer the variant whose own id (uid) matches the clicked result's id
438
- // so the panel reflects exactly the variant the user clicked; fall back to the
439
- // first available value. Single-value selections also get hidden from the UI
440
- // (handled by `visibleSelections` below).
441
- useEffect(() => {
442
- if (messageType !== 'productQuery' || !product)
443
- return;
444
- const sourceId = sourceProduct?.id;
445
- const matchedVariant = sourceId != null ? variants?.data?.find((variant) => variant.mappings?.core?.uid === sourceId) : undefined;
446
- selections.forEach((selection) => {
447
- if (selection.selected)
448
- return;
449
- const matchedValue = matchedVariant?.options?.[selection.field]?.value;
450
- const target = (matchedValue != null && selection.values.find((v) => v.available && v.value == matchedValue)) ||
451
- selection.values.find((v) => v.available) ||
452
- selection.values[0];
453
- if (target) {
454
- selection.select(target.value);
455
- }
456
- });
457
- }, [selections]);
458
- // after all hooks — an override that resolves or fails mid-lifecycle must not
459
- // change the hook count between renders
460
- if (!shouldRenderDefault) {
461
- return overrideElement;
462
- }
463
- //initialize lang
464
- const defaultLang = {
465
- loadingText: {
466
- value: 'Loading product details...',
467
- },
468
- backToComparisonButton: {
469
- value: 'Back to comparison',
470
- attributes: {
471
- 'aria-label': 'Back to comparison',
472
- },
473
- },
474
- backToInspirationButton: {
475
- value: 'Back to inspiration',
476
- attributes: {
477
- 'aria-label': 'Back to inspiration',
478
- },
479
- },
480
- addToCartButton: {
481
- value: 'Add to Cart',
482
- },
483
- similarButton: {
484
- value: 'Similar',
485
- },
486
- discussButton: {
487
- value: 'Discuss',
488
- },
489
- inStockText: {
490
- value: 'In Stock',
491
- },
492
- outOfStockText: {
493
- value: 'Out of Stock',
494
- },
495
- unavailableText: {
496
- value: 'unavailable',
497
- },
498
- variantsGroup: {
499
- attributes: {
500
- 'aria-label': 'Variant selection',
501
- },
502
- },
503
- productInformationTable: {
504
- attributes: {
505
- 'aria-label': 'Product information',
506
- },
507
- },
508
- };
509
- //deep merge with props.lang
510
- const lang = deepmerge(defaultLang, props.lang || {});
511
- const mergedLang = useLang(lang, {
512
- controller,
513
- chatItem,
514
- }, { activeBreakpoint: globalTheme?.activeBreakpoint });
515
- if (messageType !== 'productQuery') {
516
- controller?.log?.warn('ChatProductQueryMessage received message with unsupported type:', messageType, 'Expected type: productQuery');
517
- return null;
518
- }
519
- if (!product) {
520
- return (_jsx(CacheProvider, { children: _jsx("div", { className: classnames('ss__chat-product-query-message', className, internalClassName), ...styling, children: _jsx("div", { className: classnames('ss__chat-product-query-message__header'), children: _jsx("div", { className: classnames('ss__chat-product-query-message__header__product'), children: _jsx("div", { className: classnames('ss__chat-product-query-message__header__product__details'), children: _jsx("div", { className: classnames('ss__chat-product-query-message__header__product__details__name'), children: productQuickviewError || resolveLangValue(lang.loadingText) }) }) }) }) }) }));
521
- }
522
- const displayed = product.display;
523
- const displayedCore = displayed.mappings?.core || {};
524
- const visibleSelections = selections.filter((selection) => selection.values.length > 1);
525
- const displayedData = {
526
- mappings: displayed.mappings,
527
- attributes: displayed.attributes || {},
528
- };
529
- const allInfoRows = collectInfoRows(displayedData, { inStock: resolveLangValue(lang.inStockText), outOfStock: resolveLangValue(lang.outOfStockText) }, displayFields);
530
- const descriptionRow = allInfoRows.find((row) => row.rawKey.toLowerCase() === 'description');
531
- const infoRows = allInfoRows.filter((row) => row.rawKey.toLowerCase() !== 'description');
532
- const handleBack = () => {
533
- controller?.store.currentChat?.popProductQueryMessage(chatItem.sourceMessageId);
534
- controller?.store.clearProductQuickview();
535
- };
536
- const unavailableText = resolveLangValue(lang.unavailableText);
537
- return (_jsx(CacheProvider, { children: _jsxs("div", { className: classnames('ss__chat-product-query-message', className, internalClassName), ...styling, children: [(cameFromInspiration || cameFromComparison) && (_jsx(Button, { ...subProps.button, internalClassName: classnames('ss__chat-product-query-message__header__back'), icon: { icon: 'angle-left', size: '14px' }, onClick: handleBack, lang: { button: cameFromComparison ? lang.backToComparisonButton : lang.backToInspirationButton } })), _jsx("div", { className: classnames('ss__chat-product-query-message__header'), children: _jsxs("div", { className: classnames('ss__chat-product-query-message__header__product'), children: [(displayedCore.imageUrl || displayedCore.parentImageUrl) && (_jsx(Image, { ...subProps.image, className: classnames('ss__chat-product-query-message__header__product__image'), src: (displayedCore.imageUrl || displayedCore.parentImageUrl), alt: displayedCore.name || '' })), _jsxs("div", { className: classnames('ss__chat-product-query-message__header__product__details'), children: [displayedCore.name && (_jsx("div", { className: classnames('ss__chat-product-query-message__header__product__details__name'), children: displayedCore.url ? (_jsx("a", { href: displayedCore.url, onClick: (e) => controller?.track.product.click(e, product), children: displayedCore.name })) : (displayedCore.name) })), displayedCore.price != null && (_jsxs("div", { className: classnames('ss__chat-product-query-message__header__product__details__price'), children: [displayedCore.msrp != null && Number(displayedCore.msrp) > Number(displayedCore.price) && (_jsx(Price, { value: displayedCore.msrp, lineThrough: true })), _jsx(Price, { value: displayedCore.price })] })), _jsxs("div", { className: classnames('ss__chat-product-query-message__header__product__actions'), children: [_jsx("div", { className: classnames('ss__chat-product-query-message__header__product__actions__add-to-cart'), children: _jsx(Button, { ...subProps.button, icon: "cart", onClick: () => {
538
- controller?.track.product.addToCart(product);
539
- controller?.addToCart(product);
540
- }, lang: { button: lang.addToCartButton } }) }), controller?.store.features.similarProducts.enabled && (_jsx("div", { className: classnames('ss__chat-product-query-message__header__product__actions__show-similar'), children: _jsx(Button, { ...subProps.button, icon: "search-thin", onClick: () => controller?.productSimilar(sourceProduct), lang: { button: lang.similarButton } }) })), _jsx("div", { className: classnames('ss__chat-product-query-message__header__product__actions__discuss-product'), children: _jsx(Button, { ...subProps.button, icon: "chat",
541
- // pass the quickview product (not sourceProduct) — its display is masked
542
- // to the active variant, so the attachment shows the selected variant
543
- onClick: () => controller?.productQuery(product), lang: { button: lang.discussButton } }) })] })] })] }) }), visibleSelections.length > 0 && (_jsx("div", { className: classnames('ss__chat-product-query-message__variants'), role: "group", ...mergedLang.variantsGroup.attributes, children: visibleSelections.map((selection) => {
544
- // If every value in this selection shares the same thumbnail (or none have
545
- // one), the image carries no signal — show text only.
546
- const firstThumb = selection.values[0]?.thumbnailImageUrl;
547
- const allSameThumb = selection.values.every((v) => v.thumbnailImageUrl === firstThumb);
548
- const showThumbs = !allSameThumb;
549
- return (_jsxs("div", { children: [_jsxs("div", { className: classnames('ss__chat-product-query-message__variants__label'), id: `ss__chat-pq-variant-${selection.field}`, children: [formatLabel(selection.field), " (", selection.values.length, ")"] }), _jsx("div", { className: classnames('ss__chat-product-query-message__variants__swatches'), role: "radiogroup", "aria-labelledby": `ss__chat-pq-variant-${selection.field}`, children: selection.values.map((selectionValue) => {
550
- const isUnavailable = !selectionValue.available;
551
- const isSelected = selection.selected?.value === selectionValue.value;
552
- return (_createElement(Button, { ...subProps.button, key: selectionValue.value, internalClassName: classnames('ss__chat-product-query-message__variants__swatch', {
553
- 'ss__chat-product-query-message__variants__swatch--selected': isSelected,
554
- 'ss__chat-product-query-message__variants__swatch--unavailable': isUnavailable,
555
- 'ss__chat-product-query-message__variants__swatch--text-only': !showThumbs,
556
- }), ...{ role: 'radio', 'aria-checked': isSelected }, disabled: isUnavailable, lang: {
557
- button: {
558
- attributes: {
559
- title: selectionValue.value,
560
- 'aria-label': `${formatLabel(selection.field)}: ${selectionValue.value}${isUnavailable ? ` (${unavailableText})` : ''}`,
561
- },
562
- },
563
- }, onClick: () => selection.select(selectionValue.value) },
564
- showThumbs && selectionValue.thumbnailImageUrl ? (_jsx(Image, { ...subProps.image, className: classnames('ss__chat-product-query-message__variants__swatch__image'), src: selectionValue.thumbnailImageUrl, alt: selectionValue.value })) : null,
565
- _jsx("span", { className: classnames('ss__chat-product-query-message__variants__swatch__value'), children: selectionValue.value })));
566
- }) })] }, selection.field));
567
- }) })), infoRows.length > 0 && (_jsx("div", { className: classnames('ss__chat-product-query-message__section'), children: _jsx("table", { className: classnames('ss__chat-product-query-message__section__table'), ...mergedLang.productInformationTable.attributes, children: _jsx("tbody", { children: infoRows.map((row) => (_jsxs("tr", { children: [_jsx("th", { scope: "row", children: row.label }), _jsx("td", { children: row.rawKey === 'availability' ? (_jsx("span", { className: classnames({
568
- 'ss__chat-product-query-message__section__table__availability--in-stock': displayedCore.available,
569
- 'ss__chat-product-query-message__section__table__availability--out-of-stock': !displayedCore.available,
570
- }), children: displayedCore.available ? `✓ ${row.value}` : row.value })) : row.rawKey.toLowerCase() === 'price' ? (_jsxs("span", { className: "ss__chat-product-query-message__section__table__price", children: [displayedCore.msrp != null && Number(displayedCore.msrp) > Number(row.value) && (_jsx(Price, { value: Number(displayedCore.msrp), lineThrough: true })), _jsx(Price, { value: Number(row.value) })] })) : (row.value) })] }, row.key))) }) }) })), descriptionRow && _jsx("div", { className: classnames('ss__chat-product-query-message__description'), children: descriptionRow.value })] }) }));
571
- });
@@ -1,2 +0,0 @@
1
- export * from './ChatProductQueryMessage';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../components/src/components/Molecules/ChatProductQueryMessage/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC"}
@@ -1 +0,0 @@
1
- export * from './ChatProductQueryMessage';