@constructor-io/constructorio-ui-pia 2.8.0 → 2.10.0

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 (40) hide show
  1. package/dist/constructorio-ui-pia-bundled.js +75 -72
  2. package/lib/cjs/components/CioPia/CioPia.js +29 -5
  3. package/lib/cjs/components/CioPia/PiaCustomCarousel.js +42 -9
  4. package/lib/cjs/components/ConversationHistory/ConversationHistory.js +3 -3
  5. package/lib/cjs/components/PiaConversation/PiaConversation.js +2 -2
  6. package/lib/cjs/components/PiaInlineAnswer/PiaInlineAnswer.js +3 -3
  7. package/lib/cjs/constants.js +2 -1
  8. package/lib/cjs/hooks/useCioClient.js +2 -2
  9. package/lib/cjs/hooks/useCioPia.js +12 -3
  10. package/lib/cjs/hooks/useConversation.js +32 -9
  11. package/lib/cjs/hooks/useTracking.js +71 -0
  12. package/lib/cjs/hooks/useViewportTracking.js +92 -0
  13. package/lib/cjs/version.js +1 -1
  14. package/lib/mjs/components/CioPia/CioPia.js +28 -5
  15. package/lib/mjs/components/CioPia/PiaCustomCarousel.js +54 -20
  16. package/lib/mjs/components/ConversationHistory/ConversationHistory.js +3 -3
  17. package/lib/mjs/components/PiaConversation/PiaConversation.js +2 -2
  18. package/lib/mjs/components/PiaInlineAnswer/PiaInlineAnswer.js +3 -3
  19. package/lib/mjs/constants.js +1 -0
  20. package/lib/mjs/hooks/useCioClient.js +2 -2
  21. package/lib/mjs/hooks/useCioPia.js +13 -4
  22. package/lib/mjs/hooks/useConversation.js +24 -2
  23. package/lib/mjs/hooks/useTracking.js +107 -0
  24. package/lib/mjs/hooks/useViewportTracking.js +89 -0
  25. package/lib/mjs/version.js +1 -1
  26. package/lib/types/components/CioPia/CioPia.d.ts +5 -1
  27. package/lib/types/components/CioPia/PiaCustomCarousel.d.ts +5 -1
  28. package/lib/types/components/ConversationHistory/ConversationHistory.d.ts +6 -2
  29. package/lib/types/components/PiaConversation/PiaConversation.d.ts +5 -2
  30. package/lib/types/components/PiaInlineAnswer/PiaInlineAnswer.d.ts +7 -2
  31. package/lib/types/constants.d.ts +1 -0
  32. package/lib/types/hooks/useCioClient.d.ts +3 -7
  33. package/lib/types/hooks/useCioPia.d.ts +4 -0
  34. package/lib/types/hooks/useConversation.d.ts +5 -2
  35. package/lib/types/hooks/useTracking.d.ts +27 -0
  36. package/lib/types/hooks/useViewportTracking.d.ts +10 -0
  37. package/lib/types/types.d.ts +8 -0
  38. package/lib/types/utils/transformers.d.ts +1 -1
  39. package/lib/types/version.d.ts +1 -1
  40. package/package.json +6 -3
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
- const react_1 = tslib_1.__importDefault(require("react"));
4
+ const react_1 = tslib_1.__importStar(require("react"));
5
5
  const constructorio_ui_components_1 = require("@constructor-io/constructorio-ui-components");
6
6
  const Input_1 = tslib_1.__importDefault(require("../Input/Input"));
7
7
  const SuggestedQuestionsContainer_1 = tslib_1.__importDefault(require("../SuggestedQuestionsContainer/SuggestedQuestionsContainer"));
8
8
  const useCioPia_1 = tslib_1.__importDefault(require("../../hooks/useCioPia"));
9
9
  const useConversation_1 = tslib_1.__importDefault(require("../../hooks/useConversation"));
10
+ const useTracking_1 = tslib_1.__importDefault(require("../../hooks/useTracking"));
11
+ const useViewportTracking_1 = tslib_1.__importDefault(require("../../hooks/useViewportTracking"));
10
12
  const useViewportCallbacks_1 = tslib_1.__importDefault(require("../../hooks/useViewportCallbacks"));
11
13
  const ErrorBlock_1 = tslib_1.__importDefault(require("../Error/ErrorBlock"));
12
14
  const LoadingSkeleton_1 = tslib_1.__importDefault(require("../LoadingSkeleton/LoadingSkeleton"));
