@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.
- package/dist/constructorio-ui-pia-bundled.js +49 -49
- package/lib/cjs/components/CioPia/CioPia.js +4 -2
- package/lib/cjs/components/CioPia/PiaCustomCarousel.js +37 -8
- package/lib/cjs/components/ConversationHistory/ConversationHistory.js +2 -2
- package/lib/cjs/components/PiaConversation/PiaConversation.js +2 -2
- package/lib/cjs/components/PiaInlineAnswer/PiaInlineAnswer.js +2 -2
- package/lib/cjs/version.js +1 -1
- package/lib/mjs/components/CioPia/CioPia.js +4 -2
- package/lib/mjs/components/CioPia/PiaCustomCarousel.js +49 -19
- package/lib/mjs/components/ConversationHistory/ConversationHistory.js +2 -2
- package/lib/mjs/components/PiaConversation/PiaConversation.js +2 -2
- package/lib/mjs/components/PiaInlineAnswer/PiaInlineAnswer.js +2 -2
- package/lib/mjs/version.js +1 -1
- package/lib/types/components/CioPia/CioPia.d.ts +3 -1
- package/lib/types/components/CioPia/PiaCustomCarousel.d.ts +2 -1
- package/lib/types/components/ConversationHistory/ConversationHistory.d.ts +2 -1
- package/lib/types/components/PiaConversation/PiaConversation.d.ts +1 -1
- package/lib/types/components/PiaInlineAnswer/PiaInlineAnswer.d.ts +2 -1
- package/lib/types/types.d.ts +8 -0
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -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
|
|
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
|
|
46
|
-
|
|
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
|
}
|
package/lib/cjs/version.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
43
|
-
|
|
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
|
}
|
package/lib/mjs/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '2.
|
|
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 {};
|
package/lib/types/types.d.ts
CHANGED
|
@@ -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;
|
package/lib/types/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "2.
|
|
1
|
+
declare const _default: "2.10.0";
|
|
2
2
|
export default _default;
|
package/package.json
CHANGED