@constructor-io/constructorio-ui-quizzes 1.19.3 → 1.19.5

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.
@@ -6,42 +6,62 @@ const ResultCtaButton_1 = tslib_1.__importDefault(require("../ResultCtaButton/Re
6
6
  const ResultFavoritesButton_1 = tslib_1.__importDefault(require("../ResultFavoritesButton/ResultFavoritesButton"));
7
7
  const context_1 = tslib_1.__importDefault(require("../CioQuiz/context"));
8
8
  const utils_1 = require("../../utils");
9
+ const ResultCardSwatches_1 = tslib_1.__importDefault(require("../ResultCardSwatches/ResultCardSwatches"));
10
+ const useResultCard_1 = tslib_1.__importDefault(require("../../hooks/useResultCard"));
9
11
  function ResultCard(props) {
10
- const { result, salePriceKey, regularPriceKey, resultPosition, ratingCountKey, ratingScoreKey, renderResultCardPriceDetails, getResultCardImageUrl, } = props;
11
- const { customAddToFavoritesCallback, customClickItemCallback, getQuizResultButtonProps, getQuizResultLinkProps, } = (0, react_1.useContext)(context_1.default);
12
- const salePrice = (0, utils_1.validateNumberOrString)((0, utils_1.getNestedValueUsingDotNotation)(result === null || result === void 0 ? void 0 : result.data, salePriceKey));
13
- const regularPrice = (0, utils_1.validateNumberOrString)((0, utils_1.getNestedValueUsingDotNotation)(result === null || result === void 0 ? void 0 : result.data, regularPriceKey));
14
- const ratingCount = (0, utils_1.validateNumberOrString)((0, utils_1.getNestedValueUsingDotNotation)(result === null || result === void 0 ? void 0 : result.data, ratingCountKey));
15
- const ratingScore = (0, utils_1.validateNumberOrString)((0, utils_1.getNestedValueUsingDotNotation)(result === null || result === void 0 ? void 0 : result.data, ratingScoreKey));
16
- const resultCardContent = () => {
17
- var _a;
18
- return (react_1.default.createElement(react_1.default.Fragment, null,
19
- react_1.default.createElement("div", { className: 'cio-result-card-image' },
20
- react_1.default.createElement("img", { src: getResultCardImageUrl ? getResultCardImageUrl(result) : (_a = result.data) === null || _a === void 0 ? void 0 : _a.image_url, alt: 'product' })),
21
- react_1.default.createElement("div", { className: 'cio-result-card-text' },
22
- react_1.default.createElement("p", { className: 'cio-result-card-title' }, result.value),
23
- react_1.default.createElement("div", { className: 'cio-result-card-details' },
24
- react_1.default.createElement("div", { className: 'cio-result-card-rating' },
25
- !!ratingScore && (react_1.default.createElement("span", { className: 'cio-result-card-rating-score' },
26
- Array(Number(ratingScore)).fill(''),
27
- Array(5 - Number(ratingScore)).fill(''))),
28
- !!ratingCount && react_1.default.createElement("span", { className: 'cio-result-card-rating-count' },
29
- "(",
30
- ratingCount,
31
- ")")),
32
- renderResultCardPriceDetails ? (renderResultCardPriceDetails(result)) : (react_1.default.createElement("div", { className: 'cio-result-card-prices' },
33
- !!salePrice && react_1.default.createElement("span", { className: 'cio-result-card-sale-price' },
34
- "$",
35
- salePrice),
36
- !!regularPrice && (react_1.default.createElement("span", { className: `cio-result-card-regular-price${salePrice ? '--strike-through' : ''}` },
37
- "$",
38
- regularPrice))))))));
12
+ const { result, salePriceKey, regularPriceKey, resultPosition, ratingCountKey, ratingScoreKey, swatchImageKey, renderResultCardPriceDetails, getResultCardImageUrl, renderResultCard, } = props;
13
+ const { customAddToFavoritesCallback, customClickItemCallback, getQuizResultButtonProps, getAddToCartButtonProps, getAddToFavoritesButtonProps, getQuizResultLinkProps, } = (0, react_1.useContext)(context_1.default);
14
+ const { faceOutResult, getQuizResultSwatchProps } = (0, useResultCard_1.default)(result, swatchImageKey);
15
+ const { data, value } = faceOutResult || {};
16
+ const salePrice = (0, utils_1.validateNumberOrString)((0, utils_1.getNestedValueUsingDotNotation)(data, salePriceKey));
17
+ const regularPrice = (0, utils_1.validateNumberOrString)((0, utils_1.getNestedValueUsingDotNotation)(data, regularPriceKey));
18
+ const ratingCount = (0, utils_1.validateNumberOrString)((0, utils_1.getNestedValueUsingDotNotation)(data, ratingCountKey));
19
+ const ratingScore = (0, utils_1.validateNumberOrString)((0, utils_1.getNestedValueUsingDotNotation)(data, ratingScoreKey));
20
+ const resultCardContent = () => (react_1.default.createElement(react_1.default.Fragment, null,
21
+ react_1.default.createElement("div", { className: 'cio-result-card-image' },
22
+ react_1.default.createElement("img", { src: getResultCardImageUrl ? getResultCardImageUrl(faceOutResult) : data === null || data === void 0 ? void 0 : data.image_url, alt: 'product' })),
23
+ react_1.default.createElement(ResultCardSwatches_1.default, { faceOutResult: faceOutResult, getQuizResultSwatchProps: getQuizResultSwatchProps }),
24
+ react_1.default.createElement("div", { className: 'cio-result-card-text' },
25
+ react_1.default.createElement("p", { className: 'cio-result-card-title' }, value),
26
+ react_1.default.createElement("div", { className: 'cio-result-card-details' },
27
+ react_1.default.createElement("div", { className: 'cio-result-card-rating' },
28
+ !!ratingScore && (react_1.default.createElement("span", { className: 'cio-result-card-rating-score' },
29
+ Array(Number(ratingScore)).fill(''),
30
+ Array(5 - Number(ratingScore)).fill(''))),
31
+ !!ratingCount && react_1.default.createElement("span", { className: 'cio-result-card-rating-count' },
32
+ "(",
33
+ ratingCount,
34
+ ")")),
35
+ renderResultCardPriceDetails ? (renderResultCardPriceDetails(faceOutResult)) : (react_1.default.createElement("div", { className: 'cio-result-card-prices' },
36
+ !!salePrice && react_1.default.createElement("span", { className: 'cio-result-card-sale-price' },
37
+ "$",
38
+ salePrice),
39
+ !!regularPrice && (react_1.default.createElement("span", { className: `cio-result-card-regular-price${salePrice ? '--strike-through' : ''}` },
40
+ "$",
41
+ regularPrice))))))));
42
+ const resultCardContentWithoutLink = () => getQuizResultButtonProps && (react_1.default.createElement("div", Object.assign({}, getQuizResultButtonProps({
43
+ result: faceOutResult,
44
+ position: resultPosition,
45
+ type: 'button',
46
+ })), resultCardContent()));
47
+ const resultCardContentWithLink = () => getQuizResultLinkProps && (react_1.default.createElement("a", Object.assign({ className: 'cio-result-card-anchor', rel: 'noreferrer', target: '_blank' }, getQuizResultLinkProps({
48
+ result: faceOutResult,
49
+ position: resultPosition,
50
+ type: 'link',
51
+ })), resultCardContent()));
52
+ const getters = {
53
+ getQuizResultButtonProps,
54
+ getAddToCartButtonProps,
55
+ getAddToFavoritesButtonProps,
56
+ getQuizResultLinkProps,
57
+ getQuizResultSwatchProps, // The only getter function that's not from useProgGetters
39
58
  };
40
- const resultCardContentWithoutLink = () => getQuizResultButtonProps && (react_1.default.createElement("div", Object.assign({}, getQuizResultButtonProps({ result, position: resultPosition, type: 'button' })), resultCardContent()));
41
- const resultCardContentWithLink = () => getQuizResultLinkProps && (react_1.default.createElement("a", Object.assign({ className: 'cio-result-card-anchor', rel: 'noreferrer', target: '_blank' }, getQuizResultLinkProps({ result, position: resultPosition, type: 'link' })), resultCardContent()));
59
+ if (renderResultCard) {
60
+ return renderResultCard(faceOutResult, getters, resultPosition);
61
+ }
42
62
  return (react_1.default.createElement("div", { className: 'cio-result-card' },
43
- customAddToFavoritesCallback && (react_1.default.createElement(ResultFavoritesButton_1.default, { item: result, price: salePrice || regularPrice })),
63
+ customAddToFavoritesCallback && (react_1.default.createElement(ResultFavoritesButton_1.default, { item: faceOutResult, price: salePrice || regularPrice })),
44
64
  !customClickItemCallback ? resultCardContentWithLink() : resultCardContentWithoutLink(),
45
- react_1.default.createElement(ResultCtaButton_1.default, { item: result, price: salePrice || regularPrice })));
65
+ react_1.default.createElement(ResultCtaButton_1.default, { item: faceOutResult, price: salePrice || regularPrice })));
46
66
  }
47
67
  exports.default = ResultCard;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const react_1 = tslib_1.__importDefault(require("react"));
5
+ function ResultCardSwatches(props) {
6
+ var _a;
7
+ const { faceOutResult, getQuizResultSwatchProps } = props;
8
+ return (react_1.default.createElement("div", { className: 'result-card-swatches-container' }, (_a = faceOutResult === null || faceOutResult === void 0 ? void 0 : faceOutResult.variations) === null || _a === void 0 ? void 0 : _a.map((variation) => {
9
+ var _a;
10
+ const isSelected = ((_a = faceOutResult === null || faceOutResult === void 0 ? void 0 : faceOutResult.data) === null || _a === void 0 ? void 0 : _a.variation_id) === variation.data.variation_id;
11
+ return (getQuizResultSwatchProps && (react_1.default.createElement("button", Object.assign({ key: variation.data.variation_id, type: 'button' }, getQuizResultSwatchProps(variation)), isSelected && react_1.default.createElement("div", { className: 'cio-swatch-selected' }))));
12
+ })));
13
+ }
14
+ exports.default = ResultCardSwatches;
@@ -13,7 +13,7 @@ function ResultContainer(props) {
13
13
  var _a, _b, _c;
14
14
  const { resultCardOptions, onShare, resultsPageOptions } = props;
15
15
  const { state } = (0, react_1.useContext)(context_1.default);
16
- const { resultCardSalePriceKey, resultCardRegularPriceKey, resultCardRatingCountKey, resultCardRatingScoreKey, renderResultCardPriceDetails, renderResultCard, getResultCardImageUrl, } = resultCardOptions || {};
16
+ const { resultCardSalePriceKey, resultCardRegularPriceKey, resultCardRatingCountKey, resultCardRatingScoreKey, swatchImageKey, renderResultCardPriceDetails, renderResultCard, getResultCardImageUrl, } = resultCardOptions || {};
17
17
  const numberOfResults = (_c = (_b = (_a = state === null || state === void 0 ? void 0 : state.quiz.results) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.results) === null || _c === void 0 ? void 0 : _c.length;
18
18
  const resultsConfig = state === null || state === void 0 ? void 0 : state.quiz.resultsConfig;
19
19
  const zeroResults = !numberOfResults;
@@ -21,7 +21,7 @@ function ResultContainer(props) {
21
21
  return (react_1.default.createElement("div", { className: 'cio-results-container' },
22
22
  !zeroResults && react_1.default.createElement(ResultsHeaderContainer_1.default, { resultsConfig: resultsConfig }),
23
23
  !zeroResults && (react_1.default.createElement(ResultFiltersAndShare_1.default, { numberOfResults: numberOfResults, onShare: onShare, showShareButton: !!(resultsPageOptions === null || resultsPageOptions === void 0 ? void 0 : resultsPageOptions.showShareResultsButton) })),
24
- !zeroResults && (react_1.default.createElement(Results_1.default, { resultCardSalePriceKey: resultCardSalePriceKey, resultCardRegularPriceKey: resultCardRegularPriceKey, resultCardRatingCountKey: resultCardRatingCountKey, resultCardRatingScoreKey: resultCardRatingScoreKey, renderResultCardPriceDetails: renderResultCardPriceDetails, renderResultCard: renderResultCard, getResultCardImageUrl: getResultCardImageUrl })),
24
+ !zeroResults && (react_1.default.createElement(Results_1.default, { resultCardSalePriceKey: resultCardSalePriceKey, resultCardRegularPriceKey: resultCardRegularPriceKey, resultCardRatingCountKey: resultCardRatingCountKey, resultCardRatingScoreKey: resultCardRatingScoreKey, swatchImageKey: swatchImageKey, renderResultCardPriceDetails: renderResultCardPriceDetails, renderResultCard: renderResultCard, getResultCardImageUrl: getResultCardImageUrl })),
25
25
  zeroResults && react_1.default.createElement(ZeroResults_1.default, null),
26
26
  !zeroResults && (react_1.default.createElement("div", { className: 'cio-redo-button-container' },
27
27
  react_1.default.createElement(RedoButton_1.default, null)))));
@@ -6,12 +6,11 @@ const context_1 = tslib_1.__importDefault(require("../CioQuiz/context"));
6
6
  const ResultCard_1 = tslib_1.__importDefault(require("../ResultCard/ResultCard"));
7
7
  function Results(props) {
8
8
  var _a, _b, _c, _d;
9
- const { resultCardSalePriceKey, resultCardRegularPriceKey, resultCardRatingCountKey, resultCardRatingScoreKey, renderResultCardPriceDetails, renderResultCard, getResultCardImageUrl, } = props;
10
- const { state, getAddToCartButtonProps, getAddToFavoritesButtonProps, getQuizResultLinkProps } = (0, react_1.useContext)(context_1.default);
11
- const getters = { getAddToCartButtonProps, getAddToFavoritesButtonProps, getQuizResultLinkProps };
9
+ const { resultCardSalePriceKey, resultCardRegularPriceKey, resultCardRatingCountKey, resultCardRatingScoreKey, swatchImageKey, renderResultCardPriceDetails, renderResultCard, getResultCardImageUrl, } = props;
10
+ const { state } = (0, react_1.useContext)(context_1.default);
12
11
  return (react_1.default.createElement("div", { className: 'cio-results' }, (_d = (_c = (_b = (_a = state === null || state === void 0 ? void 0 : state.quiz) === null || _a === void 0 ? void 0 : _a.results) === null || _b === void 0 ? void 0 : _b.response) === null || _c === void 0 ? void 0 : _c.results) === null || _d === void 0 ? void 0 : _d.map((result, index) => {
13
12
  var _a;
14
- return renderResultCard ? (renderResultCard(result, getters, index)) : (react_1.default.createElement(ResultCard_1.default, { result: result, key: (_a = result.data) === null || _a === void 0 ? void 0 : _a.id, salePriceKey: resultCardSalePriceKey, regularPriceKey: resultCardRegularPriceKey, ratingCountKey: resultCardRatingCountKey, ratingScoreKey: resultCardRatingScoreKey, renderResultCardPriceDetails: renderResultCardPriceDetails, getResultCardImageUrl: getResultCardImageUrl, resultPosition: index + 1 }));
13
+ return (react_1.default.createElement(ResultCard_1.default, { result: result, key: (_a = result.data) === null || _a === void 0 ? void 0 : _a.id, salePriceKey: resultCardSalePriceKey, regularPriceKey: resultCardRegularPriceKey, ratingCountKey: resultCardRatingCountKey, ratingScoreKey: resultCardRatingScoreKey, swatchImageKey: swatchImageKey, renderResultCardPriceDetails: renderResultCardPriceDetails, getResultCardImageUrl: getResultCardImageUrl, resultPosition: index + 1, renderResultCard: renderResultCard }));
15
14
  })));
16
15
  }
17
16
  exports.default = Results;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const react_1 = require("react");
4
+ const utils_1 = require("../utils");
5
+ const useResultCard = (result, swatchImageKey) => {
6
+ var _a;
7
+ if (!result) {
8
+ throw new Error('The "result" parameter is required and cannot be undefined.');
9
+ }
10
+ const [faceOutResult, setFaceOutResult] = (0, react_1.useState)(result);
11
+ const onVariationClick = (0, react_1.useCallback)((variation) => {
12
+ setFaceOutResult(Object.assign(Object.assign({}, result), variation));
13
+ // eslint-disable-next-line react-hooks/exhaustive-deps
14
+ }, []);
15
+ // The only prop getter that is not returned from useProgGetters
16
+ // It's state and needs to be local to the component
17
+ const getQuizResultSwatchProps = (0, react_1.useCallback)((variation) => {
18
+ var _a, _b, _c, _d;
19
+ const isSelected = ((_a = variation === null || variation === void 0 ? void 0 : variation.data) === null || _a === void 0 ? void 0 : _a.variation_id) === ((_b = faceOutResult === null || faceOutResult === void 0 ? void 0 : faceOutResult.data) === null || _b === void 0 ? void 0 : _b.variation_id);
20
+ const style = {
21
+ background: `url(${(0, utils_1.validateNumberOrString)((0, utils_1.getNestedValueUsingDotNotation)(variation, swatchImageKey)) ||
22
+ ((_c = variation === null || variation === void 0 ? void 0 : variation.data) === null || _c === void 0 ? void 0 : _c.image_url)})`,
23
+ backgroundSize: 'contain',
24
+ backgroundPosition: 'center',
25
+ backgroundRepeat: 'no-repeat',
26
+ };
27
+ const onClick = (e) => {
28
+ e.stopPropagation();
29
+ onVariationClick(variation);
30
+ };
31
+ return {
32
+ key: (_d = variation === null || variation === void 0 ? void 0 : variation.data) === null || _d === void 0 ? void 0 : _d.variation_id,
33
+ className: `cio-result-card-swatch ${isSelected ? 'selected' : ''}`,
34
+ type: 'button',
35
+ onClick,
36
+ style,
37
+ };
38
+ }, [(_a = faceOutResult === null || faceOutResult === void 0 ? void 0 : faceOutResult.data) === null || _a === void 0 ? void 0 : _a.variation_id, onVariationClick, swatchImageKey]);
39
+ return {
40
+ faceOutResult,
41
+ onVariationClick,
42
+ getQuizResultSwatchProps,
43
+ };
44
+ };
45
+ exports.default = useResultCard;
package/lib/cjs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ResultHeroCard = exports.ResultFiltersAndShare = exports.ResultContainer = exports.ResultCard = exports.Results = exports.SelectQuestion = exports.CoverQuestion = exports.OpenTextQuestion = exports.QuizQuestions = exports.useShareResultsLink = exports.useCioQuiz = void 0;
3
+ exports.ResultHeroCard = exports.ResultFiltersAndShare = exports.ResultContainer = exports.ResultCard = exports.Results = exports.SelectQuestion = exports.CoverQuestion = exports.OpenTextQuestion = exports.QuizQuestions = exports.useResultCard = exports.useShareResultsLink = exports.useCioQuiz = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const CioQuiz_1 = tslib_1.__importDefault(require("./components/CioQuiz"));
6
6
  // Hook
@@ -8,6 +8,8 @@ var useQuiz_1 = require("./hooks/useQuiz");
8
8
  Object.defineProperty(exports, "useCioQuiz", { enumerable: true, get: function () { return tslib_1.__importDefault(useQuiz_1).default; } });
9
9
  var useShareResultsLink_1 = require("./hooks/useShareResultsLink");
10
10
  Object.defineProperty(exports, "useShareResultsLink", { enumerable: true, get: function () { return tslib_1.__importDefault(useShareResultsLink_1).default; } });
11
+ var useResultCard_1 = require("./hooks/useResultCard");
12
+ Object.defineProperty(exports, "useResultCard", { enumerable: true, get: function () { return tslib_1.__importDefault(useResultCard_1).default; } });
11
13
  // Questions Components
12
14
  var index_1 = require("./components/QuizQuestions/index");
13
15
  Object.defineProperty(exports, "QuizQuestions", { enumerable: true, get: function () { return tslib_1.__importDefault(index_1).default; } });
@@ -59,7 +59,7 @@ const trackQuizResultClick = (cioClient, quizResults, result, position) => {
59
59
  quizSessionId: quiz_session_id,
60
60
  itemId: (_a = result.data) === null || _a === void 0 ? void 0 : _a.id,
61
61
  itemName: result === null || result === void 0 ? void 0 : result.value,
62
- variationId: (_b = result.data) === null || _b === void 0 ? void 0 : _b.variation_id,
62
+ variationId: (_b = result === null || result === void 0 ? void 0 : result.data) === null || _b === void 0 ? void 0 : _b.variation_id,
63
63
  section,
64
64
  resultCount: total_num_results,
65
65
  resultPage: page,
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = '1.19.3';
3
+ exports.default = '1.19.5';
@@ -3,18 +3,23 @@ import ResultCtaButton from '../ResultCtaButton/ResultCtaButton';
3
3
  import ResultFavoritesButton from '../ResultFavoritesButton/ResultFavoritesButton';
4
4
  import QuizContext from '../CioQuiz/context';
5
5
  import { getNestedValueUsingDotNotation, validateNumberOrString } from '../../utils';
6
+ import ResultCardSwatches from '../ResultCardSwatches/ResultCardSwatches';
7
+ import useResultCard from '../../hooks/useResultCard';
6
8
  export default function ResultCard(props) {
7
- const { result, salePriceKey, regularPriceKey, resultPosition, ratingCountKey, ratingScoreKey, renderResultCardPriceDetails, getResultCardImageUrl, } = props;
8
- const { customAddToFavoritesCallback, customClickItemCallback, getQuizResultButtonProps, getQuizResultLinkProps, } = useContext(QuizContext);
9
- const salePrice = validateNumberOrString(getNestedValueUsingDotNotation(result?.data, salePriceKey));
10
- const regularPrice = validateNumberOrString(getNestedValueUsingDotNotation(result?.data, regularPriceKey));
11
- const ratingCount = validateNumberOrString(getNestedValueUsingDotNotation(result?.data, ratingCountKey));
12
- const ratingScore = validateNumberOrString(getNestedValueUsingDotNotation(result?.data, ratingScoreKey));
9
+ const { result, salePriceKey, regularPriceKey, resultPosition, ratingCountKey, ratingScoreKey, swatchImageKey, renderResultCardPriceDetails, getResultCardImageUrl, renderResultCard, } = props;
10
+ const { customAddToFavoritesCallback, customClickItemCallback, getQuizResultButtonProps, getAddToCartButtonProps, getAddToFavoritesButtonProps, getQuizResultLinkProps, } = useContext(QuizContext);
11
+ const { faceOutResult, getQuizResultSwatchProps } = useResultCard(result, swatchImageKey);
12
+ const { data, value } = faceOutResult || {};
13
+ const salePrice = validateNumberOrString(getNestedValueUsingDotNotation(data, salePriceKey));
14
+ const regularPrice = validateNumberOrString(getNestedValueUsingDotNotation(data, regularPriceKey));
15
+ const ratingCount = validateNumberOrString(getNestedValueUsingDotNotation(data, ratingCountKey));
16
+ const ratingScore = validateNumberOrString(getNestedValueUsingDotNotation(data, ratingScoreKey));
13
17
  const resultCardContent = () => (React.createElement(React.Fragment, null,
14
18
  React.createElement("div", { className: 'cio-result-card-image' },
15
- React.createElement("img", { src: getResultCardImageUrl ? getResultCardImageUrl(result) : result.data?.image_url, alt: 'product' })),
19
+ React.createElement("img", { src: getResultCardImageUrl ? getResultCardImageUrl(faceOutResult) : data?.image_url, alt: 'product' })),
20
+ React.createElement(ResultCardSwatches, { faceOutResult: faceOutResult, getQuizResultSwatchProps: getQuizResultSwatchProps }),
16
21
  React.createElement("div", { className: 'cio-result-card-text' },
17
- React.createElement("p", { className: 'cio-result-card-title' }, result.value),
22
+ React.createElement("p", { className: 'cio-result-card-title' }, value),
18
23
  React.createElement("div", { className: 'cio-result-card-details' },
19
24
  React.createElement("div", { className: 'cio-result-card-rating' },
20
25
  !!ratingScore && (React.createElement("span", { className: 'cio-result-card-rating-score' },
@@ -24,17 +29,35 @@ export default function ResultCard(props) {
24
29
  "(",
25
30
  ratingCount,
26
31
  ")")),
27
- renderResultCardPriceDetails ? (renderResultCardPriceDetails(result)) : (React.createElement("div", { className: 'cio-result-card-prices' },
32
+ renderResultCardPriceDetails ? (renderResultCardPriceDetails(faceOutResult)) : (React.createElement("div", { className: 'cio-result-card-prices' },
28
33
  !!salePrice && React.createElement("span", { className: 'cio-result-card-sale-price' },
29
34
  "$",
30
35
  salePrice),
31
36
  !!regularPrice && (React.createElement("span", { className: `cio-result-card-regular-price${salePrice ? '--strike-through' : ''}` },
32
37
  "$",
33
38
  regularPrice))))))));
34
- const resultCardContentWithoutLink = () => getQuizResultButtonProps && (React.createElement("div", { ...getQuizResultButtonProps({ result, position: resultPosition, type: 'button' }) }, resultCardContent()));
35
- const resultCardContentWithLink = () => getQuizResultLinkProps && (React.createElement("a", { className: 'cio-result-card-anchor', rel: 'noreferrer', target: '_blank', ...getQuizResultLinkProps({ result, position: resultPosition, type: 'link' }) }, resultCardContent()));
39
+ const resultCardContentWithoutLink = () => getQuizResultButtonProps && (React.createElement("div", { ...getQuizResultButtonProps({
40
+ result: faceOutResult,
41
+ position: resultPosition,
42
+ type: 'button',
43
+ }) }, resultCardContent()));
44
+ const resultCardContentWithLink = () => getQuizResultLinkProps && (React.createElement("a", { className: 'cio-result-card-anchor', rel: 'noreferrer', target: '_blank', ...getQuizResultLinkProps({
45
+ result: faceOutResult,
46
+ position: resultPosition,
47
+ type: 'link',
48
+ }) }, resultCardContent()));
49
+ const getters = {
50
+ getQuizResultButtonProps,
51
+ getAddToCartButtonProps,
52
+ getAddToFavoritesButtonProps,
53
+ getQuizResultLinkProps,
54
+ getQuizResultSwatchProps, // The only getter function that's not from useProgGetters
55
+ };
56
+ if (renderResultCard) {
57
+ return renderResultCard(faceOutResult, getters, resultPosition);
58
+ }
36
59
  return (React.createElement("div", { className: 'cio-result-card' },
37
- customAddToFavoritesCallback && (React.createElement(ResultFavoritesButton, { item: result, price: salePrice || regularPrice })),
60
+ customAddToFavoritesCallback && (React.createElement(ResultFavoritesButton, { item: faceOutResult, price: salePrice || regularPrice })),
38
61
  !customClickItemCallback ? resultCardContentWithLink() : resultCardContentWithoutLink(),
39
- React.createElement(ResultCtaButton, { item: result, price: salePrice || regularPrice })));
62
+ React.createElement(ResultCtaButton, { item: faceOutResult, price: salePrice || regularPrice })));
40
63
  }
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export default function ResultCardSwatches(props) {
3
+ const { faceOutResult, getQuizResultSwatchProps } = props;
4
+ return (React.createElement("div", { className: 'result-card-swatches-container' }, faceOutResult?.variations?.map((variation) => {
5
+ const isSelected = faceOutResult?.data?.variation_id === variation.data.variation_id;
6
+ return (getQuizResultSwatchProps && (React.createElement("button", { key: variation.data.variation_id, type: 'button', ...getQuizResultSwatchProps(variation) }, isSelected && React.createElement("div", { className: 'cio-swatch-selected' }))));
7
+ })));
8
+ }
@@ -9,7 +9,7 @@ import RedoButton from '../RedoButton/RedoButton';
9
9
  export default function ResultContainer(props) {
10
10
  const { resultCardOptions, onShare, resultsPageOptions } = props;
11
11
  const { state } = useContext(QuizContext);
12
- const { resultCardSalePriceKey, resultCardRegularPriceKey, resultCardRatingCountKey, resultCardRatingScoreKey, renderResultCardPriceDetails, renderResultCard, getResultCardImageUrl, } = resultCardOptions || {};
12
+ const { resultCardSalePriceKey, resultCardRegularPriceKey, resultCardRatingCountKey, resultCardRatingScoreKey, swatchImageKey, renderResultCardPriceDetails, renderResultCard, getResultCardImageUrl, } = resultCardOptions || {};
13
13
  const numberOfResults = state?.quiz.results?.response?.results?.length;
14
14
  const resultsConfig = state?.quiz.resultsConfig;
15
15
  const zeroResults = !numberOfResults;
@@ -17,7 +17,7 @@ export default function ResultContainer(props) {
17
17
  return (React.createElement("div", { className: 'cio-results-container' },
18
18
  !zeroResults && React.createElement(ResultsHeaderContainer, { resultsConfig: resultsConfig }),
19
19
  !zeroResults && (React.createElement(ResultFiltersAndShare, { numberOfResults: numberOfResults, onShare: onShare, showShareButton: !!resultsPageOptions?.showShareResultsButton })),
20
- !zeroResults && (React.createElement(Results, { resultCardSalePriceKey: resultCardSalePriceKey, resultCardRegularPriceKey: resultCardRegularPriceKey, resultCardRatingCountKey: resultCardRatingCountKey, resultCardRatingScoreKey: resultCardRatingScoreKey, renderResultCardPriceDetails: renderResultCardPriceDetails, renderResultCard: renderResultCard, getResultCardImageUrl: getResultCardImageUrl })),
20
+ !zeroResults && (React.createElement(Results, { resultCardSalePriceKey: resultCardSalePriceKey, resultCardRegularPriceKey: resultCardRegularPriceKey, resultCardRatingCountKey: resultCardRatingCountKey, resultCardRatingScoreKey: resultCardRatingScoreKey, swatchImageKey: swatchImageKey, renderResultCardPriceDetails: renderResultCardPriceDetails, renderResultCard: renderResultCard, getResultCardImageUrl: getResultCardImageUrl })),
21
21
  zeroResults && React.createElement(ZeroResults, null),
22
22
  !zeroResults && (React.createElement("div", { className: 'cio-redo-button-container' },
23
23
  React.createElement(RedoButton, null)))));
@@ -2,9 +2,8 @@ import React, { useContext } from 'react';
2
2
  import QuizContext from '../CioQuiz/context';
3
3
  import ResultCard from '../ResultCard/ResultCard';
4
4
  function Results(props) {
5
- const { resultCardSalePriceKey, resultCardRegularPriceKey, resultCardRatingCountKey, resultCardRatingScoreKey, renderResultCardPriceDetails, renderResultCard, getResultCardImageUrl, } = props;
6
- const { state, getAddToCartButtonProps, getAddToFavoritesButtonProps, getQuizResultLinkProps } = useContext(QuizContext);
7
- const getters = { getAddToCartButtonProps, getAddToFavoritesButtonProps, getQuizResultLinkProps };
8
- return (React.createElement("div", { className: 'cio-results' }, state?.quiz?.results?.response?.results?.map((result, index) => renderResultCard ? (renderResultCard(result, getters, index)) : (React.createElement(ResultCard, { result: result, key: result.data?.id, salePriceKey: resultCardSalePriceKey, regularPriceKey: resultCardRegularPriceKey, ratingCountKey: resultCardRatingCountKey, ratingScoreKey: resultCardRatingScoreKey, renderResultCardPriceDetails: renderResultCardPriceDetails, getResultCardImageUrl: getResultCardImageUrl, resultPosition: index + 1 })))));
5
+ const { resultCardSalePriceKey, resultCardRegularPriceKey, resultCardRatingCountKey, resultCardRatingScoreKey, swatchImageKey, renderResultCardPriceDetails, renderResultCard, getResultCardImageUrl, } = props;
6
+ const { state } = useContext(QuizContext);
7
+ return (React.createElement("div", { className: 'cio-results' }, state?.quiz?.results?.response?.results?.map((result, index) => (React.createElement(ResultCard, { result: result, key: result.data?.id, salePriceKey: resultCardSalePriceKey, regularPriceKey: resultCardRegularPriceKey, ratingCountKey: resultCardRatingCountKey, ratingScoreKey: resultCardRatingScoreKey, swatchImageKey: swatchImageKey, renderResultCardPriceDetails: renderResultCardPriceDetails, getResultCardImageUrl: getResultCardImageUrl, resultPosition: index + 1, renderResultCard: renderResultCard })))));
9
8
  }
10
9
  export default Results;
@@ -0,0 +1,44 @@
1
+ import { useCallback, useState } from 'react';
2
+ import { getNestedValueUsingDotNotation, validateNumberOrString } from '../utils';
3
+ const useResultCard = (result, swatchImageKey) => {
4
+ if (!result) {
5
+ throw new Error('The "result" parameter is required and cannot be undefined.');
6
+ }
7
+ const [faceOutResult, setFaceOutResult] = useState(result);
8
+ const onVariationClick = useCallback((variation) => {
9
+ setFaceOutResult({
10
+ ...result,
11
+ ...variation,
12
+ });
13
+ // eslint-disable-next-line react-hooks/exhaustive-deps
14
+ }, []);
15
+ // The only prop getter that is not returned from useProgGetters
16
+ // It's state and needs to be local to the component
17
+ const getQuizResultSwatchProps = useCallback((variation) => {
18
+ const isSelected = variation?.data?.variation_id === faceOutResult?.data?.variation_id;
19
+ const style = {
20
+ background: `url(${validateNumberOrString(getNestedValueUsingDotNotation(variation, swatchImageKey)) ||
21
+ variation?.data?.image_url})`,
22
+ backgroundSize: 'contain',
23
+ backgroundPosition: 'center',
24
+ backgroundRepeat: 'no-repeat',
25
+ };
26
+ const onClick = (e) => {
27
+ e.stopPropagation();
28
+ onVariationClick(variation);
29
+ };
30
+ return {
31
+ key: variation?.data?.variation_id,
32
+ className: `cio-result-card-swatch ${isSelected ? 'selected' : ''}`,
33
+ type: 'button',
34
+ onClick,
35
+ style,
36
+ };
37
+ }, [faceOutResult?.data?.variation_id, onVariationClick, swatchImageKey]);
38
+ return {
39
+ faceOutResult,
40
+ onVariationClick,
41
+ getQuizResultSwatchProps,
42
+ };
43
+ };
44
+ export default useResultCard;
package/lib/mjs/index.js CHANGED
@@ -2,6 +2,7 @@ import CioQuiz from './components/CioQuiz';
2
2
  // Hook
3
3
  export { default as useCioQuiz } from './hooks/useQuiz';
4
4
  export { default as useShareResultsLink } from './hooks/useShareResultsLink';
5
+ export { default as useResultCard } from './hooks/useResultCard';
5
6
  // Questions Components
6
7
  export { default as QuizQuestions } from './components/QuizQuestions/index';
7
8
  export { default as OpenTextQuestion } from './components/OpenTextTypeQuestion/OpenTextTypeQuestion';
@@ -44,7 +44,7 @@ export const trackQuizResultClick = (cioClient, quizResults, result, position) =
44
44
  quizSessionId: quiz_session_id,
45
45
  itemId: result.data?.id,
46
46
  itemName: result?.value,
47
- variationId: result.data?.variation_id,
47
+ variationId: result?.data?.variation_id,
48
48
  section,
49
49
  resultCount: total_num_results,
50
50
  resultPage: page,
@@ -1 +1 @@
1
- export default '1.19.3';
1
+ export default '1.19.5';
package/lib/styles.css CHANGED
@@ -1135,3 +1135,35 @@
1135
1135
  display: flex;
1136
1136
  justify-content: center;
1137
1137
  }
1138
+
1139
+ .cio-quiz .cio-result-card-swatch {
1140
+ background: none;
1141
+ color: inherit;
1142
+ border: none;
1143
+ padding: 0;
1144
+ font: inherit;
1145
+ cursor: pointer;
1146
+ width: 25px;
1147
+ height: 25px;
1148
+ outline: 1px black solid;
1149
+ border-radius: 50%;
1150
+ }
1151
+
1152
+ .cio-quiz .cio-swatch-selected {
1153
+ width: 100%;
1154
+ height: 100%;
1155
+ border-radius: 50%;
1156
+ outline-offset: 4px;
1157
+ z-index: 1000;
1158
+ filter: opacity(0.6);
1159
+ outline: 3px solid black;
1160
+ }
1161
+ .cio-quiz .result-card-swatches-container {
1162
+ display: flex;
1163
+ flex-wrap: wrap;
1164
+ padding: 0;
1165
+ gap: 10px;
1166
+ cursor: default;
1167
+ margin-bottom: 14px;
1168
+ }
1169
+
@@ -1,14 +1,16 @@
1
1
  /// <reference types="react" />
2
- import { QuizResultDataPartial } from '../../types';
3
- interface ResultCardOptions {
2
+ import { QuizResultDataPartial, RenderResultCard } from '../../types';
3
+ interface ResultCardProps {
4
4
  result: QuizResultDataPartial;
5
5
  salePriceKey?: string;
6
6
  regularPriceKey?: string;
7
7
  ratingCountKey?: string;
8
8
  ratingScoreKey?: string;
9
+ swatchImageKey?: string;
9
10
  resultPosition: number;
10
11
  renderResultCardPriceDetails?: (result: QuizResultDataPartial) => JSX.Element;
11
12
  getResultCardImageUrl?: (result: QuizResultDataPartial) => string;
13
+ renderResultCard?: RenderResultCard;
12
14
  }
13
- export default function ResultCard(props: ResultCardOptions): JSX.Element;
15
+ export default function ResultCard(props: ResultCardProps): JSX.Element;
14
16
  export {};
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { GetQuizResultSwatchProps, QuizResultDataPartial } from '../../types';
3
+ interface ResultCardSwatchesOptions {
4
+ faceOutResult: QuizResultDataPartial;
5
+ getQuizResultSwatchProps?: GetQuizResultSwatchProps;
6
+ }
7
+ export default function ResultCardSwatches(props: ResultCardSwatchesOptions): JSX.Element;
8
+ export {};
@@ -0,0 +1,7 @@
1
+ import { GetQuizResultSwatchProps, QuizResultDataPartial } from '../types';
2
+ declare const useResultCard: (result: QuizResultDataPartial, swatchImageKey?: string) => {
3
+ faceOutResult: Partial<import("@constructor-io/constructorio-client-javascript").QuizResultData>;
4
+ onVariationClick: (variation: QuizResultDataPartial) => void;
5
+ getQuizResultSwatchProps: GetQuizResultSwatchProps;
6
+ };
7
+ export default useResultCard;
@@ -1,6 +1,7 @@
1
1
  import CioQuiz from './components/CioQuiz';
2
2
  export { default as useCioQuiz } from './hooks/useQuiz';
3
3
  export { default as useShareResultsLink } from './hooks/useShareResultsLink';
4
+ export { default as useResultCard } from './hooks/useResultCard';
4
5
  export { default as QuizQuestions } from './components/QuizQuestions/index';
5
6
  export { default as OpenTextQuestion } from './components/OpenTextTypeQuestion/OpenTextTypeQuestion';
6
7
  export { default as CoverQuestion } from './components/CoverTypeQuestion/CoverTypeQuestion';
@@ -12,17 +12,21 @@ export type QuizEmailResults = {
12
12
  url: string;
13
13
  results?: Partial<QuizResultData>[];
14
14
  };
15
+ export type RenderResultCard = (result: QuizResultDataPartial, getters: {
16
+ getAddToCartButtonProps?: GetAddToCartButtonProps;
17
+ getAddToFavoritesButtonProps?: GetAddToFavoritesButtonProps;
18
+ getQuizResultLinkProps?: GetQuizResultLinkProps;
19
+ getQuizResultButtonProps?: GetQuizResultButtonProps;
20
+ getQuizResultSwatchProps?: GetQuizResultSwatchProps;
21
+ }, resultPosition: number) => JSX.Element;
15
22
  export interface ResultCardOptions {
16
23
  resultCardSalePriceKey?: string;
17
24
  resultCardRegularPriceKey?: string;
18
25
  resultCardRatingCountKey?: string;
19
26
  resultCardRatingScoreKey?: string;
27
+ swatchImageKey?: string;
20
28
  renderResultCardPriceDetails?: (result: QuizResultDataPartial) => JSX.Element;
21
- renderResultCard?: (result: QuizResultDataPartial, getters: {
22
- getAddToCartButtonProps?: GetAddToCartButtonProps;
23
- getAddToFavoritesButtonProps?: GetAddToFavoritesButtonProps;
24
- getQuizResultLinkProps?: GetQuizResultLinkProps;
25
- }, index: number) => JSX.Element;
29
+ renderResultCard?: RenderResultCard;
26
30
  getResultCardImageUrl?: (result: QuizResultDataPartial) => string;
27
31
  }
28
32
  export declare namespace QuizResultsEventsProps {
@@ -248,6 +252,7 @@ export type GetAddToCartButtonProps = (result: QuizResultDataPartial, price?: nu
248
252
  export type GetAddToFavoritesButtonProps = (result: QuizResultDataPartial, price?: number | string, clickHandler?: () => void) => AddToCartButtonProps;
249
253
  export type GetQuizImageProps = () => QuizImageProps;
250
254
  export type GetSelectQuestionImageProps = (option: QuestionOption) => QuizImageProps;
255
+ export type GetQuizResultSwatchProps = (variation: QuizResultDataPartial) => React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>;
251
256
  export interface QuizResultOptions<T = 'button' | 'link'> {
252
257
  result: QuizResultDataPartial;
253
258
  position: number;
@@ -1,2 +1,2 @@
1
- declare const _default: "1.19.3";
1
+ declare const _default: "1.19.5";
2
2
  export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructor-io/constructorio-ui-quizzes",
3
- "version": "1.19.3",
3
+ "version": "1.19.5",
4
4
  "description": "Constructor.io Quizzes UI library for web applications",
5
5
  "author": "Constructor.io Corporation",
6
6
  "license": "MIT",