@@ -16,9 +18,11 @@ const PiaModal_1 = tslib_1.__importDefault(require("../PiaConversation/PiaModal"
16
18
  const PiaConversation_1 = tslib_1.__importDefault(require("../PiaConversation/PiaConversation"));
17
19
  // eslint-disable-next-line complexity
18
20
  function CioPia(props) {
19
- const { apiKey, itemId, threadId, variationId, cioClient, displayConfigs, componentOverrides, callbacks, formatters, children, translations, suggestedQuestionsParameters, } = props;
21
+ var _a;
22
+ const { apiKey, itemId, itemName, threadId, variationId, cioClient, displayConfigs, componentOverrides, callbacks, formatters, productCardProps, children, translations, suggestedQuestionsParameters, } = props;
20
23
  const { learnMoreUrl, showFeedback, mode = 'default', type = 'inline', showPreviousItems, disclaimerPosition = 'bottom', } = displayConfigs || {};
21
24
  const isConversation = mode === 'conversation' || type === 'modal';
25
+ const { priceCurrency } = productCardProps || {};
22
26
  const pia = (0, useCioPia_1.default)({
23
27
  apiKey,
24
28
  itemId,
@@ -28,8 +32,24 @@ function CioPia(props) {
28
32
  suggestedQuestionsParameters,
29
33
  formatImageUrl: formatters === null || formatters === void 0 ? void 0 : formatters.formatImageUrl,
30
34
  });
31
- const { currentQuestion, displayedQuestions, conversationHistory, currentAnswer, currentItems, isLoading, error, context, handleSubmitQuestion, handleQuestionClick, handleInputFocus, resetState, } = (0, useConversation_1.default)({ pia, itemId, isConversation, callbacks });
32
- const { containerRef } = (0, useViewportCallbacks_1.default)({ callbacks, context });
35
+ const tracking = (0, useTracking_1.default)({
36
+ cioClient: pia.cioClient,
37
+ itemId,
38
+ itemName,
39
+ variationId,
40
+ threadId: pia.threadId,
41
+ });
42
+ const { currentQuestion, displayedQuestions, conversationHistory, currentAnswer, currentItems, isLoading, error, context, handleSubmitQuestion, handleQuestionClick, handleInputFocus, handleFeedback, resetState, } = (0, useConversation_1.default)({ pia, itemId, isConversation, callbacks, tracking });
43
+ const { containerRef: viewportContainerRef } = (0, useViewportTracking_1.default)({
44
+ tracking,
45
+ questions: displayedQuestions,
46
+ });
47
+ const { containerRef: callbackContainerRef } = (0, useViewportCallbacks_1.default)({ callbacks, context });
48
+ const containerRef = (0, react_1.useCallback)((node) => {
49
+ viewportContainerRef(node);
50
+ callbackContainerRef(node);
51
+ }, [viewportContainerRef, callbackContainerRef]);
52
+ const qnaResultId = (_a = pia.answers.data) === null || _a === void 0 ? void 0 : _a.qna_result_id;
33
53
  const renderProps = {
34
54
  items: currentItems,
35
55
  isLoading,
@@ -55,8 +75,12 @@ function CioPia(props) {
55
75
  displayedQuestions,
56
76
  handleSubmitQuestion,
57
77
  handleQuestionClick,
78
+ handleFeedback,
79
+ onResultClick: tracking.trackResultClick,
80
+ qnaResultId,
58
81
  containerRef,
59
82
  onInputFocus: handleInputFocus,
83
+ priceCurrency,
60
84
  };
61
85
  if (type === 'modal') {
62
86
  return (react_1.default.createElement(PiaModal_1.default, { initialQuestions: pia.suggestedQuestions.data, handleSubmitQuestion: handleSubmitQuestion, handleQuestionClick: handleQuestionClick, containerRef: containerRef, isLoading: isLoading, componentOverrides: componentOverrides, translations: translations, onInputFocus: handleInputFocus, onClose: resetState },
@@ -72,7 +96,7 @@ function CioPia(props) {
72
96
  isLoading && react_1.default.createElement(LoadingSkeleton_1.default, { componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.loading }),
73
97
  !isLoading && error && react_1.default.createElement(ErrorBlock_1.default, { message: (error === null || error === void 0 ? void 0 : error.message) || 'Unexpected error' }),
74
98
  !isLoading && !error && (react_1.default.createElement(react_1.default.Fragment, null,
75
- currentAnswer && (react_1.default.createElement(PiaInlineAnswer_1.default, { currentAnswer: currentAnswer, currentItems: currentItems, showFeedback: showFeedback, learnMoreUrl: learnMoreUrl, disclaimerPosition: disclaimerPosition, translations: translations, callbacks: callbacks, componentOverrides: componentOverrides })),
99
+ currentAnswer && (react_1.default.createElement(PiaInlineAnswer_1.default, { currentAnswer: currentAnswer, currentItems: currentItems, showFeedback: showFeedback, learnMoreUrl: learnMoreUrl, disclaimerPosition: disclaimerPosition, translations: translations, callbacks: callbacks, componentOverrides: componentOverrides, onFeedback: handleFeedback, onResultClick: tracking.trackResultClick, question: currentQuestion, qnaResultId: qnaResultId, priceCurrency: priceCurrency })),
76
100
  react_1.default.createElement(SuggestedQuestionsContainer_1.default, { questions: displayedQuestions, onQuestionClick: handleQuestionClick, componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.suggestedQuestions }))))));
77
101
  }
78
102
  exports.default = CioPia;
@@ -10,10 +10,48 @@ function HtmlDescription({ product }) {
10
10
  return null;
11
11
  return (react_1.default.createElement("p", { className: 'cio-product-card-description', dangerouslySetInnerHTML: { __html: (0, contentTransformers_1.sanitizeHtml)(description) } }));
12
12
  }
13
- function PiaCustomCarousel({ items, componentOverrides, callbacks, }) {
13
+ function createPriceSectionOverride(priceCurrency) {
14
+ return function PriceSectionOverride({ product }) {
15
+ const { price, salePrice } = product;
16
+ if (price == null)
17
+ return null;
18
+ return (react_1.default.createElement("div", { className: 'cio-product-card-price-section flex items-baseline gap-2' },
19
+ react_1.default.createElement("span", { className: 'text-lg font-bold' },
20
+ priceCurrency,
21
+ "\u00A0", salePrice !== null && salePrice !== void 0 ? salePrice : price),
22
+ salePrice != null && (react_1.default.createElement("span", { className: 'text-sm text-gray-400 line-through' },
23
+ priceCurrency,
24
+ "\u00A0",
25
+ price))));
26
+ };
27
+ }
28
+ function getContentDefaults(content, priceSectionOverride) {
29
+ const defaults = {};
30
+ if (!(content === null || content === void 0 ? void 0 : content.description)) {
31
+ defaults.description = { reactNode: HtmlDescription };
32
+ }
33
+ if (!(content === null || content === void 0 ? void 0 : content.price) && priceSectionOverride) {
34
+ defaults.price = { reactNode: priceSectionOverride };
35
+ }
36
+ return defaults;
37
+ }
38
+ function buildMergedOverrides(componentOverrides, priceSectionOverride) {
39
+ var _a, _b, _c;
40
+ const content = (_b = (_a = componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.item) === null || _a === void 0 ? void 0 : _a.productCard) === null || _b === void 0 ? void 0 : _b.content;
41
+ const defaults = getContentDefaults(content, priceSectionOverride);
42
+ if (Object.keys(defaults).length === 0) {
43
+ return componentOverrides || {};
44
+ }
45
+ return Object.assign(Object.assign({}, componentOverrides), { item: Object.assign(Object.assign({}, componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.item), { productCard: Object.assign(Object.assign({}, (_c = componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.item) === null || _c === void 0 ? void 0 : _c.productCard), { content: Object.assign(Object.assign({}, content), defaults) }) }) });
46
+ }
47
+ function PiaCustomCarousel({ items, componentOverrides, callbacks, onResultClick, question, qnaResultId, priceCurrency, }) {
14
48
  const wrapperRef = (0, react_1.useRef)(null);
15
49
  // Determine to use user-defined click handler or default behavior
16
50
  const productClickHandler = (0, react_1.useCallback)((item) => {
51
+ const position = items.findIndex((i) => i.id === item.id);
52
+ if (onResultClick && question) {
53
+ onResultClick(item, position >= 0 ? position : 0, question, qnaResultId);
54
+ }
17
55
  const { onProductCardClick } = callbacks || {};
18
56
  if (onProductCardClick) {
19
57
  onProductCardClick(item);
@@ -21,7 +59,7 @@ function PiaCustomCarousel({ items, componentOverrides, callbacks, }) {
21
59
  else if (item === null || item === void 0 ? void 0 : item.url) {
22
60
  window.open(item.url, '_blank', 'noopener,noreferrer');
23
61
  }
24
- }, [callbacks]);
62
+ }, [callbacks, items, onResultClick, question, qnaResultId]);
25
63
  // Set up event listener for product card clicks
26
64
  (0, react_1.useEffect)(() => {
27
65
  const el = wrapperRef.current;
@@ -38,13 +76,8 @@ function PiaCustomCarousel({ items, componentOverrides, callbacks, }) {
38
76
  el.removeEventListener(constructorio_ui_components_1.CIO_EVENTS.productCard.click, handleClick);
39
77
  };
40
78
  }, [productClickHandler]);
41
- const mergedOverrides = (0, react_1.useMemo)(() => {
42
- var _a, _b, _c, _d, _e, _f;
43
- if ((_c = (_b = (_a = componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.item) === null || _a === void 0 ? void 0 : _a.productCard) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.description) {
44
- return componentOverrides;
45
- }
46
- return Object.assign(Object.assign({}, componentOverrides), { item: Object.assign(Object.assign({}, componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.item), { productCard: Object.assign(Object.assign({}, (_d = componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.item) === null || _d === void 0 ? void 0 : _d.productCard), { content: Object.assign(Object.assign({}, (_f = (_e = componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.item) === null || _e === void 0 ? void 0 : _e.productCard) === null || _f === void 0 ? void 0 : _f.content), { description: { reactNode: HtmlDescription } }) }) }) });
47
- }, [componentOverrides]);
79
+ const priceSectionOverride = (0, react_1.useMemo)(() => (priceCurrency ? createPriceSectionOverride(priceCurrency) : undefined), [priceCurrency]);
80
+ const mergedOverrides = (0, react_1.useMemo)(() => buildMergedOverrides(componentOverrides, priceSectionOverride), [componentOverrides, priceSectionOverride]);
48
81
  // If there are no items, do not render the carousel
49
82
  if (items.length === 0) {
50
83
  return null;
@@ -8,7 +8,7 @@ const Disclaimer_1 = tslib_1.__importDefault(require("../CioPia/Disclaimer"));
8
8
  const ErrorBlock_1 = tslib_1.__importDefault(require("../Error/ErrorBlock"));
9
9
  const LoadingSkeleton_1 = tslib_1.__importDefault(require("../LoadingSkeleton/LoadingSkeleton"));
10
10
  const PiaCustomCarousel_1 = tslib_1.__importDefault(require("../CioPia/PiaCustomCarousel"));
11
- function ConversationHistory({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems = true, learnMoreUrl, disclaimerPosition = 'bottom', translations, callbacks, componentOverrides, }) {
11
+ function ConversationHistory({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems = true, learnMoreUrl, disclaimerPosition = 'bottom', translations, callbacks, componentOverrides, handleFeedback, onResultClick, qnaResultId, priceCurrency, }) {
12
12
  const scrollContainerRef = (0, react_1.useRef)(null);
13
13
  (0, react_1.useEffect)(() => {
14
14
  const container = scrollContainerRef.current;
@@ -34,8 +34,8 @@ function ConversationHistory({ conversationHistory, isLoading, error, currentIte
34
34
  isLast && !isLoading && error && (react_1.default.createElement(ErrorBlock_1.default, { message: error.message || 'Unexpected error' })),
35
35
  entry.answer && (react_1.default.createElement("div", { className: 'cio-pia-answer-container' },
36
36
  react_1.default.createElement(Answer_1.default, { text: entry.answer, componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.answer }),
37
- carouselItems && (react_1.default.createElement(PiaCustomCarousel_1.default, { items: carouselItems, componentOverrides: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.carousel, callbacks: callbacks })),
38
- isLast && showFeedback && (react_1.default.createElement(Feedback_1.default, { translations: translations, onFeedback: callbacks === null || callbacks === void 0 ? void 0 : callbacks.onFeedback, componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.feedback }))))));
37
+ carouselItems && (react_1.default.createElement(PiaCustomCarousel_1.default, { items: carouselItems, componentOverrides: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.carousel, callbacks: callbacks, onResultClick: onResultClick, question: entry.question, qnaResultId: qnaResultId, priceCurrency: priceCurrency })),
38
+ isLast && showFeedback && (react_1.default.createElement(Feedback_1.default, { translations: translations, onFeedback: handleFeedback, componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.feedback }))))));
39
39
  })),
40
40
  disclaimerPosition === 'bottom' && disclaimer));
41
41
  }
@@ -7,11 +7,11 @@ const SuggestedQuestionsContainer_1 = tslib_1.__importDefault(require("../Sugges
7
7
  const SuggestedQuestionsSkeleton_1 = tslib_1.__importDefault(require("../SuggestedQuestionsContainer/SuggestedQuestionsSkeleton"));
8
8
  const translate_1 = require("../../utils/translate");
9
9
  const ConversationHistory_1 = tslib_1.__importDefault(require("../ConversationHistory/ConversationHistory"));
10
- function PiaConversation({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems, learnMoreUrl, disclaimerPosition, translations, callbacks, componentOverrides, displayedQuestions, handleSubmitQuestion, handleQuestionClick, containerRef, onInputFocus, }) {
10
+ function PiaConversation({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems, learnMoreUrl, disclaimerPosition, translations, callbacks, componentOverrides, displayedQuestions, handleSubmitQuestion, handleQuestionClick, containerRef, handleFeedback, onResultClick, qnaResultId, onInputFocus, priceCurrency, }) {
11
11
  const hasHistory = conversationHistory.length > 0;
12
12
  return (react_1.default.createElement("div", { ref: containerRef, className: 'cio-pia-container cio-pia-conversation', "data-testid": 'cio-pia-container' },
13
13
  !hasHistory && (react_1.default.createElement("p", { className: 'cio-pia-title', "data-testid": 'cio-pia-title' }, (0, translate_1.translate)('Any questions about this product?', translations))),
14
- react_1.default.createElement(ConversationHistory_1.default, { conversationHistory: conversationHistory, isLoading: isLoading, error: error, currentItems: currentItems, showFeedback: showFeedback, showPreviousItems: showPreviousItems, learnMoreUrl: learnMoreUrl, disclaimerPosition: disclaimerPosition, translations: translations, callbacks: callbacks, componentOverrides: componentOverrides }),
14
+ react_1.default.createElement(ConversationHistory_1.default, { conversationHistory: conversationHistory, isLoading: isLoading, error: error, currentItems: currentItems, showFeedback: showFeedback, showPreviousItems: showPreviousItems, learnMoreUrl: learnMoreUrl, disclaimerPosition: disclaimerPosition, translations: translations, callbacks: callbacks, componentOverrides: componentOverrides, handleFeedback: handleFeedback, onResultClick: onResultClick, qnaResultId: qnaResultId, priceCurrency: priceCurrency }),
15
15
  react_1.default.createElement("div", { className: 'cio-pia-conversation-footer' },
16
16
  isLoading && !error && react_1.default.createElement(SuggestedQuestionsSkeleton_1.default, null),
17
17
  !isLoading && !error && (react_1.default.createElement(SuggestedQuestionsContainer_1.default, { questions: displayedQuestions, onQuestionClick: handleQuestionClick, componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.suggestedQuestions })),
@@ -6,13 +6,13 @@ const Answer_1 = tslib_1.__importDefault(require("../Answer/Answer"));
6
6
  const Feedback_1 = tslib_1.__importDefault(require("../Feedback/Feedback"));
7
7
  const Disclaimer_1 = tslib_1.__importDefault(require("../CioPia/Disclaimer"));
8
8
  const PiaCustomCarousel_1 = tslib_1.__importDefault(require("../CioPia/PiaCustomCarousel"));
9
- function PiaInlineAnswer({ currentAnswer, currentItems, showFeedback, learnMoreUrl, disclaimerPosition = 'bottom', translations, callbacks, componentOverrides, }) {
9
+ function PiaInlineAnswer({ currentAnswer, currentItems, showFeedback, learnMoreUrl, disclaimerPosition = 'bottom', translations, callbacks, componentOverrides, onFeedback, onResultClick, question, qnaResultId, priceCurrency, }) {
10
10
  const disclaimer = (react_1.default.createElement(Disclaimer_1.default, { learnMoreUrl: learnMoreUrl, translations: translations, componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.disclaimer }));
11
11
  return (react_1.default.createElement("div", { className: 'cio-pia-answer-container' },
12
12
  disclaimerPosition === 'top' && disclaimer,
13
13
  react_1.default.createElement(Answer_1.default, { text: currentAnswer, componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.answer }),
14
- currentItems && (react_1.default.createElement(PiaCustomCarousel_1.default, { items: currentItems, componentOverrides: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.carousel, callbacks: callbacks })),
15
- showFeedback && (react_1.default.createElement(Feedback_1.default, { translations: translations, onFeedback: callbacks === null || callbacks === void 0 ? void 0 : callbacks.onFeedback, componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.feedback })),
14
+ currentItems && (react_1.default.createElement(PiaCustomCarousel_1.default, { items: currentItems, componentOverrides: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.carousel, callbacks: callbacks, onResultClick: onResultClick, question: question, qnaResultId: qnaResultId, priceCurrency: priceCurrency })),
15
+ showFeedback && (react_1.default.createElement(Feedback_1.default, { translations: translations, onFeedback: onFeedback || (callbacks === null || callbacks === void 0 ? void 0 : callbacks.onFeedback), componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.feedback })),
16
16
  disclaimerPosition === 'bottom' && disclaimer));
17
17
  }
18
18
  exports.default = PiaInlineAnswer;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DISCLAIMER_TEXT = exports.MOCK_QUESTIONS = exports.DEMO_QUESTION_ALTERNATIVE_PRODUCTS = exports.DEMO_QUESTION = exports.DEMO_ITEM_ID = exports.DEMO_API_KEY = void 0;
3
+ exports.DISCLAIMER_TEXT = exports.MOCK_QUESTIONS = exports.DEMO_QUESTION_ALTERNATIVE_PRODUCTS = exports.DEMO_QUESTION = exports.DEMO_ITEM_NAME = exports.DEMO_ITEM_ID = exports.DEMO_API_KEY = void 0;
4
4
  exports.DEMO_API_KEY = 'key_13TO6qN9H3BP3Wrn';
5
5
  exports.DEMO_ITEM_ID = '149100215';
6
+ exports.DEMO_ITEM_NAME = 'Ensure Original Nutrition Shake';
6
7
  exports.DEMO_QUESTION = 'What is the nutritional content of this shake?';
7
8
  exports.DEMO_QUESTION_ALTERNATIVE_PRODUCTS = 'What alternative products are available for this item?';
8
9
  exports.MOCK_QUESTIONS = [
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const react_1 = require("react");
5
+ const constructorio_client_javascript_1 = tslib_1.__importDefault(require("@constructor-io/constructorio-client-javascript"));
5
6
  const version_1 = tslib_1.__importDefault(require("../version"));
6
- const MockConstructorIOClient_1 = tslib_1.__importDefault(require("./mocks/MockConstructorIOClient"));
7
7
  const useCioClient = ({ apiKey, cioClient, options } = {}) => {
8
8
  if (!apiKey && !cioClient) {
9
9
  throw new Error('Api Key or Constructor Client required');
@@ -12,7 +12,7 @@ const useCioClient = ({ apiKey, cioClient, options } = {}) => {
12
12
  if (cioClient)
13
13
  return cioClient;
14
14
  if (apiKey) {
15
- return new MockConstructorIOClient_1.default(Object.assign({ apiKey, sendTrackingEvents: true, version: `cio-ui-pia-${version_1.default}` }, options));
15
+ return new constructorio_client_javascript_1.default(Object.assign({ apiKey, sendTrackingEvents: true, version: `cio-ui-pia-${version_1.default}` }, options));
16
16
  }
17
17
  return null;
18
18
  }, [apiKey, cioClient, options]);
@@ -2,15 +2,23 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const react_1 = require("react");
5
+ const MockConstructorIOClient_1 = tslib_1.__importDefault(require("./mocks/MockConstructorIOClient"));
5
6
  const useAnswerResults_1 = tslib_1.__importDefault(require("./useAnswerResults"));
6
- const useCioClient_1 = tslib_1.__importDefault(require("./useCioClient"));
7
7
  const useSuggestedQuestions_1 = tslib_1.__importDefault(require("./useSuggestedQuestions"));
8
+ const version_1 = tslib_1.__importDefault(require("../version"));
8
9
  function useCioPia(props) {
9
10
  const { apiKey, itemId, variationId, threadId: providedThreadId, cioClient: providedClient, suggestedQuestionsParameters, formatImageUrl, } = props;
10
11
  const [generatedThreadId] = (0, react_1.useState)(() => crypto.randomUUID());
11
12
  const threadId = providedThreadId || generatedThreadId;
12
- const defaultClient = (0, useCioClient_1.default)({ apiKey });
13
- const client = providedClient || defaultClient;
13
+ const client = (0, react_1.useMemo)(() => {
14
+ if (providedClient)
15
+ return providedClient;
16
+ return new MockConstructorIOClient_1.default({
17
+ apiKey,
18
+ sendTrackingEvents: true,
19
+ version: `cio-ui-pia-${version_1.default}`,
20
+ });
21
+ }, [apiKey, providedClient]);
14
22
  const suggestedQuestions = (0, useSuggestedQuestions_1.default)({
15
23
  itemId,
16
24
  variationId,
@@ -26,6 +34,7 @@ function useCioPia(props) {
26
34
  formatImageUrl,
27
35
  });
28
36
  return {
37
+ cioClient: client,
29
38
  threadId,
30
39
  suggestedQuestions,
31
40
  answers,
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const react_1 = require("react");
4
- function useConversation({ pia, itemId, isConversation, callbacks, }) {
4
+ function useConversation({ pia, itemId, isConversation, callbacks, tracking, }) {
5
5
  var _a, _b, _c, _d;
6
6
  const { suggestedQuestions, answers, threadId } = pia;
7
7
  const { getAnswer } = answers;
@@ -11,8 +11,11 @@ function useConversation({ pia, itemId, isConversation, callbacks, }) {
11
11
  const [conversationHistory, setConversationHistory] = (0, react_1.useState)([]);
12
12
  const entryIdRef = (0, react_1.useRef)(0);
13
13
  const prevAnswerValueRef = (0, react_1.useRef)((_a = answers.data) === null || _a === void 0 ? void 0 : _a.value);
14
+ const hasTrackedCurrentAnswerRef = (0, react_1.useRef)(false);
15
+ const answersRef = (0, react_1.useRef)(answers);
14
16
  const callbacksRef = (0, react_1.useRef)(callbacks);
15
17
  const contextRef = (0, react_1.useRef)(context);
18
+ const trackingRef = (0, react_1.useRef)(tracking);
16
19
  const lastQuestionRef = (0, react_1.useRef)('');
17
20
  const lastSourceRef = (0, react_1.useRef)('user');
18
21
  (0, react_1.useEffect)(() => {
@@ -21,9 +24,16 @@ function useConversation({ pia, itemId, isConversation, callbacks, }) {
21
24
  (0, react_1.useEffect)(() => {
22
25
  contextRef.current = context;
23
26
  }, [context]);
27
+ (0, react_1.useEffect)(() => {
28
+ trackingRef.current = tracking;
29
+ }, [tracking]);
30
+ (0, react_1.useEffect)(() => {
31
+ answersRef.current = answers;
32
+ }, [answers]);
24
33
  const submitQuestion = (0, react_1.useCallback)((question, source) => {
25
34
  lastSourceRef.current = source;
26
35
  lastQuestionRef.current = question;
36
+ hasTrackedCurrentAnswerRef.current = false;
27
37
  setCurrentQuestion(question);
28
38
  getAnswer(question);
29
39
  if (isConversation) {
@@ -33,18 +43,26 @@ function useConversation({ pia, itemId, isConversation, callbacks, }) {
33
43
  }
34
44
  }, [getAnswer, isConversation]);
35
45
  const handleSubmitQuestion = (0, react_1.useCallback)((question) => {
36
- var _a, _b;
37
- (_b = (_a = callbacksRef.current) === null || _a === void 0 ? void 0 : _a.onQuestionSubmit) === null || _b === void 0 ? void 0 : _b.call(_a, question, contextRef.current, 'user');
46
+ var _a, _b, _c;
47
+ (_a = trackingRef.current) === null || _a === void 0 ? void 0 : _a.trackQuestionSubmit(question);
48
+ (_c = (_b = callbacksRef.current) === null || _b === void 0 ? void 0 : _b.onQuestionSubmit) === null || _c === void 0 ? void 0 : _c.call(_b, question, contextRef.current, 'user');
38
49
  submitQuestion(question, 'user');
39
50
  }, [submitQuestion]);
40
51
  const handleQuestionClick = (0, react_1.useCallback)((question) => {
41
- var _a, _b;
42
- (_b = (_a = callbacksRef.current) === null || _a === void 0 ? void 0 : _a.onQuestionSubmit) === null || _b === void 0 ? void 0 : _b.call(_a, question, contextRef.current, 'suggestion');
52
+ var _a, _b, _c;
53
+ (_a = trackingRef.current) === null || _a === void 0 ? void 0 : _a.trackQuestionClick(question);
54
+ (_c = (_b = callbacksRef.current) === null || _b === void 0 ? void 0 : _b.onQuestionSubmit) === null || _c === void 0 ? void 0 : _c.call(_b, question, contextRef.current, 'suggestion');
43
55
  submitQuestion(question, 'suggestion');
44
56
  }, [submitQuestion]);
45
57
  const handleInputFocus = (0, react_1.useCallback)(() => {
46
- var _a, _b;
47
- (_b = (_a = callbacksRef.current) === null || _a === void 0 ? void 0 : _a.onFocus) === null || _b === void 0 ? void 0 : _b.call(_a, contextRef.current);
58
+ var _a, _b, _c;
59
+ (_a = trackingRef.current) === null || _a === void 0 ? void 0 : _a.trackFocus();
60
+ (_c = (_b = callbacksRef.current) === null || _b === void 0 ? void 0 : _b.onFocus) === null || _c === void 0 ? void 0 : _c.call(_b, contextRef.current);
61
+ }, []);
62
+ const handleFeedback = (0, react_1.useCallback)((type) => {
63
+ var _a, _b, _c, _d;
64
+ (_a = trackingRef.current) === null || _a === void 0 ? void 0 : _a.trackAnswerFeedback(type, (_b = answersRef.current.data) === null || _b === void 0 ? void 0 : _b.qna_result_id);
65
+ (_d = (_c = callbacksRef.current) === null || _c === void 0 ? void 0 : _c.onFeedback) === null || _d === void 0 ? void 0 : _d.call(_c, type);
48
66
  }, []);
49
67
  const resetState = (0, react_1.useCallback)(() => {
50
68
  setCurrentQuestion('');
@@ -62,10 +80,14 @@ function useConversation({ pia, itemId, isConversation, callbacks, }) {
62
80
  setDisplayedQuestions(suggestedQuestions.data);
63
81
  }, [suggestedQuestions.data]);
64
82
  (0, react_1.useEffect)(() => {
65
- var _a;
83
+ var _a, _b;
66
84
  if ((_a = answers.data) === null || _a === void 0 ? void 0 : _a.follow_up_questions)
67
85
  setDisplayedQuestions(answers.data.follow_up_questions);
68
- }, [answers.data]);
86
+ if (answers.data && lastQuestionRef.current && !hasTrackedCurrentAnswerRef.current) {
87
+ hasTrackedCurrentAnswerRef.current = true;
88
+ (_b = trackingRef.current) === null || _b === void 0 ? void 0 : _b.trackAnswerView(lastQuestionRef.current, answers.data, answers.items);
89
+ }
90
+ }, [answers.data, answers.items]);
69
91
  (0, react_1.useEffect)(() => {
70
92
  var _a, _b, _c, _d, _e, _f;
71
93
  const answerValue = (_b = (_a = answers.data) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : '';
@@ -116,6 +138,7 @@ function useConversation({ pia, itemId, isConversation, callbacks, }) {
116
138
  handleSubmitQuestion,
117
139
  handleQuestionClick,
118
140
  handleInputFocus,
141
+ handleFeedback,
119
142
  resetState,
120
143
  };
121
144
  }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const react_1 = require("react");
4
+ const types_1 = require("../types");
5
+ function useTracking({ cioClient, itemId, itemName, variationId, threadId, }) {
6
+ const tracker = cioClient === null || cioClient === void 0 ? void 0 : cioClient.tracker;
7
+ const baseParams = (0, react_1.useMemo)(() => (Object.assign(Object.assign({ itemId,
8
+ itemName }, (variationId && { variationId })), (threadId && { threadId }))), [itemId, itemName, variationId, threadId]);
9
+ const mapQuestions = (0, react_1.useCallback)((questions) => questions.map((q) => ({ question: q.value })), []);
10
+ const trackViews = (0, react_1.useCallback)((questions, viewTimespans) => {
11
+ tracker === null || tracker === void 0 ? void 0 : tracker.trackProductInsightsAgentViews(Object.assign(Object.assign({}, baseParams), { questions: mapQuestions(questions), viewTimespans }));
12
+ }, [tracker, baseParams, mapQuestions]);
13
+ const trackView = (0, react_1.useCallback)((questions) => {
14
+ tracker === null || tracker === void 0 ? void 0 : tracker.trackProductInsightsAgentView(Object.assign(Object.assign({}, baseParams), { questions: mapQuestions(questions) }));
15
+ }, [tracker, baseParams, mapQuestions]);
16
+ const trackOutOfView = (0, react_1.useCallback)(() => {
17
+ tracker === null || tracker === void 0 ? void 0 : tracker.trackProductInsightsAgentOutOfView(baseParams);
18
+ }, [tracker, baseParams]);
19
+ const trackFocus = (0, react_1.useCallback)(() => {
20
+ tracker === null || tracker === void 0 ? void 0 : tracker.trackProductInsightsAgentFocus(baseParams);
21
+ }, [tracker, baseParams]);
22
+ const trackQuestionClick = (0, react_1.useCallback)((question) => {
23
+ tracker === null || tracker === void 0 ? void 0 : tracker.trackProductInsightsAgentQuestionClick(Object.assign(Object.assign({}, baseParams), { question }));
24
+ }, [tracker, baseParams]);
25
+ const trackQuestionSubmit = (0, react_1.useCallback)((question) => {
26
+ tracker === null || tracker === void 0 ? void 0 : tracker.trackProductInsightsAgentQuestionSubmit(Object.assign(Object.assign({}, baseParams), { question }));
27
+ }, [tracker, baseParams]);
28
+ const trackAnswerView = (0, react_1.useCallback)((question, answerData, items) => {
29
+ tracker === null || tracker === void 0 ? void 0 : tracker.trackProductInsightsAgentAnswerView(Object.assign(Object.assign(Object.assign(Object.assign({}, baseParams), { question, answerText: answerData.value, qnaResultId: answerData.qna_result_id }), (items &&
30
+ items.length > 0 && {
31
+ items: items.map((item) => ({
32
+ itemId: item.id,
33
+ itemName: item.name,
34
+ })),
35
+ })), (answerData.follow_up_questions &&
36
+ answerData.follow_up_questions.length > 0 && {
37
+ followUpQuestions: answerData.follow_up_questions.map((q) => ({
38
+ value: q.value,
39
+ })),
40
+ })));
41
+ }, [tracker, baseParams]);
42
+ const trackAnswerFeedback = (0, react_1.useCallback)((feedbackType, qnaResultId) => {
43
+ const feedbackLabel = feedbackType === types_1.FeedbackType.UP ? 'thumbs_up' : 'thumbs_down';
44
+ tracker === null || tracker === void 0 ? void 0 : tracker.trackProductInsightsAgentAnswerFeedback(Object.assign(Object.assign(Object.assign({}, baseParams), { feedbackLabel }), (qnaResultId && { qnaResultId })));
45
+ }, [tracker, baseParams]);
46
+ const trackResultClick = (0, react_1.useCallback)((clickedItem, position, question, qnaResultId) => {
47
+ tracker === null || tracker === void 0 ? void 0 : tracker.trackProductInsightsAgentResultClick(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ itemId: clickedItem.id, itemName: clickedItem.name }, (clickedItem.variationId && { variationId: clickedItem.variationId })), { question, seedItemId: itemId, seedItemName: itemName }), (variationId && { seedVariationId: variationId })), (qnaResultId && { qnaResultId })), (threadId && { threadId })), { position }));
48
+ }, [tracker, itemId, itemName, variationId, threadId]);
49
+ return (0, react_1.useMemo)(() => ({
50
+ trackViews,
51
+ trackView,
52
+ trackOutOfView,
53
+ trackFocus,
54
+ trackQuestionClick,
55
+ trackQuestionSubmit,
56
+ trackAnswerView,
57
+ trackAnswerFeedback,
58
+ trackResultClick,
59
+ }), [
60
+ trackViews,
61
+ trackView,
62
+ trackOutOfView,
63
+ trackFocus,
64
+ trackQuestionClick,
65
+ trackQuestionSubmit,
66
+ trackAnswerView,
67
+ trackAnswerFeedback,
68
+ trackResultClick,
69
+ ]);
70
+ }
71
+ exports.default = useTracking;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const react_1 = require("react");
4
+ const FLUSH_INTERVAL_MS = 5 * 60 * 1000;
5
+ function useViewportTracking({ tracking, questions, }) {
6
+ const nodeRef = (0, react_1.useRef)(null);
7
+ const observerRef = (0, react_1.useRef)(null);
8
+ const intervalRef = (0, react_1.useRef)(null);
9
+ const timespansRef = (0, react_1.useRef)([]);
10
+ const entryTimeRef = (0, react_1.useRef)(null);
11
+ const questionsRef = (0, react_1.useRef)(questions);
12
+ const trackingRef = (0, react_1.useRef)(tracking);
13
+ (0, react_1.useEffect)(() => {
14
+ const questionsJustArrived = questionsRef.current.length === 0 && questions.length > 0;
15
+ questionsRef.current = questions;
16
+ if (questionsJustArrived && entryTimeRef.current) {
17
+ trackingRef.current.trackView(questions);
18
+ }
19
+ }, [questions]);
20
+ (0, react_1.useEffect)(() => {
21
+ trackingRef.current = tracking;
22
+ }, [tracking]);
23
+ // Stable: only reads refs
24
+ const flush = (0, react_1.useCallback)(() => {
25
+ if (entryTimeRef.current) {
26
+ timespansRef.current.push({
27
+ start: entryTimeRef.current,
28
+ end: new Date().toISOString(),
29
+ });
30
+ entryTimeRef.current = null;
31
+ }
32
+ if (timespansRef.current.length > 0 && questionsRef.current.length > 0) {
33
+ trackingRef.current.trackViews(questionsRef.current, [...timespansRef.current]);
34
+ timespansRef.current = [];
35
+ }
36
+ }, []);
37
+ const setupObserver = (0, react_1.useCallback)((element) => {
38
+ const observer = new IntersectionObserver(([entry]) => {
39
+ if (entry.isIntersecting) {
40
+ entryTimeRef.current = new Date().toISOString();
41
+ if (questionsRef.current.length > 0) {
42
+ trackingRef.current.trackView(questionsRef.current);
43
+ }
44
+ }
45
+ else if (entryTimeRef.current) {
46
+ timespansRef.current.push({
47
+ start: entryTimeRef.current,
48
+ end: new Date().toISOString(),
49
+ });
50
+ entryTimeRef.current = null;
51
+ trackingRef.current.trackOutOfView();
52
+ }
53
+ }, { threshold: 0.5 });
54
+ observer.observe(element);
55
+ observerRef.current = observer;
56
+ intervalRef.current = setInterval(flush, FLUSH_INTERVAL_MS);
57
+ const handleVisibilityChange = () => {
58
+ if (document.visibilityState === 'hidden') {
59
+ flush();
60
+ }
61
+ };
62
+ document.addEventListener('visibilitychange', handleVisibilityChange);
63
+ return () => {
64
+ observer.disconnect();
65
+ if (intervalRef.current)
66
+ clearInterval(intervalRef.current);
67
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
68
+ flush();
69
+ };
70
+ }, [flush]);
71
+ const cleanupRef = (0, react_1.useRef)(null);
72
+ const containerRef = (0, react_1.useCallback)((node) => {
73
+ if (cleanupRef.current) {
74
+ cleanupRef.current();
75
+ cleanupRef.current = null;
76
+ }
77
+ nodeRef.current = node;
78
+ if (node) {
79
+ cleanupRef.current = setupObserver(node);
80
+ }
81
+ }, [setupObserver]);
82
+ (0, react_1.useEffect)(() => {
83
+ return () => {
84
+ if (cleanupRef.current) {
85
+ cleanupRef.current();
86
+ cleanupRef.current = null;
87
+ }
88
+ };
89
+ }, []);
90
+ return { containerRef };
91
+ }
92
+ exports.default = useViewportTracking;
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = '2.8.0';
3
+ exports.default = '2.10.0';
@@ -1,9 +1,11 @@
1
- import React from 'react';
1
+ import React, { useCallback } from 'react';
2
2
  import { RenderPropsWrapper, } from '@constructor-io/constructorio-ui-components';
3
3
  import Input from '../Input/Input';
4
4
  import SuggestedQuestionsContainer from '../SuggestedQuestionsContainer/SuggestedQuestionsContainer';
5
5
  import useCioPia from '../../hooks/useCioPia';
6
6
  import useConversation from '../../hooks/useConversation';
7
+ import useTracking from '../../hooks/useTracking';
8
+ import useViewportTracking from '../../hooks/useViewportTracking';
7
9
  import useViewportCallbacks from '../../hooks/useViewportCallbacks';
8
10
  import ErrorBlock from '../Error/ErrorBlock';
9
11
  import LoadingSkeleton from '../LoadingSkeleton/LoadingSkeleton';
@@ -13,9 +15,10 @@ import PiaModal from '../PiaConversation/PiaModal';
13
15
  import PiaConversation from '../PiaConversation/PiaConversation';
14
16
  // eslint-disable-next-line complexity
15
17
  export default function CioPia(props) {
16
- const { apiKey, itemId, threadId, variationId, cioClient, displayConfigs, componentOverrides, callbacks, formatters, children, translations, suggestedQuestionsParameters, } = props;
18
+ const { apiKey, itemId, itemName, threadId, variationId, cioClient, displayConfigs, componentOverrides, callbacks, formatters, productCardProps, children, translations, suggestedQuestionsParameters, } = props;
17
19
  const { learnMoreUrl, showFeedback, mode = 'default', type = 'inline', showPreviousItems, disclaimerPosition = 'bottom', } = displayConfigs || {};
18
20
  const isConversation = mode === 'conversation' || type === 'modal';
21
+ const { priceCurrency } = productCardProps || {};
19
22
  const pia = useCioPia({
20
23
  apiKey,
21
24
  itemId,
@@ -25,8 +28,24 @@ export default function CioPia(props) {
25
28
  suggestedQuestionsParameters,
26
29
  formatImageUrl: formatters?.formatImageUrl,
27
30
  });
28
- const { currentQuestion, displayedQuestions, conversationHistory, currentAnswer, currentItems, isLoading, error, context, handleSubmitQuestion, handleQuestionClick, handleInputFocus, resetState, } = useConversation({ pia, itemId, isConversation, callbacks });
29
- const { containerRef } = useViewportCallbacks({ callbacks, context });
31
+ const tracking = useTracking({
32
+ cioClient: pia.cioClient,
33
+ itemId,
34
+ itemName,
35
+ variationId,
36
+ threadId: pia.threadId,
37
+ });
38
+ const { currentQuestion, displayedQuestions, conversationHistory, currentAnswer, currentItems, isLoading, error, context, handleSubmitQuestion, handleQuestionClick, handleInputFocus, handleFeedback, resetState, } = useConversation({ pia, itemId, isConversation, callbacks, tracking });
39
+ const { containerRef: viewportContainerRef } = useViewportTracking({
40
+ tracking,
41
+ questions: displayedQuestions,
42
+ });
43
+ const { containerRef: callbackContainerRef } = useViewportCallbacks({ callbacks, context });
44
+ const containerRef = useCallback((node) => {
45
+ viewportContainerRef(node);
46
+ callbackContainerRef(node);
47
+ }, [viewportContainerRef, callbackContainerRef]);
48
+ const qnaResultId = pia.answers.data?.qna_result_id;
30
49
  const renderProps = {
31
50
  items: currentItems,
32
51
  isLoading,
@@ -52,8 +71,12 @@ export default function CioPia(props) {
52
71
  displayedQuestions,
53
72
  handleSubmitQuestion,
54
73
  handleQuestionClick,
74
+ handleFeedback,
75
+ onResultClick: tracking.trackResultClick,
76
+ qnaResultId,
55
77
  containerRef,
56
78
  onInputFocus: handleInputFocus,
79
+ priceCurrency,
57
80
  };
58
81
  if (type === 'modal') {
59
82
  return (React.createElement(PiaModal, { initialQuestions: pia.suggestedQuestions.data, handleSubmitQuestion: handleSubmitQuestion, handleQuestionClick: handleQuestionClick, containerRef: containerRef, isLoading: isLoading, componentOverrides: componentOverrides, translations: translations, onInputFocus: handleInputFocus, onClose: resetState },
@@ -69,6 +92,6 @@ export default function CioPia(props) {
69
92
  isLoading && React.createElement(LoadingSkeleton, { componentOverride: componentOverrides?.loading }),
70
93
  !isLoading && error && React.createElement(ErrorBlock, { message: error?.message || 'Unexpected error' }),
71
94
  !isLoading && !error && (React.createElement(React.Fragment, null,
72
- currentAnswer && (React.createElement(PiaInlineAnswer, { currentAnswer: currentAnswer, currentItems: currentItems, showFeedback: showFeedback, learnMoreUrl: learnMoreUrl, disclaimerPosition: disclaimerPosition, translations: translations, callbacks: callbacks, componentOverrides: componentOverrides })),
95
+ currentAnswer && (React.createElement(PiaInlineAnswer, { currentAnswer: currentAnswer, currentItems: currentItems, showFeedback: showFeedback, learnMoreUrl: learnMoreUrl, disclaimerPosition: disclaimerPosition, translations: translations, callbacks: callbacks, componentOverrides: componentOverrides, onFeedback: handleFeedback, onResultClick: tracking.trackResultClick, question: currentQuestion, qnaResultId: qnaResultId, priceCurrency: priceCurrency })),
73
96
  React.createElement(SuggestedQuestionsContainer, { questions: displayedQuestions, onQuestionClick: handleQuestionClick, componentOverride: componentOverrides?.suggestedQuestions }))))));
74
97
  }