@constructor-io/constructorio-ui-pia 2.9.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.
@@ -19,9 +19,10 @@ const PiaConversation_1 = tslib_1.__importDefault(require("../PiaConversation/Pi
19
19
  // eslint-disable-next-line complexity
20
20
  function CioPia(props) {
21
21
  var _a;
22
- const { apiKey, itemId, itemName, threadId, variationId, cioClient, displayConfigs, componentOverrides, callbacks, formatters, children, translations, suggestedQuestionsParameters, } = props;
22
+ const { apiKey, itemId, itemName, threadId, variationId, cioClient, displayConfigs, componentOverrides, callbacks, formatters, productCardProps, children, translations, suggestedQuestionsParameters, } = props;
23
23
  const { learnMoreUrl, showFeedback, mode = 'default', type = 'inline', showPreviousItems, disclaimerPosition = 'bottom', } = displayConfigs || {};
24
24
  const isConversation = mode === 'conversation' || type === 'modal';
25
+ const { priceCurrency } = productCardProps || {};
25
26
  const pia = (0, useCioPia_1.default)({
26
27
  apiKey,
27
28
  itemId,
@@ -79,6 +80,7 @@ function CioPia(props) {
79
80
  qnaResultId,
80
81
  containerRef,
81
82
  onInputFocus: handleInputFocus,
83
+ priceCurrency,
82
84
  };
83
85
  if (type === 'modal') {
84
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 },
@@ -94,7 +96,7 @@ function CioPia(props) {
94
96
  isLoading && react_1.default.createElement(LoadingSkeleton_1.default, { componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.loading }),
95
97
  !isLoading && error && react_1.default.createElement(ErrorBlock_1.default, { message: (error === null || error === void 0 ? void 0 : error.message) || 'Unexpected error' }),
96
98
  !isLoading && !error && (react_1.default.createElement(react_1.default.Fragment, null,
97
- 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 })),
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 })),
98
100
  react_1.default.createElement(SuggestedQuestionsContainer_1.default, { questions: displayedQuestions, onQuestionClick: handleQuestionClick, componentOverride: componentOverrides === null || componentOverrides === void 0 ? void 0 : componentOverrides.suggestedQuestions }))))));
99
101
  }
100
102
  exports.default = CioPia;
@@ -10,7 +10,41 @@ 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, onResultClick, question, qnaResultId, }) {
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) => {
@@ -42,13 +76,8 @@ function PiaCustomCarousel({ items, componentOverrides, callbacks, onResultClick
42
76
  el.removeEventListener(constructorio_ui_components_1.CIO_EVENTS.productCard.click, handleClick);
43
77
  };
44
78
  }, [productClickHandler]);
45
- const mergedOverrides = (0, react_1.useMemo)(() => {
46
- var _a, _b, _c, _d, _e, _f;
47
- 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) {
48
- return componentOverrides;
49
- }
50
- 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 } }) }) }) });
51
- }, [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]);
52
81
  // If there are no items, do not render the carousel
53
82
  if (items.length === 0) {
54
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, handleFeedback, onResultClick, qnaResultId, }) {
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,7 +34,7 @@ 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, onResultClick: onResultClick, question: entry.question, qnaResultId: qnaResultId })),
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
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));
@@ -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, handleFeedback, onResultClick, qnaResultId, 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, handleFeedback: handleFeedback, onResultClick: onResultClick, qnaResultId: qnaResultId }),
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,12 +6,12 @@ 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, onFeedback, onResultClick, question, qnaResultId, }) {
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, onResultClick: onResultClick, question: question, qnaResultId: qnaResultId })),
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
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
  }
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = '2.9.0';
3
+ exports.default = '2.10.0';
@@ -15,9 +15,10 @@ import PiaModal from '../PiaConversation/PiaModal';
15
15
  import PiaConversation from '../PiaConversation/PiaConversation';
16
16
  // eslint-disable-next-line complexity
