@athoscommerce/snap-preact 1.5.1-beta.112 → 1.5.1-beta.116
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/dist/cjs/components/src/components/Atoms/Dropdown/Dropdown.d.ts +3 -0
- package/dist/cjs/components/src/components/Atoms/Dropdown/Dropdown.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Atoms/Dropdown/Dropdown.js +28 -7
- package/dist/cjs/components/src/components/Molecules/ChatAttachmentContext/ChatAttachmentContext.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Molecules/ChatAttachmentContext/ChatAttachmentContext.js +3 -2
- package/dist/cjs/components/src/components/Molecules/ChatProductComparisonMessage/ChatProductComparisonMessage.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Molecules/ChatProductComparisonMessage/ChatProductComparisonMessage.js +22 -2
- package/dist/cjs/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.js +96 -66
- package/dist/cjs/components/src/components/Organisms/Chat/Chat.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Organisms/Chat/Chat.js +276 -76
- package/dist/cjs/components/src/components/Organisms/Chat/Chat.styles.d.ts.map +1 -1
- package/dist/cjs/components/src/components/Organisms/Chat/Chat.styles.js +217 -178
- package/dist/cjs/components/src/components/Organisms/Chat/hooks/useChatFileUpload.js +4 -4
- package/dist/cjs/src/Templates/SnapTemplates.d.ts.map +1 -1
- package/dist/cjs/src/Templates/SnapTemplates.js +1 -1
- package/dist/esm/components/src/components/Atoms/Dropdown/Dropdown.d.ts +3 -0
- package/dist/esm/components/src/components/Atoms/Dropdown/Dropdown.d.ts.map +1 -1
- package/dist/esm/components/src/components/Atoms/Dropdown/Dropdown.js +26 -8
- package/dist/esm/components/src/components/Molecules/ChatAttachmentContext/ChatAttachmentContext.d.ts.map +1 -1
- package/dist/esm/components/src/components/Molecules/ChatAttachmentContext/ChatAttachmentContext.js +3 -2
- package/dist/esm/components/src/components/Molecules/ChatProductComparisonMessage/ChatProductComparisonMessage.d.ts.map +1 -1
- package/dist/esm/components/src/components/Molecules/ChatProductComparisonMessage/ChatProductComparisonMessage.js +22 -2
- package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.d.ts.map +1 -1
- package/dist/esm/components/src/components/Molecules/ChatProductQueryMessage/ChatProductQueryMessage.js +94 -65
- package/dist/esm/components/src/components/Organisms/Chat/Chat.d.ts.map +1 -1
- package/dist/esm/components/src/components/Organisms/Chat/Chat.js +240 -45
- package/dist/esm/components/src/components/Organisms/Chat/Chat.styles.d.ts.map +1 -1
- package/dist/esm/components/src/components/Organisms/Chat/Chat.styles.js +73 -8
- package/dist/esm/components/src/components/Organisms/Chat/hooks/useChatFileUpload.js +3 -3
- package/dist/esm/src/Templates/SnapTemplates.d.ts.map +1 -1
- package/dist/esm/src/Templates/SnapTemplates.js +4 -1
- package/package.json +12 -12
|
@@ -83,7 +83,7 @@ var ChatInspirationResultMessage_1 = require("../../Molecules/ChatInspirationRes
|
|
|
83
83
|
var ChatProductComparisonMessage_1 = require("../../Molecules/ChatProductComparisonMessage/ChatProductComparisonMessage");
|
|
84
84
|
var ChatProductQueryMessage_1 = require("../../Molecules/ChatProductQueryMessage/ChatProductQueryMessage");
|
|
85
85
|
exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
86
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
|
|
86
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
|
|
87
87
|
var globalTheme = (0, providers_1.useTheme)();
|
|
88
88
|
var globalTreePath = (0, providers_1.useTreePath)();
|
|
89
89
|
var isMobile = (0, __1.useMediaQuery)('(max-width: 767px)');
|
|
@@ -92,7 +92,7 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
92
92
|
logo: 'https://cdn.athoscommerce.net/snap/images/Athos%20Commerce_Icon_white.svg',
|
|
93
93
|
title: 'Athos Conversational Assistant',
|
|
94
94
|
subtitle: 'Your Guided Discovery Expert',
|
|
95
|
-
multiselectFacets:
|
|
95
|
+
multiselectFacets: false,
|
|
96
96
|
disableBubbleSuggestedQuestions: isMobile ? true : false,
|
|
97
97
|
primaryColorBg: '#253B80',
|
|
98
98
|
primaryColorFg: '#fff',
|
|
@@ -174,33 +174,37 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
174
174
|
var chatRef = (0, hooks_1.useRef)(null);
|
|
175
175
|
// Ref for the mobile secondary panel — needed for swipe-to-dismiss measurements
|
|
176
176
|
var secondaryRef = (0, hooks_1.useRef)(null);
|
|
177
|
-
var
|
|
178
|
-
var
|
|
177
|
+
var _0 = (0, hooks_1.useState)(false), mobileProductInfoOpen = _0[0], setMobileProductInfoOpen = _0[1];
|
|
178
|
+
var _1 = (0, hooks_1.useState)(0), footerHeight = _1[0], setFooterHeight = _1[1];
|
|
179
179
|
var dropEnabled = store.features.imageSearch.enabled && !store.loading && !store.blocked && !((_a = store.currentChat) === null || _a === void 0 ? void 0 : _a.sessionLimitReached);
|
|
180
|
-
var
|
|
180
|
+
var _2 = (0, useChatFileUpload_1.useChatFileUpload)({
|
|
181
181
|
enabled: !!dropEnabled,
|
|
182
182
|
onUpload: function (files) { return controller.upload(files); },
|
|
183
|
-
}), fileInputRef =
|
|
183
|
+
}), fileInputRef = _2.fileInputRef, isDraggingFile = _2.isDraggingFile, dragHandlers = _2.dragHandlers;
|
|
184
184
|
// productQuery messages are filtered out of the main chat render (they only drive the side-chat panel),
|
|
185
185
|
// so don't auto-scroll when one is added — otherwise clicking a product in the side chat scrolls the main thread.
|
|
186
186
|
var visibleChat = (((_b = store.currentChat) === null || _b === void 0 ? void 0 : _b.chat) || []).filter(function (m) { return m.messageType !== 'productQuery'; });
|
|
187
187
|
var visibleChatLength = visibleChat.length;
|
|
188
188
|
var lastVisibleMessage = visibleChat[visibleChat.length - 1];
|
|
189
|
-
var
|
|
189
|
+
var _3 = (0, useChatOverflow_1.useChatOverflow)({
|
|
190
190
|
messagesContainerRef: messagesContainerRef,
|
|
191
191
|
headerRef: headerRef,
|
|
192
192
|
open: store.open,
|
|
193
193
|
loading: store.loading,
|
|
194
194
|
visibleChatLength: visibleChatLength,
|
|
195
195
|
lastVisibleMessage: lastVisibleMessage,
|
|
196
|
-
}), showNewMessages =
|
|
196
|
+
}), showNewMessages = _3.showNewMessages, setShowNewMessages = _3.setShowNewMessages, messagesOverflow = _3.messagesOverflow, scrollToBottom = _3.scrollToBottom, scrollToBottomIfNear = _3.scrollToBottomIfNear;
|
|
197
197
|
// Re-focus the chat input on desktop after a search completes.
|
|
198
198
|
// The input is disabled while loading, which causes the browser to drop focus.
|
|
199
199
|
// On mobile we intentionally skip this so the virtual keyboard dismisses.
|
|
200
|
+
// Only fire on the loading true → false transition — running on mount steals
|
|
201
|
+
// focus away from the Storybook controls whenever the story re-renders.
|
|
202
|
+
var prevLoadingRef = (0, hooks_1.useRef)(store.loading);
|
|
200
203
|
(0, hooks_1.useEffect)(function () {
|
|
201
|
-
if (!store.loading && !isMobile && store.open) {
|
|
204
|
+
if (prevLoadingRef.current && !store.loading && !isMobile && store.open) {
|
|
202
205
|
controller.focusInput();
|
|
203
206
|
}
|
|
207
|
+
prevLoadingRef.current = store.loading;
|
|
204
208
|
}, [store.loading]);
|
|
205
209
|
// const subProps: ChatSubProps = {};
|
|
206
210
|
var activeMessage = (_c = store.currentChat) === null || _c === void 0 ? void 0 : _c.activeMessage;
|
|
@@ -221,19 +225,34 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
221
225
|
var sideChatTypes = isMobile
|
|
222
226
|
? __spreadArray(__spreadArray(['inspirationResult'], (isFirstMobileComparison ? ['productComparison'] : []), true), (mobileProductInfoOpen ? ['productQuery'] : []), true) : ['inspirationResult', 'productComparison', 'productQuery'];
|
|
223
227
|
var shouldShowSideChat = activeMessage && sideChatTypes.includes(activeMessage === null || activeMessage === void 0 ? void 0 : activeMessage.messageType) && ((_d = store.currentChat) === null || _d === void 0 ? void 0 : _d.dismissedSideChatMessageId) !== activeMessage.id;
|
|
224
|
-
var
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
228
|
+
var hasSideChat = !!shouldShowSideChat;
|
|
229
|
+
var styling = (0, hooks_1.useMemo)(function () {
|
|
230
|
+
return (0, utilities_1.mergeStyles)({
|
|
231
|
+
mobile: isMobile,
|
|
232
|
+
offset: offset,
|
|
233
|
+
hasSideChat: hasSideChat,
|
|
234
|
+
footerHeight: footerHeight,
|
|
235
|
+
primaryColorBg: colorPrimary,
|
|
236
|
+
primaryColorFg: colorPrimaryText,
|
|
237
|
+
primaryAccentColorBg: colorPrimaryAccent,
|
|
238
|
+
primaryAccentColorFg: colorPrimaryAccentText,
|
|
239
|
+
secondaryAccentColorBg: colorSecondaryAccent,
|
|
240
|
+
secondaryAccentColorFg: colorSecondaryAccentText,
|
|
241
|
+
position: chatPosition,
|
|
242
|
+
}, Chat_styles_1.chatDefaultStyles);
|
|
243
|
+
}, [
|
|
244
|
+
isMobile,
|
|
245
|
+
offset,
|
|
246
|
+
hasSideChat,
|
|
247
|
+
footerHeight,
|
|
248
|
+
colorPrimary,
|
|
249
|
+
colorPrimaryText,
|
|
250
|
+
colorPrimaryAccent,
|
|
251
|
+
colorPrimaryAccentText,
|
|
252
|
+
colorSecondaryAccent,
|
|
253
|
+
colorSecondaryAccentText,
|
|
254
|
+
chatPosition,
|
|
255
|
+
]);
|
|
237
256
|
// Lock body scroll while chat is open so touch/wheel scrolls don't leak to the page behind
|
|
238
257
|
(0, hooks_1.useEffect)(function () {
|
|
239
258
|
if (!store.open)
|
|
@@ -281,6 +300,117 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
281
300
|
observer.observe(el);
|
|
282
301
|
return function () { return observer.disconnect(); };
|
|
283
302
|
}, [store.open, (_e = store.currentChat) === null || _e === void 0 ? void 0 : _e.isExpired]);
|
|
303
|
+
// Prevent the background page from scrolling while the chat is open on touch
|
|
304
|
+
// devices. iOS Safari (real iPad/iPhone) rubber-band-scrolls the body when a
|
|
305
|
+
// touchmove inside `.ss__chat__messages` reaches the top/bottom — and
|
|
306
|
+
// `overscroll-behavior: contain` is ignored there.
|
|
307
|
+
//
|
|
308
|
+
// We don't touch body styles (locking via `position: fixed` on `<body>` leaves
|
|
309
|
+
// iPad Safari in a stuck viewport state where the page can't scroll after the
|
|
310
|
+
// lock is released). Instead we install a `touchmove` handler that:
|
|
311
|
+
// - allows the touchmove if it's inside a scrollable region of the chat
|
|
312
|
+
// and that region isn't at its scroll edge in the swipe direction;
|
|
313
|
+
// - calls `preventDefault()` otherwise — which is what blocks both
|
|
314
|
+
// background scrolling and iOS rubber-band overscroll.
|
|
315
|
+
// Cleanup just removes the listeners, so nothing can leak into the page.
|
|
316
|
+
(0, hooks_1.useEffect)(function () {
|
|
317
|
+
if (!store.open)
|
|
318
|
+
return;
|
|
319
|
+
if (typeof document === 'undefined')
|
|
320
|
+
return;
|
|
321
|
+
var startX = 0;
|
|
322
|
+
var startY = 0;
|
|
323
|
+
var scrollEl = null;
|
|
324
|
+
// Walk up from the touch target to find the first ancestor inside the chat
|
|
325
|
+
// that is actually scrollable in either axis. Stop at the chat root so we
|
|
326
|
+
// never consider elements outside the chat.
|
|
327
|
+
var findScrollableInChat = function (start) {
|
|
328
|
+
var chatRoot = chatRef.current;
|
|
329
|
+
if (!chatRoot)
|
|
330
|
+
return null;
|
|
331
|
+
var el = start;
|
|
332
|
+
while (el && chatRoot.contains(el)) {
|
|
333
|
+
var style = getComputedStyle(el);
|
|
334
|
+
var scrollableY = (style.overflowY === 'auto' || style.overflowY === 'scroll') && el.scrollHeight > el.clientHeight;
|
|
335
|
+
var scrollableX = (style.overflowX === 'auto' || style.overflowX === 'scroll') && el.scrollWidth > el.clientWidth;
|
|
336
|
+
if (scrollableY || scrollableX) {
|
|
337
|
+
return el;
|
|
338
|
+
}
|
|
339
|
+
if (el === chatRoot)
|
|
340
|
+
break;
|
|
341
|
+
el = el.parentElement;
|
|
342
|
+
}
|
|
343
|
+
return null;
|
|
344
|
+
};
|
|
345
|
+
var onTouchStart = function (e) {
|
|
346
|
+
if (!e.touches[0])
|
|
347
|
+
return;
|
|
348
|
+
startX = e.touches[0].clientX;
|
|
349
|
+
startY = e.touches[0].clientY;
|
|
350
|
+
scrollEl = findScrollableInChat(e.target);
|
|
351
|
+
};
|
|
352
|
+
var onTouchMove = function (e) {
|
|
353
|
+
var _a, _b, _c, _d;
|
|
354
|
+
var target = e.target;
|
|
355
|
+
var chatRoot = chatRef.current;
|
|
356
|
+
var inChat = !!(chatRoot && target && chatRoot.contains(target));
|
|
357
|
+
// Touches outside the chat shouldn't scroll the background.
|
|
358
|
+
if (!inChat) {
|
|
359
|
+
if (e.cancelable)
|
|
360
|
+
e.preventDefault();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
// Inside the chat but no scrollable container — block to prevent body scroll.
|
|
364
|
+
if (!scrollEl) {
|
|
365
|
+
if (e.cancelable)
|
|
366
|
+
e.preventDefault();
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
// Inside a scrollable container — only block when at the edge in the
|
|
370
|
+
// swipe direction, so internal scrolling continues to work. Detect the
|
|
371
|
+
// dominant axis so horizontally-scrollable rows (e.g. the facets row)
|
|
372
|
+
// also get to handle their own touch gestures.
|
|
373
|
+
var currentX = (_b = (_a = e.touches[0]) === null || _a === void 0 ? void 0 : _a.clientX) !== null && _b !== void 0 ? _b : startX;
|
|
374
|
+
var currentY = (_d = (_c = e.touches[0]) === null || _c === void 0 ? void 0 : _c.clientY) !== null && _d !== void 0 ? _d : startY;
|
|
375
|
+
var deltaX = currentX - startX;
|
|
376
|
+
var deltaY = currentY - startY;
|
|
377
|
+
var horizontal = Math.abs(deltaX) > Math.abs(deltaY);
|
|
378
|
+
if (horizontal) {
|
|
379
|
+
var scrollsX = scrollEl.scrollWidth > scrollEl.clientWidth;
|
|
380
|
+
if (!scrollsX) {
|
|
381
|
+
if (e.cancelable)
|
|
382
|
+
e.preventDefault();
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
var atLeft = scrollEl.scrollLeft <= 0;
|
|
386
|
+
var atRight = scrollEl.scrollLeft + scrollEl.clientWidth >= scrollEl.scrollWidth - 1;
|
|
387
|
+
if ((atLeft && deltaX > 0) || (atRight && deltaX < 0)) {
|
|
388
|
+
if (e.cancelable)
|
|
389
|
+
e.preventDefault();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
var scrollsY = scrollEl.scrollHeight > scrollEl.clientHeight;
|
|
394
|
+
if (!scrollsY) {
|
|
395
|
+
if (e.cancelable)
|
|
396
|
+
e.preventDefault();
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
var atTop = scrollEl.scrollTop <= 0;
|
|
400
|
+
var atBottom = scrollEl.scrollTop + scrollEl.clientHeight >= scrollEl.scrollHeight - 1;
|
|
401
|
+
if ((atTop && deltaY > 0) || (atBottom && deltaY < 0)) {
|
|
402
|
+
if (e.cancelable)
|
|
403
|
+
e.preventDefault();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
document.addEventListener('touchstart', onTouchStart, { passive: true });
|
|
408
|
+
document.addEventListener('touchmove', onTouchMove, { passive: false });
|
|
409
|
+
return function () {
|
|
410
|
+
document.removeEventListener('touchstart', onTouchStart);
|
|
411
|
+
document.removeEventListener('touchmove', onTouchMove);
|
|
412
|
+
};
|
|
413
|
+
}, [store.open]);
|
|
284
414
|
var HistoryButton = function (props) { return ((0, jsx_runtime_1.jsx)(Button_1.Button, { className: "ss__chat__header__button--history", disabled: props.disabled, icon: {
|
|
285
415
|
icon: 'history',
|
|
286
416
|
title: 'Chat History',
|
|
@@ -288,7 +418,10 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
288
418
|
var HistoryPopup = function (props) { return ((0, jsx_runtime_1.jsxs)("div", { className: "ss__chat__history", children: [(0, jsx_runtime_1.jsxs)("div", { className: "ss__chat__history__header", children: [(0, jsx_runtime_1.jsx)("h4", { children: "History" }), (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__history__header__buttons", children: (0, jsx_runtime_1.jsx)(Button_1.Button, { content: "clear", onClick: function () {
|
|
289
419
|
controller.store.clearHistory();
|
|
290
420
|
props.toggleOpen && props.toggleOpen();
|
|
291
|
-
} }) })] }), store.chats.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "ss__chat__history__chats", children: store.chats
|
|
421
|
+
} }) })] }), store.chats.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "ss__chat__history__chats", children: store.chats
|
|
422
|
+
.slice()
|
|
423
|
+
.reverse()
|
|
424
|
+
.map(function (chat) { return ((0, jsx_runtime_1.jsx)("div", { className: "ss__chat__history__chats__chat", children: (0, jsx_runtime_1.jsxs)(Button_1.Button, { className: "ss__chat__history__chat__button", onClick: function () {
|
|
292
425
|
controller.store.switchChat(chat.id);
|
|
293
426
|
}, disabled: chat.id === store.currentChatId, children: [(0, jsx_runtime_1.jsx)("div", { className: "ss__chat__history__chat__button__text", children: (function () {
|
|
294
427
|
var lastUserMessage = __spreadArray([], chat.chat, true).reverse().find(function (message) { return message.messageType === 'user'; });
|
|
@@ -357,13 +490,26 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
357
490
|
boxShadow: '0px 3px 6px 0px rgba(0, 0, 0, 0.2)',
|
|
358
491
|
borderRadius: '6px',
|
|
359
492
|
},
|
|
360
|
-
}, children: (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__actions__facet__options", children: (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__actions__facet__slider", style: { padding: '12px 16px' }, children: (0, jsx_runtime_1.jsx)(__1.FacetSlider, { facet: props.facet
|
|
493
|
+
}, children: (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__actions__facet__options", children: (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__actions__facet__slider", style: { padding: '12px 16px' }, children: (0, jsx_runtime_1.jsx)(__1.FacetSlider, { facet: props.facet, onChange: function () {
|
|
494
|
+
if (!multiselectFacets) {
|
|
495
|
+
// FacetSlider fires onChange before its urlManager update; defer
|
|
496
|
+
// so controller.search() reads the updated filter state. Force
|
|
497
|
+
// productSearch with the current filters so a slider tweak doesn't
|
|
498
|
+
// fall through to `general` when hasPendingFacetChanges happens to
|
|
499
|
+
// be false (e.g. the slider returned to the seeded range).
|
|
500
|
+
queueMicrotask(function () {
|
|
501
|
+
return controller.search({
|
|
502
|
+
data: { requestType: 'productSearch', searchFilters: controller.store.searchFilters },
|
|
503
|
+
});
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
} }) }) }) }) }));
|
|
361
507
|
};
|
|
362
508
|
// TODO: if starting a new chat and it's expired, this button would then disappear
|
|
363
509
|
if (!controller.store.chatEnabled) {
|
|
364
510
|
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
|
|
365
511
|
}
|
|
366
|
-
var
|
|
512
|
+
var _4 = (0, useChatGestures_1.useChatGestures)({
|
|
367
513
|
panelRef: secondaryRef,
|
|
368
514
|
shouldShowSideChat: !!shouldShowSideChat,
|
|
369
515
|
activeMessageId: activeMessage === null || activeMessage === void 0 ? void 0 : activeMessage.id,
|
|
@@ -375,7 +521,7 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
375
521
|
setMobileProductInfoOpen(false);
|
|
376
522
|
(_b = store.currentChat) === null || _b === void 0 ? void 0 : _b.dismissSideChat();
|
|
377
523
|
},
|
|
378
|
-
}), swipeOffset =
|
|
524
|
+
}), swipeOffset = _4.swipeOffset, swipeAnimating = _4.swipeAnimating, swipeHandlers = _4.swipeHandlers;
|
|
379
525
|
var requestType = (_f = store.currentChat) === null || _f === void 0 ? void 0 : _f.requestType;
|
|
380
526
|
var loadingVerbs = (0, hooks_1.useMemo)(function () {
|
|
381
527
|
switch (requestType) {
|
|
@@ -396,11 +542,13 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
396
542
|
return undefined;
|
|
397
543
|
}
|
|
398
544
|
}, [requestType]);
|
|
545
|
+
var isWelcomeState = (!((_g = store.currentChat) === null || _g === void 0 ? void 0 : _g.chat) || store.currentChat.chat.length === 0) && !!store.welcomeMessage && !((_h = store.currentChat) === null || _h === void 0 ? void 0 : _h.isExpired);
|
|
399
546
|
return ((0, jsx_runtime_1.jsx)(providers_1.CacheProvider, { children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", __assign({ ref: chatRef, className: (0, classnames_1.default)('ss__chat', {
|
|
400
547
|
'ss__chat--open': store.open,
|
|
401
548
|
'ss__chat--minimized': !store.open,
|
|
402
549
|
'ss__chat--mobile': isMobile,
|
|
403
|
-
|
|
550
|
+
'ss__chat--welcome': isWelcomeState,
|
|
551
|
+
}, className, internalClassName) }, styling, { children: [!disableBubbleSuggestedQuestions && !store.open && !store.currentChat && ((_j = store.suggestedQuestions) === null || _j === void 0 ? void 0 : _j.length) > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "ss__chat__suggested-questions", children: store.suggestedQuestions.map(function (question, index) { return ((0, jsx_runtime_1.jsx)("div", { className: "ss__chat__suggested-questions__item", onClick: function () {
|
|
404
552
|
controller.openChat(question);
|
|
405
553
|
}, children: question }, index)); }) })), (0, jsx_runtime_1.jsx)("button", { type: "button", className: 'ss__chat__bubble', "aria-label": store.open ? 'Close chat' : 'Open chat', "aria-expanded": store.open, onClick: function () { return controller.handlers.button.click(); }, children: (0, jsx_runtime_1.jsx)(__1.Icon, { icon: "chat", title: "Open Chat" }) }), store.open && shouldShowSideChat && activeMessage ? ((0, jsx_runtime_1.jsxs)("div", { ref: secondaryRef, className: (0, classnames_1.default)('ss__chat__secondary'), role: "region", "aria-label": "Conversation details", style: isMobile
|
|
406
554
|
? {
|
|
@@ -414,7 +562,7 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
414
562
|
productQuery: 'Product Information',
|
|
415
563
|
}[activeMessage.messageType] || null }), (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__header__title__secondary", children: {
|
|
416
564
|
inspirationResult: 'Choose a style direction to explore',
|
|
417
|
-
productComparison: "Comparing ".concat(((
|
|
565
|
+
productComparison: "Comparing ".concat(((_k = activeMessage === null || activeMessage === void 0 ? void 0 : activeMessage.searchResults) === null || _k === void 0 ? void 0 : _k.length) || '', " products"),
|
|
418
566
|
productQuery: 'Complete product details',
|
|
419
567
|
}[activeMessage.messageType] || null })] }), (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__header__buttons", children: (0, jsx_runtime_1.jsx)(Button_1.Button, { className: "ss__chat__header__button--close", "aria-label": "Close chat", icon: { icon: 'close2', title: 'Close Chat' }, onClick: function () {
|
|
420
568
|
var _a, _b;
|
|
@@ -432,7 +580,7 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
432
580
|
} }) })] }), (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__content", children: (0, jsx_runtime_1.jsx)("div", { className: 'ss__chat__messages', children: {
|
|
433
581
|
inspirationResult: ((0, jsx_runtime_1.jsx)(ChatInspirationResultMessage_1.ChatInspirationResultMessage, __assign({}, subProps.inspirationResultMessage, { chatItem: activeMessage, controller: controller, onProductQuickView: isMobile ? function () { return setMobileProductInfoOpen(true); } : undefined }))),
|
|
434
582
|
productComparison: ((0, jsx_runtime_1.jsx)(ChatProductComparisonMessage_1.ChatProductComparisonMessage, __assign({}, subProps.productComparisonMessage, { chatItem: activeMessage, controller: controller }))),
|
|
435
|
-
productQuery: ((0, jsx_runtime_1.jsx)(ChatProductQueryMessage_1.ChatProductQueryMessage, __assign({}, subProps.productQueryMessage, { chatItem: activeMessage, controller: controller, displayFields: (
|
|
583
|
+
productQuery: ((0, jsx_runtime_1.jsx)(ChatProductQueryMessage_1.ChatProductQueryMessage, __assign({}, subProps.productQueryMessage, { chatItem: activeMessage, controller: controller, displayFields: (_m = (_l = controller.config.settings) === null || _l === void 0 ? void 0 : _l.quickview) === null || _m === void 0 ? void 0 : _m.displayFields, primaryColor: colorPrimary, primaryColorText: colorPrimaryText }))),
|
|
436
584
|
}[activeMessage.messageType] || null }) })] })) : null, store.open ? ((0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__primary', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__header', children: [(0, jsx_runtime_1.jsxs)("div", { className: "ss__chat__header__title", children: [logo ? (0, jsx_runtime_1.jsx)("img", { className: "ss__chat__header__title__logo", src: logo }) : null, (0, jsx_runtime_1.jsxs)("div", { className: "ss__chat__header__title__text", children: [title ? (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__header__title__text__primary", children: title }) : null, subtitle ? (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__header__title__text__secondary", children: subtitle }) : null] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "ss__chat__header__buttons", children: [(0, jsx_runtime_1.jsx)(Button_1.Button
|
|
437
585
|
// disabled={store.currentChat?.chat && store.currentChat.chat.length <= 1}
|
|
438
586
|
, {
|
|
@@ -455,7 +603,7 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
455
603
|
}, children: (0, jsx_runtime_1.jsx)(__1.Icon, { icon: "close-thin", size: "14px" }) }))] })) : null;
|
|
456
604
|
})(), (0, jsx_runtime_1.jsxs)("div", { className: "ss__chat__content", children: [(0, jsx_runtime_1.jsx)("div", { ref: headerRef, className: (0, classnames_1.default)('ss__chat__content__header', {
|
|
457
605
|
'ss__chat__content__header--overlay': messagesOverflow,
|
|
458
|
-
}), children: ((
|
|
606
|
+
}), children: ((_o = store.currentChat) === null || _o === void 0 ? void 0 : _o.comparisons.compared) && store.currentChat.comparisons.compared.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__content__header__comparisons', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__content__header__comparisons__header', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__content__header__comparisons__header__title', children: [(0, jsx_runtime_1.jsx)(__1.Icon, { className: 'ss__chat__content__header__comparisons__header__title__icon', icon: 'clipboard' }), (0, jsx_runtime_1.jsxs)("span", { className: 'ss__chat__content__header__comparisons__header__title__text', children: ["Compare Products (", (_p = store.currentChat) === null || _p === void 0 ? void 0 : _p.comparisons.compared.length, "/", (_q = store.currentChat) === null || _q === void 0 ? void 0 : _q.comparisons.maxItems, ")"] })] }), (0, jsx_runtime_1.jsx)("div", { className: 'ss__chat__content__header__comparisons__header__actions', children: (0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: function () { var _a; return (_a = store.currentChat) === null || _a === void 0 ? void 0 : _a.comparisons.reset(); }, children: "clear" }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__content__header__comparisons__content', children: [(0, jsx_runtime_1.jsx)("div", { className: 'ss__chat__content__header__comparisons__content__items', children: Array.from({ length: (_r = store.currentChat) === null || _r === void 0 ? void 0 : _r.comparisons.maxItems }).map(function (_, index) {
|
|
459
607
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
460
608
|
var comparisonItem = (_a = store.currentChat) === null || _a === void 0 ? void 0 : _a.comparisons.compared[index];
|
|
461
609
|
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('ss__chat__content__header__comparisons__content__comparison', {
|
|
@@ -475,8 +623,8 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
475
623
|
(_a = store.currentChat) === null || _a === void 0 ? void 0 : _a.comparisons.remove(comparisonItem.result.id);
|
|
476
624
|
}, children: (0, jsx_runtime_1.jsx)(__1.Icon, { icon: 'close-thin', size: '12px' }) })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(__1.Icon, { icon: 'plus-thin' }), (0, jsx_runtime_1.jsx)("div", { className: 'ss__chat__content__header__comparisons__content__comparison--placeholder__text', children: "Add" })] })) }, index));
|
|
477
625
|
}) }), (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('ss__chat__content__header__comparisons__action', {
|
|
478
|
-
'ss__chat__content__header__comparisons__action--hidden': (((
|
|
479
|
-
}), children: (0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: function () { return controller.search(); }, icon: { icon: 'compare', title: 'Compare' }, children: "Compare" }) })] })] })) }), (0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__messages', ref: messagesContainerRef, role: "log", "aria-live": "polite", "aria-relevant": "additions", "aria-label": "Chat messages", style: visibleChatLength ? { scrollbarGutter: 'stable' } : undefined, children: [(!((
|
|
626
|
+
'ss__chat__content__header__comparisons__action--hidden': (((_s = store.currentChat) === null || _s === void 0 ? void 0 : _s.comparisons.compared.length) || 0) < 2,
|
|
627
|
+
}), children: (0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: function () { return controller.search(); }, icon: { icon: 'compare', title: 'Compare' }, children: "Compare" }) })] })] })) }), (0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__messages', ref: messagesContainerRef, role: "log", "aria-live": "polite", "aria-relevant": "additions", "aria-label": "Chat messages", style: visibleChatLength ? { scrollbarGutter: 'stable' } : undefined, children: [(!((_t = store.currentChat) === null || _t === void 0 ? void 0 : _t.chat) || store.currentChat.chat.length === 0) && store.welcomeMessage && !((_u = store.currentChat) === null || _u === void 0 ? void 0 : _u.isExpired) && ((0, jsx_runtime_1.jsxs)("div", { className: "ss__chat__welcome", children: [(0, jsx_runtime_1.jsx)("div", { className: "ss__chat__welcome__message", children: store.welcomeMessage }), (0, jsx_runtime_1.jsx)(ChatSuggestedQuestions_1.ChatSuggestedQuestions, __assign({}, subProps.suggestedQuestions, { questions: store.suggestedQuestions, controller: controller }))] })), (_v = store.currentChat) === null || _v === void 0 ? void 0 : _v.chat.filter(function (chatItem) { return chatItem.messageType !== 'productQuery'; }).map(function (chatItem, index) { return ((0, jsx_runtime_1.jsx)("div", { className: "ss__chat__message ss__chat__message--".concat(chatItem.messageType), children: {
|
|
480
628
|
user: ((0, jsx_runtime_1.jsx)(ChatMessageUser_1.ChatMessageUser, __assign({}, subProps.messageUser, { chatItem: chatItem, controller: controller, onProductQuickView: isMobile ? function () { return setMobileProductInfoOpen(true); } : undefined, primaryColor: colorPrimary, primaryColorText: colorPrimaryText }))),
|
|
481
629
|
text: ((0, jsx_runtime_1.jsx)(ChatMessageText_1.ChatMessageText, __assign({}, subProps.messageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onProductQuickView: isMobile ? function () { return setMobileProductInfoOpen(true); } : undefined, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText }))),
|
|
482
630
|
content: ((0, jsx_runtime_1.jsx)(ChatMessageText_1.ChatMessageText, __assign({}, subProps.messageText, { chatItem: chatItem, controller: controller, scrollToBottom: scrollToBottomIfNear, onProductQuickView: isMobile ? function () { return setMobileProductInfoOpen(true); } : undefined, sideChatOpen: !!shouldShowSideChat, primaryColor: colorPrimary, primaryColorText: colorPrimaryText }))),
|
|
@@ -500,11 +648,11 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
500
648
|
}[chatItem.messageType] || null }, index)); }), (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__messages__end", ref: messagesEndRef }), showNewMessages && messagesOverflow && ((0, jsx_runtime_1.jsxs)("div", { className: "ss__chat__new-messages", onClick: function () {
|
|
501
649
|
scrollToBottom();
|
|
502
650
|
setShowNewMessages(false);
|
|
503
|
-
}, children: [(0, jsx_runtime_1.jsx)(__1.Icon, { icon: "angle-down", size: "12px" }), (0, jsx_runtime_1.jsx)("span", { children: "New messages" })] }))] }), (0, jsx_runtime_1.jsx)(ChatLoadingIndicator_1.ChatLoadingIndicator, __assign({}, subProps.loadingIndicator, { loading: store.loading, verbs: loadingVerbs })), !((
|
|
651
|
+
}, children: [(0, jsx_runtime_1.jsx)(__1.Icon, { icon: "angle-down", size: "12px" }), (0, jsx_runtime_1.jsx)("span", { children: "New messages" })] }))] }), (0, jsx_runtime_1.jsx)(ChatLoadingIndicator_1.ChatLoadingIndicator, __assign({}, subProps.loadingIndicator, { loading: store.loading, verbs: loadingVerbs })), !((_w = store.currentChat) === null || _w === void 0 ? void 0 : _w.isExpired) ? ((0, jsx_runtime_1.jsxs)("div", __assign({ className: "ss__chat__content__footer", ref: footerRef }, dragHandlers, { children: [store.error && (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__error", children: store.error.message }), ((_x = store.currentChat) === null || _x === void 0 ? void 0 : _x.sessionLimitReached) && ((0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__topic-drift', children: [(0, jsx_runtime_1.jsx)(__1.Icon, { icon: "info", size: "18px", className: 'ss__chat__topic-drift__icon--info' }), (0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__topic-drift__text', children: [(0, jsx_runtime_1.jsx)("span", { children: "Session limit reached" }), (0, jsx_runtime_1.jsx)("span", { children: "This chat has reached its maximum number of interactions. Start a new session to continue." })] }), (0, jsx_runtime_1.jsx)(Button_1.Button, { className: 'ss__chat__topic-drift__button', onClick: function () {
|
|
504
652
|
controller.store.createChat();
|
|
505
653
|
}, children: "New Session" })] })), store.facets && store.facets.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: 'ss__chat__actions', children: (0, jsx_runtime_1.jsxs)("div", { className: "ss__chat__actions__wrap", children: [(0, jsx_runtime_1.jsxs)("div", { className: "ss__chat__actions__facets-header", children: [(0, jsx_runtime_1.jsx)("div", { className: "ss__chat__actions--title", children: "Filter by:" }), multiselectFacets && store.hasPendingFacetChanges && ((0, jsx_runtime_1.jsx)("div", { className: 'ss__chat__actions__facets-apply ss__chat__actions__facets-apply--active', children: (0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: function () {
|
|
506
654
|
controller.search();
|
|
507
|
-
}, children: "Apply" }) }))] }), (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__actions--facets", children: store.facets.slice(0, 10).map(function (facet, idx) {
|
|
655
|
+
}, children: store.pendingFacetCount > 0 ? "Apply (".concat(store.pendingFacetCount, ")") : 'Clear facets' }) }))] }), (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__actions--facets", children: store.facets.slice(0, 10).map(function (facet, idx) {
|
|
508
656
|
var _a;
|
|
509
657
|
// range/slider facets render via FacetSlider; everything else needs at least one value to be useful
|
|
510
658
|
if (facet.type !== 'range' && !((_a = facet.values) === null || _a === void 0 ? void 0 : _a.length))
|
|
@@ -512,7 +660,7 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
512
660
|
if (facet.type === 'range') {
|
|
513
661
|
return (0, jsx_runtime_1.jsx)(SliderFacetDropdown, { facet: facet, label: getFacetButtonLabel(facet) }, idx);
|
|
514
662
|
}
|
|
515
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: "ss__chat__actions__facet ss__chat__actions__facet--".concat(facet.type), children: (0, jsx_runtime_1.jsx)(__1.Dropdown, { usePortal: true, dropUp: true, button: (0, jsx_runtime_1.jsx)(FacetButton, { label: getFacetButtonLabel(facet) }), style: {
|
|
663
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "ss__chat__actions__facet ss__chat__actions__facet--".concat(facet.type), children: (0, jsx_runtime_1.jsx)(__1.Dropdown, { usePortal: true, dropUp: true, boundaryRef: chatRef, button: (0, jsx_runtime_1.jsx)(FacetButton, { label: getFacetButtonLabel(facet) }), style: {
|
|
516
664
|
'.ss__dropdown__content': __assign({ width: '150px', maxHeight: '200px', overflowY: 'auto', background: 'white', boxShadow: '0px 3px 6px 0px rgba(0, 0, 0, 0.2)', borderRadius: '6px' }, (multiselectFacets
|
|
517
665
|
? {
|
|
518
666
|
'.ss__chat__actions__facet__option--checkbox': {
|
|
@@ -569,6 +717,9 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
569
717
|
'&:hover': {
|
|
570
718
|
background: new utilities_1.Colour(colorPrimary).lightenHex(0.95),
|
|
571
719
|
},
|
|
720
|
+
'&.ss__chat__actions__facet__option--selected': {
|
|
721
|
+
fontWeight: 'bold',
|
|
722
|
+
},
|
|
572
723
|
},
|
|
573
724
|
})),
|
|
574
725
|
}, children: (0, jsx_runtime_1.jsx)("div", { className: "ss__chat__actions__facet__options", children: facet.type === 'range-buckets'
|
|
@@ -592,12 +743,28 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
592
743
|
'ss__chat__actions__facet__option__checkbox--checked': isSelected_1,
|
|
593
744
|
}), children: isSelected_1 && (0, jsx_runtime_1.jsx)(__1.Icon, { icon: "check-thin", size: "10px" }) }), (0, jsx_runtime_1.jsx)("span", { className: "ss__chat__actions__facet__option__label", children: rangeOption.label })] }, optionValue));
|
|
594
745
|
}
|
|
595
|
-
return ((0, jsx_runtime_1.jsx)(Button_1.Button, {
|
|
596
|
-
controller.store.
|
|
597
|
-
|
|
598
|
-
|
|
746
|
+
return ((0, jsx_runtime_1.jsx)(Button_1.Button, { className: (0, classnames_1.default)({
|
|
747
|
+
'ss__chat__actions__facet__option--selected': controller.store.isFacetSelected(facet.field, optionValue),
|
|
748
|
+
}), onClick: function () {
|
|
749
|
+
// Non-multiselect: clicking an already-selected value toggles it off.
|
|
750
|
+
// `addFacet` is idempotent against an existing urlManager value, so without
|
|
751
|
+
// the toggle the state wouldn't change, `hasPendingFacetChanges` would stay
|
|
752
|
+
// false, and the params getter would fall through to `general`.
|
|
753
|
+
if (controller.store.isFacetSelected(facet.field, optionValue)) {
|
|
754
|
+
controller.store.removeFacet(facet.field, optionValue);
|
|
755
|
+
}
|
|
756
|
+
else {
|
|
757
|
+
controller.store.addFacet({
|
|
758
|
+
key: facet.field,
|
|
759
|
+
value: optionValue,
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
// Force productSearch with the current filter state rather than relying
|
|
763
|
+
// on the params getter's hasPendingFacetChanges promotion — a facet click
|
|
764
|
+
// in the chat is unambiguously a search intent.
|
|
765
|
+
controller.search({
|
|
766
|
+
data: { requestType: 'productSearch', searchFilters: controller.store.searchFilters },
|
|
599
767
|
});
|
|
600
|
-
controller.search();
|
|
601
768
|
}, children: rangeOption.label }, optionValue));
|
|
602
769
|
})
|
|
603
770
|
: facet.values.map(function (option) {
|
|
@@ -619,12 +786,28 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
619
786
|
'ss__chat__actions__facet__option__checkbox--checked': isSelected_2,
|
|
620
787
|
}), children: isSelected_2 && (0, jsx_runtime_1.jsx)(__1.Icon, { icon: "check-thin", size: "10px" }) }), (0, jsx_runtime_1.jsx)("span", { className: "ss__chat__actions__facet__option__label", children: valueOption.label })] }, optionValue));
|
|
621
788
|
}
|
|
622
|
-
return ((0, jsx_runtime_1.jsx)(Button_1.Button, {
|
|
623
|
-
controller.store.
|
|
624
|
-
|
|
625
|
-
|
|
789
|
+
return ((0, jsx_runtime_1.jsx)(Button_1.Button, { className: (0, classnames_1.default)({
|
|
790
|
+
'ss__chat__actions__facet__option--selected': controller.store.isFacetSelected(facet.field, optionValue),
|
|
791
|
+
}), onClick: function () {
|
|
792
|
+
// Non-multiselect: clicking an already-selected value toggles it off.
|
|
793
|
+
// `addFacet` is idempotent against an existing urlManager value, so without
|
|
794
|
+
// the toggle the state wouldn't change, `hasPendingFacetChanges` would stay
|
|
795
|
+
// false, and the params getter would fall through to `general`.
|
|
796
|
+
if (controller.store.isFacetSelected(facet.field, optionValue)) {
|
|
797
|
+
controller.store.removeFacet(facet.field, optionValue);
|
|
798
|
+
}
|
|
799
|
+
else {
|
|
800
|
+
controller.store.addFacet({
|
|
801
|
+
key: facet.field,
|
|
802
|
+
value: optionValue,
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
// Force productSearch with the current filter state rather than relying
|
|
806
|
+
// on the params getter's hasPendingFacetChanges promotion — a facet click
|
|
807
|
+
// in the chat is unambiguously a search intent.
|
|
808
|
+
controller.search({
|
|
809
|
+
data: { requestType: 'productSearch', searchFilters: controller.store.searchFilters },
|
|
626
810
|
});
|
|
627
|
-
controller.search();
|
|
628
811
|
}, children: valueOption.label }, optionValue));
|
|
629
812
|
}) }) }, facet.field) }, idx));
|
|
630
813
|
}) })] }) })), (function () {
|
|
@@ -653,12 +836,11 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
653
836
|
id: result === null || result === void 0 ? void 0 : result.id,
|
|
654
837
|
name: ((_b = (_a = d === null || d === void 0 ? void 0 : d.mappings) === null || _a === void 0 ? void 0 : _a.core) === null || _b === void 0 ? void 0 : _b.name) || '',
|
|
655
838
|
imageUrl: ((_d = (_c = d === null || d === void 0 ? void 0 : d.mappings) === null || _c === void 0 ? void 0 : _c.core) === null || _d === void 0 ? void 0 : _d.thumbnailImageUrl) || ((_f = (_e = d === null || d === void 0 ? void 0 : d.mappings) === null || _e === void 0 ? void 0 : _e.core) === null || _f === void 0 ? void 0 : _f.imageUrl) || ((_h = (_g = d === null || d === void 0 ? void 0 : d.mappings) === null || _g === void 0 ? void 0 : _g.core) === null || _h === void 0 ? void 0 : _h.parentImageUrl) || '',
|
|
656
|
-
onClick:
|
|
657
|
-
|
|
658
|
-
|
|
839
|
+
onClick: function () {
|
|
840
|
+
controller.productQuickView(result);
|
|
841
|
+
if (isMobile)
|
|
659
842
|
setMobileProductInfoOpen(true);
|
|
660
|
-
|
|
661
|
-
: undefined,
|
|
843
|
+
},
|
|
662
844
|
};
|
|
663
845
|
})
|
|
664
846
|
: showCommittedComparisons
|
|
@@ -669,34 +851,29 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
669
851
|
id: (_b = comparisonItem.result) === null || _b === void 0 ? void 0 : _b.id,
|
|
670
852
|
name: ((_d = (_c = d === null || d === void 0 ? void 0 : d.mappings) === null || _c === void 0 ? void 0 : _c.core) === null || _d === void 0 ? void 0 : _d.name) || '',
|
|
671
853
|
imageUrl: ((_f = (_e = d === null || d === void 0 ? void 0 : d.mappings) === null || _e === void 0 ? void 0 : _e.core) === null || _f === void 0 ? void 0 : _f.thumbnailImageUrl) || ((_h = (_g = d === null || d === void 0 ? void 0 : d.mappings) === null || _g === void 0 ? void 0 : _g.core) === null || _h === void 0 ? void 0 : _h.imageUrl) || ((_k = (_j = d === null || d === void 0 ? void 0 : d.mappings) === null || _j === void 0 ? void 0 : _j.core) === null || _k === void 0 ? void 0 : _k.parentImageUrl) || '',
|
|
672
|
-
onClick:
|
|
673
|
-
|
|
674
|
-
|
|
854
|
+
onClick: function () {
|
|
855
|
+
controller.productQuickView(comparisonItem.result);
|
|
856
|
+
if (isMobile)
|
|
675
857
|
setMobileProductInfoOpen(true);
|
|
676
|
-
|
|
677
|
-
: undefined,
|
|
858
|
+
},
|
|
678
859
|
};
|
|
679
860
|
})
|
|
680
861
|
: [];
|
|
681
|
-
var productItems = productAttachments.map(function (item) {
|
|
682
|
-
|
|
683
|
-
name: item.name || '',
|
|
684
|
-
imageUrl: item.thumbnailUrl || '',
|
|
685
|
-
onClick: isMobile
|
|
686
|
-
? function () {
|
|
687
|
-
setMobileProductInfoOpen(true);
|
|
688
|
-
}
|
|
689
|
-
: function () {
|
|
690
|
-
var _a, _b, _c;
|
|
691
|
-
(_a = store.currentChat) === null || _a === void 0 ? void 0 : _a.setActiveMessage(((_c = (_b = store.currentChat) === null || _b === void 0 ? void 0 : _b.activeMessage) === null || _c === void 0 ? void 0 : _c.id) || '');
|
|
692
|
-
},
|
|
693
|
-
onRemove: function () {
|
|
862
|
+
var productItems = productAttachments.map(function (item) {
|
|
863
|
+
var remove = function () {
|
|
694
864
|
var _a, _b;
|
|
695
865
|
(_a = store.currentChat) === null || _a === void 0 ? void 0 : _a.attachments.remove(item.id);
|
|
696
866
|
setMobileProductInfoOpen(false);
|
|
697
867
|
(_b = store.currentChat) === null || _b === void 0 ? void 0 : _b.dismissSideChat();
|
|
698
|
-
}
|
|
699
|
-
|
|
868
|
+
};
|
|
869
|
+
return {
|
|
870
|
+
id: item.id,
|
|
871
|
+
name: item.name || '',
|
|
872
|
+
imageUrl: item.thumbnailUrl || '',
|
|
873
|
+
onClick: remove,
|
|
874
|
+
onRemove: remove,
|
|
875
|
+
};
|
|
876
|
+
});
|
|
700
877
|
var imageItems = imageAttachments.map(function (item) {
|
|
701
878
|
var _a;
|
|
702
879
|
return ({
|
|
@@ -709,7 +886,7 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
709
886
|
onRemove: function () { var _a; return (_a = store.currentChat) === null || _a === void 0 ? void 0 : _a.attachments.remove(item.id); },
|
|
710
887
|
});
|
|
711
888
|
});
|
|
712
|
-
var productTitle = productItems.length > 1 ? 'Compare these products' : 'Ask about this product'
|
|
889
|
+
var productTitle = productItems.length > 1 ? 'Compare these products' : 'Ask about this product';
|
|
713
890
|
var hasImageError = imageItems.some(function (item) { return item.hasError; });
|
|
714
891
|
var imageTitle = imageItems.length > 0 && !hasImageError ? 'Find products similar to this image:' : '';
|
|
715
892
|
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [comparisonItems.length > 0 && ((0, jsx_runtime_1.jsx)(ChatAttachmentContext_1.ChatAttachmentContext, __assign({}, subProps.attachmentContext, { title: 'Compare these products', items: comparisonItems, onClose: function () {
|
|
@@ -738,21 +915,44 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
738
915
|
: 'Start a fresh session for better assistance, or keep going in this one?';
|
|
739
916
|
var buttonText = isScopeRedirect ? '' : 'New Session';
|
|
740
917
|
return ((0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__topic-drift', children: [(0, jsx_runtime_1.jsx)(__1.Icon, { icon: "info", size: "18px", className: 'ss__chat__topic-drift__icon--info' }), (0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__topic-drift__text', children: [(0, jsx_runtime_1.jsx)("span", { children: primaryText }), (0, jsx_runtime_1.jsx)("span", { children: secondaryText })] }), buttonText && ((0, jsx_runtime_1.jsx)(Button_1.Button, { className: 'ss__chat__topic-drift__button', onClick: function () {
|
|
741
|
-
var _a, _b;
|
|
918
|
+
var _a, _b, _c;
|
|
742
919
|
if (isScopeRedirect) {
|
|
743
920
|
(_a = store.currentChat) === null || _a === void 0 ? void 0 : _a.dismissTopicDrift();
|
|
744
921
|
return;
|
|
745
922
|
}
|
|
746
|
-
|
|
923
|
+
// Capture image attachments from the current chat before handleTopicDrift /
|
|
924
|
+
// createChat tear down the conversation — an imageSearch that drifted needs
|
|
925
|
+
// the same image attached to the carried-over message in the new session,
|
|
926
|
+
// otherwise params would fall back to a `general` request without the image.
|
|
927
|
+
var previousImageAttachments = (((_b = store.currentChat) === null || _b === void 0 ? void 0 : _b.attachments.attached) || [])
|
|
928
|
+
.filter(function (item) { return item.type === 'image' && item.state !== 'error'; })
|
|
929
|
+
.map(function (item) {
|
|
930
|
+
var img = item;
|
|
931
|
+
return {
|
|
932
|
+
type: 'image',
|
|
933
|
+
base64: img.base64,
|
|
934
|
+
fileName: img.fileName,
|
|
935
|
+
imageId: img.imageId,
|
|
936
|
+
imageUrl: img.imageUrl,
|
|
937
|
+
thumbnailUrl: img.thumbnailUrl,
|
|
938
|
+
// Already uploaded — skip the 'loading' default state.
|
|
939
|
+
state: 'attached',
|
|
940
|
+
};
|
|
941
|
+
});
|
|
942
|
+
var messageText = (_c = store.currentChat) === null || _c === void 0 ? void 0 : _c.handleTopicDrift();
|
|
747
943
|
if (messageText) {
|
|
748
944
|
controller.store.createChat();
|
|
945
|
+
previousImageAttachments.forEach(function (cfg) {
|
|
946
|
+
var _a;
|
|
947
|
+
(_a = controller.store.currentChat) === null || _a === void 0 ? void 0 : _a.attachments.add(cfg);
|
|
948
|
+
});
|
|
749
949
|
controller.search({ data: { message: messageText } });
|
|
750
950
|
}
|
|
751
951
|
}, children: buttonText })), (0, jsx_runtime_1.jsx)("span", { onClick: function () {
|
|
752
952
|
var _a;
|
|
753
953
|
(_a = store.currentChat) === null || _a === void 0 ? void 0 : _a.dismissTopicDrift();
|
|
754
954
|
}, children: (0, jsx_runtime_1.jsx)(__1.Icon, { icon: "close-thin", size: "14px", className: 'ss__chat__topic-drift__icon--close' }) })] }));
|
|
755
|
-
})(), (0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__input', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__input__input', children: [(0, jsx_runtime_1.jsx)("input", { type: "text", name: "ss-chat-input", disabled: store.loading || store.blocked || ((
|
|
955
|
+
})(), (0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__input', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'ss__chat__input__input', children: [(0, jsx_runtime_1.jsx)("input", { type: "text", name: "ss-chat-input", disabled: store.loading || store.blocked || ((_y = store.currentChat) === null || _y === void 0 ? void 0 : _y.sessionLimitReached), placeholder: (function () {
|
|
756
956
|
var _a, _b, _c;
|
|
757
957
|
var comparedCount = ((_a = store.currentChat) === null || _a === void 0 ? void 0 : _a.comparisons.compared.length) || 0;
|
|
758
958
|
var committedCount = ((_b = store.currentChat) === null || _b === void 0 ? void 0 : _b.comparisons.committed.length) || 0;
|
|
@@ -780,7 +980,7 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
780
980
|
if (e.keyCode === 13 && isMobile && mobileProductInfoOpen) {
|
|
781
981
|
setMobileProductInfoOpen(false);
|
|
782
982
|
}
|
|
783
|
-
}, value: controller.store.inputValue }), store.features.imageSearch.enabled && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { className: 'ss__chat__upload-button', disabled: store.loading || store.blocked || ((
|
|
983
|
+
}, value: controller.store.inputValue }), store.features.imageSearch.enabled && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { className: 'ss__chat__upload-button', disabled: store.loading || store.blocked || ((_z = store.currentChat) === null || _z === void 0 ? void 0 : _z.sessionLimitReached), onClick: function () { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, icon: { icon: 'image', title: 'Upload Image' } }), (0, jsx_runtime_1.jsx)("input", { ref: fileInputRef, onChange: function (e) { return __awaiter(void 0, void 0, void 0, function () {
|
|
784
984
|
return __generator(this, function (_a) {
|
|
785
985
|
switch (_a.label) {
|
|
786
986
|
case 0: return [4 /*yield*/, controller.upload(e.target.files)];
|
|
@@ -791,7 +991,7 @@ exports.ChatOrganism = (0, mobx_react_lite_1.observer)(function (properties) {
|
|
|
791
991
|
return [2 /*return*/];
|
|
792
992
|
}
|
|
793
993
|
});
|
|
794
|
-
}); },
|
|
994
|
+
}); }, type: "file", accept: "image/*", className: "ss__chat__input__input__file" })] }))] }), (0, jsx_runtime_1.jsx)("div", { className: 'ss__chat__input__actions', children: (function () {
|
|
795
995
|
var _a, _b;
|
|
796
996
|
var hasImageAttachment = (((_a = store.currentChat) === null || _a === void 0 ? void 0 : _a.attachments.attached) || []).some(function (item) { return item.type === 'image' && !item.error; });
|
|
797
997
|
var messageEmpty = !controller.store.inputValue.trim();
|