17
17
  export default function CioPia(props) {
18
- const { apiKey, itemId, itemName, 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;
19
19
  const { learnMoreUrl, showFeedback, mode = 'default', type = 'inline', showPreviousItems, disclaimerPosition = 'bottom', } = displayConfigs || {};
20
20
  const isConversation = mode === 'conversation' || type === 'modal';
21
+ const { priceCurrency } = productCardProps || {};
21
22
  const pia = useCioPia({
22
23
  apiKey,
23
24
  itemId,
@@ -75,6 +76,7 @@ export default function CioPia(props) {
75
76
  qnaResultId,
76
77
  containerRef,
77
78
  onInputFocus: handleInputFocus,
79
+ priceCurrency,
78
80
  };
79
81
  if (type === 'modal') {
80
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 },
@@ -90,6 +92,6 @@ export default function CioPia(props) {
90
92
  isLoading && React.createElement(LoadingSkeleton, { componentOverride: componentOverrides?.loading }),
91
93
  !isLoading && error && React.createElement(ErrorBlock, { message: error?.message || 'Unexpected error' }),
92
94
  !isLoading && !error && (React.createElement(React.Fragment, null,
93
- 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 })),
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 })),
94
96
  React.createElement(SuggestedQuestionsContainer, { questions: displayedQuestions, onQuestionClick: handleQuestionClick, componentOverride: componentOverrides?.suggestedQuestions }))))));
95
97
  }
@@ -7,7 +7,53 @@ function HtmlDescription({ product }) {
7
7
  return null;
8
8
  return (React.createElement("p", { className: 'cio-product-card-description', dangerouslySetInnerHTML: { __html: sanitizeHtml(description) } }));
9
9
  }
10
- export default function PiaCustomCarousel({ items, componentOverrides, callbacks, onResultClick, question, qnaResultId, }) {
10
+ function createPriceSectionOverride(priceCurrency) {
11
+ return function PriceSectionOverride({ product }) {
12
+ const { price, salePrice } = product;
13
+ if (price == null)
14
+ return null;
15
+ return (React.createElement("div", { className: 'cio-product-card-price-section flex items-baseline gap-2' },
16
+ React.createElement("span", { className: 'text-lg font-bold' },
17
+ priceCurrency,
18
+ "\u00A0",
19
+ salePrice ?? price),
20
+ salePrice != null && (React.createElement("span", { className: 'text-sm text-gray-400 line-through' },
21
+ priceCurrency,
22
+ "\u00A0",
23
+ price))));
24
+ };
25
+ }
26
+ function getContentDefaults(content, priceSectionOverride) {
27
+ const defaults = {};
28
+ if (!content?.description) {
29
+ defaults.description = { reactNode: HtmlDescription };
30
+ }
31
+ if (!content?.price && priceSectionOverride) {
32
+ defaults.price = { reactNode: priceSectionOverride };
33
+ }
34
+ return defaults;
35
+ }
36
+ function buildMergedOverrides(componentOverrides, priceSectionOverride) {
37
+ const content = componentOverrides?.item?.productCard?.content;
38
+ const defaults = getContentDefaults(content, priceSectionOverride);
39
+ if (Object.keys(defaults).length === 0) {
40
+ return componentOverrides || {};
41
+ }
42
+ return {
43
+ ...componentOverrides,
44
+ item: {
45
+ ...componentOverrides?.item,
46
+ productCard: {
47
+ ...componentOverrides?.item?.productCard,
48
+ content: {
49
+ ...content,
50
+ ...defaults,
51
+ },
52
+ },
53
+ },
54
+ };
55
+ }
56
+ export default function PiaCustomCarousel({ items, componentOverrides, callbacks, onResultClick, question, qnaResultId, priceCurrency, }) {
11
57
  const wrapperRef = useRef(null);
12
58
  // Determine to use user-defined click handler or default behavior
13
59
  const productClickHandler = useCallback((item) => {
@@ -39,24 +85,8 @@ export default function PiaCustomCarousel({ items, componentOverrides, callbacks
39
85
  el.removeEventListener(CIO_EVENTS.productCard.click, handleClick);
40
86
  };
41
87
  }, [productClickHandler]);
42
- const mergedOverrides = useMemo(() => {
43
- if (componentOverrides?.item?.productCard?.content?.description) {
44
- return componentOverrides;
45
- }
46
- return {
47
- ...componentOverrides,
48
- item: {
49
- ...componentOverrides?.item,
50
- productCard: {
51
- ...componentOverrides?.item?.productCard,
52
- content: {
53
- ...componentOverrides?.item?.productCard?.content,
54
- description: { reactNode: HtmlDescription },
55
- },
56
- },
57
- },
58
- };
59
- }, [componentOverrides]);
88
+ const priceSectionOverride = useMemo(() => (priceCurrency ? createPriceSectionOverride(priceCurrency) : undefined), [priceCurrency]);
89
+ const mergedOverrides = useMemo(() => buildMergedOverrides(componentOverrides, priceSectionOverride), [componentOverrides, priceSectionOverride]);
60
90
  // If there are no items, do not render the carousel
61
91
  if (items.length === 0) {
62
92
  return null;
@@ -5,7 +5,7 @@ import Disclaimer from '../CioPia/Disclaimer';
5
5
  import ErrorBlock from '../Error/ErrorBlock';
6
6
  import LoadingSkeleton from '../LoadingSkeleton/LoadingSkeleton';
7
7
  import PiaCustomCarousel from '../CioPia/PiaCustomCarousel';
8
- export default function ConversationHistory({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems = true, learnMoreUrl, disclaimerPosition = 'bottom', translations, callbacks, componentOverrides, handleFeedback, onResultClick, qnaResultId, }) {
8
+ export default function ConversationHistory({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems = true, learnMoreUrl, disclaimerPosition = 'bottom', translations, callbacks, componentOverrides, handleFeedback, onResultClick, qnaResultId, priceCurrency, }) {
9
9
  const scrollContainerRef = useRef(null);
10
10
  useEffect(() => {
11
11
  const container = scrollContainerRef.current;
@@ -31,7 +31,7 @@ export default function ConversationHistory({ conversationHistory, isLoading, er
31
31
  isLast && !isLoading && error && (React.createElement(ErrorBlock, { message: error.message || 'Unexpected error' })),
32
32
  entry.answer && (React.createElement("div", { className: 'cio-pia-answer-container' },
33
33
  React.createElement(Answer, { text: entry.answer, componentOverride: componentOverrides?.answer }),
34
- carouselItems && (React.createElement(PiaCustomCarousel, { items: carouselItems, componentOverrides: componentOverrides?.carousel, callbacks: callbacks, onResultClick: onResultClick, question: entry.question, qnaResultId: qnaResultId })),
34
+ carouselItems && (React.createElement(PiaCustomCarousel, { items: carouselItems, componentOverrides: componentOverrides?.carousel, callbacks: callbacks, onResultClick: onResultClick, question: entry.question, qnaResultId: qnaResultId, priceCurrency: priceCurrency })),
35
35
  isLast && showFeedback && (React.createElement(Feedback, { translations: translations, onFeedback: handleFeedback, componentOverride: componentOverrides?.feedback }))))));
36
36
  })),
37
37
  disclaimerPosition === 'bottom' && disclaimer));
@@ -4,11 +4,11 @@ import SuggestedQuestionsContainer from '../SuggestedQuestionsContainer/Suggeste
4
4
  import SuggestedQuestionsSkeleton from '../SuggestedQuestionsContainer/SuggestedQuestionsSkeleton';
5
5
  import { translate } from '../../utils/translate';
6
6
  import ConversationHistory from '../ConversationHistory/ConversationHistory';
7
- export default function PiaConversation({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems, learnMoreUrl, disclaimerPosition, translations, callbacks, componentOverrides, displayedQuestions, handleSubmitQuestion, handleQuestionClick, containerRef, handleFeedback, onResultClick, qnaResultId, onInputFocus, }) {
7
+ export default function PiaConversation({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems, learnMoreUrl, disclaimerPosition, translations, callbacks, componentOverrides, displayedQuestions, handleSubmitQuestion, handleQuestionClick, containerRef, handleFeedback, onResultClick, qnaResultId, onInputFocus, priceCurrency, }) {
8
8
  const hasHistory = conversationHistory.length > 0;
9
9
  return (React.createElement("div", { ref: containerRef, className: 'cio-pia-container cio-pia-conversation', "data-testid": 'cio-pia-container' },
10
10
  !hasHistory && (React.createElement("p", { className: 'cio-pia-title', "data-testid": 'cio-pia-title' }, translate('Any questions about this product?', translations))),
11
- React.createElement(ConversationHistory, { 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 }),
11
+ React.createElement(ConversationHistory, { 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 }),
12
12
  React.createElement("div", { className: 'cio-pia-conversation-footer' },
13
13
  isLoading && !error && React.createElement(SuggestedQuestionsSkeleton, null),
14
14
  !isLoading && !error && (React.createElement(SuggestedQuestionsContainer, { questions: displayedQuestions, onQuestionClick: handleQuestionClick, componentOverride: componentOverrides?.suggestedQuestions })),
@@ -3,12 +3,12 @@ import Answer from '../Answer/Answer';
3
3
  import Feedback from '../Feedback/Feedback';
4
4
  import Disclaimer from '../CioPia/Disclaimer';
5
5
  import PiaCustomCarousel from '../CioPia/PiaCustomCarousel';
6
- export default function PiaInlineAnswer({ currentAnswer, currentItems, showFeedback, learnMoreUrl, disclaimerPosition = 'bottom', translations, callbacks, componentOverrides, onFeedback, onResultClick, question, qnaResultId, }) {
6
+ export default function PiaInlineAnswer({ currentAnswer, currentItems, showFeedback, learnMoreUrl, disclaimerPosition = 'bottom', translations, callbacks, componentOverrides, onFeedback, onResultClick, question, qnaResultId, priceCurrency, }) {
7
7
  const disclaimer = (React.createElement(Disclaimer, { learnMoreUrl: learnMoreUrl, translations: translations, componentOverride: componentOverrides?.disclaimer }));
8
8
  return (React.createElement("div", { className: 'cio-pia-answer-container' },
9
9
  disclaimerPosition === 'top' && disclaimer,
10
10
  React.createElement(Answer, { text: currentAnswer, componentOverride: componentOverrides?.answer }),
11
- currentItems && (React.createElement(PiaCustomCarousel, { items: currentItems, componentOverrides: componentOverrides?.carousel, callbacks: callbacks, onResultClick: onResultClick, question: question, qnaResultId: qnaResultId })),
11
+ currentItems && (React.createElement(PiaCustomCarousel, { items: currentItems, componentOverrides: componentOverrides?.carousel, callbacks: callbacks, onResultClick: onResultClick, question: question, qnaResultId: qnaResultId, priceCurrency: priceCurrency })),
12
12
  showFeedback && (React.createElement(Feedback, { translations: translations, onFeedback: onFeedback || callbacks?.onFeedback, componentOverride: componentOverrides?.feedback })),
13
13
  disclaimerPosition === 'bottom' && disclaimer));
14
14
  }
@@ -1 +1 @@
1
- export default '2.9.0';
1
+ export default '2.10.0';
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { IncludeComponentOverrides, IncludeRenderProps } from '@constructor-io/constructorio-ui-components';
3
3
  import MockConstructorIOClient from '../../hooks/mocks/MockConstructorIOClient';
4
- import { CioPiaRenderProps, CioPiaComponentOverrides, Callbacks, CioPiaDisplayConfigs, Translations, SuggestedQuestionsParameters, Formatters } from '../../types';
4
+ import { CioPiaRenderProps, CioPiaComponentOverrides, Callbacks, CioPiaDisplayConfigs, Translations, SuggestedQuestionsParameters, Formatters, ProductCardDisplayProps } from '../../types';
5
5
  export interface CioPiaProps extends IncludeRenderProps<CioPiaRenderProps>, IncludeComponentOverrides<CioPiaComponentOverrides> {
6
6
  /** Your Constructor.io API key. */
7
7
  apiKey: string;
@@ -23,6 +23,8 @@ export interface CioPiaProps extends IncludeRenderProps<CioPiaRenderProps>, Incl
23
23
  componentOverrides?: CioPiaComponentOverrides;
24
24
  /** Formatter functions for transforming data before display. */
25
25
  formatters?: Formatters;
26
+ /** Props forwarded to the ProductCard rendered inside the carousel. */
27
+ productCardProps?: ProductCardDisplayProps;
26
28
  /** UI string translations for internationalization. */
27
29
  translations?: Translations;
28
30
  /** Parameters for the suggested questions request. */
@@ -8,6 +8,7 @@ interface PiaCustomCarouselProps {
8
8
  onResultClick?: (item: Item, position: number, question: string, qnaResultId?: string) => void;
9
9
  question?: string;
10
10
  qnaResultId?: string;
11
+ priceCurrency?: string;
11
12
  }
12
- export default function PiaCustomCarousel({ items, componentOverrides, callbacks, onResultClick, question, qnaResultId, }: PiaCustomCarouselProps): React.JSX.Element | null;
13
+ export default function PiaCustomCarousel({ items, componentOverrides, callbacks, onResultClick, question, qnaResultId, priceCurrency, }: PiaCustomCarouselProps): React.JSX.Element | null;
13
14
  export {};
@@ -25,5 +25,6 @@ export interface ConversationHistoryProps {
25
25
  handleFeedback?: (type: FeedbackType) => void;
26
26
  onResultClick?: (item: Item, position: number, question: string, qnaResultId?: string) => void;
27
27
  qnaResultId?: string;
28
+ priceCurrency?: string;
28
29
  }
29
- export default function ConversationHistory({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems, learnMoreUrl, disclaimerPosition, translations, callbacks, componentOverrides, handleFeedback, onResultClick, qnaResultId, }: ConversationHistoryProps): React.JSX.Element;
30
+ export default function ConversationHistory({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems, learnMoreUrl, disclaimerPosition, translations, callbacks, componentOverrides, handleFeedback, onResultClick, qnaResultId, priceCurrency, }: ConversationHistoryProps): React.JSX.Element;
@@ -11,4 +11,4 @@ export interface PiaConversationProps extends ConversationHistoryProps {
11
11
  qnaResultId?: string;
12
12
  onInputFocus?: () => void;
13
13
  }
14
- export default function PiaConversation({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems, learnMoreUrl, disclaimerPosition, translations, callbacks, componentOverrides, displayedQuestions, handleSubmitQuestion, handleQuestionClick, containerRef, handleFeedback, onResultClick, qnaResultId, onInputFocus, }: PiaConversationProps): React.JSX.Element;
14
+ export default function PiaConversation({ conversationHistory, isLoading, error, currentItems, showFeedback, showPreviousItems, learnMoreUrl, disclaimerPosition, translations, callbacks, componentOverrides, displayedQuestions, handleSubmitQuestion, handleQuestionClick, containerRef, handleFeedback, onResultClick, qnaResultId, onInputFocus, priceCurrency, }: PiaConversationProps): React.JSX.Element;
@@ -13,6 +13,7 @@ interface PiaInlineAnswerProps {
13
13
  onResultClick?: (item: Item, position: number, question: string, qnaResultId?: string) => void;
14
14
  question?: string;
15
15
  qnaResultId?: string;
16
+ priceCurrency?: string;
16
17
  }
17
- export default function PiaInlineAnswer({ currentAnswer, currentItems, showFeedback, learnMoreUrl, disclaimerPosition, translations, callbacks, componentOverrides, onFeedback, onResultClick, question, qnaResultId, }: PiaInlineAnswerProps): React.JSX.Element;
18
+ export default function PiaInlineAnswer({ currentAnswer, currentItems, showFeedback, learnMoreUrl, disclaimerPosition, translations, callbacks, componentOverrides, onFeedback, onResultClick, question, qnaResultId, priceCurrency, }: PiaInlineAnswerProps): React.JSX.Element;
18
19
  export {};
@@ -86,6 +86,14 @@ export interface Formatters {
86
86
  /** Transforms image URLs before rendering (e.g., prepend a CDN base URL). */
87
87
  formatImageUrl?: (url: string) => string;
88
88
  }
89
+ /** Props forwarded to the ProductCard rendered inside the carousel. */
90
+ export interface ProductCardDisplayProps {
91
+ /**
92
+ * Currency symbol to display next to product prices (e.g., "€", "£").
93
+ * When omitted, the default ProductCard price rendering is used.
94
+ */
95
+ priceCurrency?: string;
96
+ }
89
97
  /** Extends Product type to include PIA-specific fields */
90
98
  export interface Item extends Product, Record<string, any> {
91
99
  url?: string;
@@ -1,2 +1,2 @@
1
- declare const _default: "2.9.0";
1
+ declare const _default: "2.10.0";
2
2
  export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructor-io/constructorio-ui-pia",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "description": "Constructor.io AI Product Insights Agent UI library for web applications",
5
5
  "author": "Constructor.io Corporation",
6
6
  "license": "MIT",