@constructor-io/constructorio-ui-quizzes 1.3.11 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/dist/constructorio-ui-quizzes-bundled.js +20 -20
  2. package/lib/cjs/components/BackButton/BackButton.js +12 -7
  3. package/lib/cjs/components/CTAButton/CTAButton.js +4 -3
  4. package/lib/cjs/components/CioQuiz/actions.js +1 -0
  5. package/lib/cjs/components/CioQuiz/index.js +16 -9
  6. package/lib/cjs/components/CioQuiz/quizApiReducer.js +15 -9
  7. package/lib/cjs/components/CioQuiz/quizLocalReducer.js +36 -8
  8. package/lib/cjs/components/ControlBar/ControlBar.js +6 -4
  9. package/lib/cjs/components/CoverTypeQuestion/CoverTypeQuestion.js +2 -7
  10. package/lib/cjs/components/OpenTextTypeQuestion/OpenTextTypeQuestion.js +4 -32
  11. package/lib/cjs/components/RedoButton/RedoButton.js +11 -4
  12. package/lib/cjs/components/ResultCard/ResultCard.js +3 -18
  13. package/lib/cjs/components/ResultContainer/ResultContainer.js +2 -2
  14. package/lib/cjs/components/ResultCtaButton/ResultCtaButton.js +8 -7
  15. package/lib/cjs/components/ResultHeroCard/ResultHeroCard.js +36 -0
  16. package/lib/cjs/components/SelectTypeQuestion/SelectTypeQuestion.js +6 -56
  17. package/lib/cjs/components/SessionPromptModal/SessionPromptModal.js +18 -6
  18. package/lib/cjs/components/ZeroResults/ZeroResults.js +5 -4
  19. package/lib/cjs/constants.js +40 -5
  20. package/lib/cjs/hooks/useConsoleErrors.js +2 -1
  21. package/lib/cjs/hooks/usePropsGetters/index.js +85 -0
  22. package/lib/cjs/hooks/usePropsGetters/useCoverQuestionProps.js +13 -0
  23. package/lib/cjs/hooks/usePropsGetters/useNextQuestionButtonProps.js +24 -0
  24. package/lib/cjs/hooks/usePropsGetters/useOpenTextInputProps.js +47 -0
  25. package/lib/cjs/hooks/usePropsGetters/usePreviousQuestionButtonProps.js +18 -0
  26. package/lib/cjs/hooks/usePropsGetters/useSelectInputProps.js +84 -0
  27. package/lib/cjs/hooks/useQuiz.js +14 -28
  28. package/lib/cjs/hooks/useQuizEvents/index.js +21 -16
  29. package/lib/cjs/hooks/useQuizEvents/useHydrateQuizLocalState.js +18 -0
  30. package/lib/cjs/hooks/useQuizEvents/useQuizAddToCart.js +2 -2
  31. package/lib/cjs/hooks/useQuizEvents/useQuizAnswerChangeHandler.js +48 -0
  32. package/lib/cjs/hooks/useQuizEvents/useQuizBackClick.js +5 -5
  33. package/lib/cjs/hooks/useQuizEvents/useQuizNextClick.js +13 -39
  34. package/lib/cjs/hooks/useQuizEvents/useQuizResetClick.js +20 -0
  35. package/lib/cjs/hooks/useQuizEvents/useQuizResultClick.js +2 -2
  36. package/lib/cjs/hooks/useQuizState/index.js +21 -0
  37. package/lib/cjs/hooks/{useQuizApiState.js → useQuizState/useQuizApiState.js} +15 -29
  38. package/lib/cjs/hooks/useQuizState/useQuizLocalState.js +30 -0
  39. package/lib/cjs/index.js +25 -0
  40. package/lib/cjs/services/index.js +3 -3
  41. package/lib/cjs/stories/Quiz/tests/mocks.js +69 -14
  42. package/lib/cjs/utils.js +23 -1
  43. package/lib/mjs/components/BackButton/BackButton.js +12 -7
  44. package/lib/mjs/components/CTAButton/CTAButton.js +4 -3
  45. package/lib/mjs/components/CioQuiz/actions.js +1 -0
  46. package/lib/mjs/components/CioQuiz/index.js +16 -9
  47. package/lib/mjs/components/CioQuiz/quizApiReducer.js +19 -7
  48. package/lib/mjs/components/CioQuiz/quizLocalReducer.js +36 -7
  49. package/lib/mjs/components/ControlBar/ControlBar.js +6 -4
  50. package/lib/mjs/components/CoverTypeQuestion/CoverTypeQuestion.js +2 -7
  51. package/lib/mjs/components/OpenTextTypeQuestion/OpenTextTypeQuestion.js +5 -32
  52. package/lib/mjs/components/RedoButton/RedoButton.js +11 -4
  53. package/lib/mjs/components/ResultCard/ResultCard.js +3 -15
  54. package/lib/mjs/components/ResultContainer/ResultContainer.js +2 -2
  55. package/lib/mjs/components/ResultCtaButton/ResultCtaButton.js +8 -7
  56. package/lib/mjs/components/ResultHeroCard/ResultHeroCard.js +31 -0
  57. package/lib/mjs/components/SelectTypeQuestion/SelectTypeQuestion.js +6 -55
  58. package/lib/mjs/components/SessionPromptModal/SessionPromptModal.js +18 -6
  59. package/lib/mjs/components/ZeroResults/ZeroResults.js +5 -4
  60. package/lib/mjs/constants.js +39 -4
  61. package/lib/mjs/hooks/useConsoleErrors.js +2 -1
  62. package/lib/mjs/hooks/usePropsGetters/index.js +72 -0
  63. package/lib/mjs/hooks/usePropsGetters/useCoverQuestionProps.js +10 -0
  64. package/lib/mjs/hooks/usePropsGetters/useNextQuestionButtonProps.js +20 -0
  65. package/lib/mjs/hooks/usePropsGetters/useOpenTextInputProps.js +43 -0
  66. package/lib/mjs/hooks/usePropsGetters/usePreviousQuestionButtonProps.js +14 -0
  67. package/lib/mjs/hooks/usePropsGetters/useSelectInputProps.js +79 -0
  68. package/lib/mjs/hooks/useQuiz.js +13 -21
  69. package/lib/mjs/hooks/useQuizEvents/index.js +21 -16
  70. package/lib/mjs/hooks/useQuizEvents/useHydrateQuizLocalState.js +16 -0
  71. package/lib/mjs/hooks/useQuizEvents/useQuizAddToCart.js +2 -2
  72. package/lib/mjs/hooks/useQuizEvents/useQuizAnswerChangeHandler.js +45 -0
  73. package/lib/mjs/hooks/useQuizEvents/useQuizBackClick.js +5 -5
  74. package/lib/mjs/hooks/useQuizEvents/useQuizNextClick.js +12 -38
  75. package/lib/mjs/hooks/useQuizEvents/useQuizResetClick.js +18 -0
  76. package/lib/mjs/hooks/useQuizEvents/useQuizResultClick.js +2 -2
  77. package/lib/mjs/hooks/useQuizState/index.js +18 -0
  78. package/lib/mjs/hooks/{useQuizApiState.js → useQuizState/useQuizApiState.js} +15 -28
  79. package/lib/mjs/hooks/useQuizState/useQuizLocalState.js +26 -0
  80. package/lib/mjs/index.js +14 -0
  81. package/lib/mjs/services/index.js +1 -1
  82. package/lib/mjs/stories/Quiz/tests/mocks.js +75 -12
  83. package/lib/mjs/utils.js +17 -0
  84. package/lib/styles.css +13 -2
  85. package/lib/types/components/BackButton/BackButton.d.ts +2 -2
  86. package/lib/types/components/CTAButton/CTAButton.d.ts +1 -0
  87. package/lib/types/components/CioQuiz/actions.d.ts +5 -6
  88. package/lib/types/components/CioQuiz/context.d.ts +13 -6
  89. package/lib/types/components/CioQuiz/quizApiReducer.d.ts +2 -2
  90. package/lib/types/components/CioQuiz/quizLocalReducer.d.ts +3 -5
  91. package/lib/types/components/ControlBar/ControlBar.d.ts +0 -4
  92. package/lib/types/components/OpenTextTypeQuestion/OpenTextTypeQuestion.d.ts +2 -6
  93. package/lib/types/components/RedoButton/RedoButton.d.ts +1 -1
  94. package/lib/types/components/ResultCtaButton/ResultCtaButton.d.ts +1 -2
  95. package/lib/types/components/ResultHeroCard/ResultHeroCard.d.ts +7 -0
  96. package/lib/types/components/SelectTypeQuestion/SelectTypeQuestion.d.ts +3 -0
  97. package/lib/types/components/ZeroResults/ZeroResults.d.ts +2 -5
  98. package/lib/types/constants.d.ts +5 -4
  99. package/lib/types/hooks/useConsoleErrors.d.ts +2 -2
  100. package/lib/types/hooks/usePropsGetters/index.d.ts +18 -0
  101. package/lib/types/hooks/usePropsGetters/useCoverQuestionProps.d.ts +2 -0
  102. package/lib/types/hooks/usePropsGetters/useNextQuestionButtonProps.d.ts +4 -0
  103. package/lib/types/hooks/usePropsGetters/useOpenTextInputProps.d.ts +2 -0
  104. package/lib/types/hooks/usePropsGetters/usePreviousQuestionButtonProps.d.ts +3 -0
  105. package/lib/types/hooks/usePropsGetters/useSelectInputProps.d.ts +2 -0
  106. package/lib/types/hooks/useQuizEvents/index.d.ts +4 -16
  107. package/lib/types/hooks/useQuizEvents/useHydrateQuizLocalState.d.ts +4 -0
  108. package/lib/types/hooks/useQuizEvents/useQuizAnswerChangeHandler.d.ts +5 -0
  109. package/lib/types/hooks/useQuizEvents/useQuizBackClick.d.ts +2 -1
  110. package/lib/types/hooks/useQuizEvents/useQuizNextClick.d.ts +2 -1
  111. package/lib/types/hooks/useQuizEvents/useQuizResetClick.d.ts +4 -0
  112. package/lib/types/hooks/useQuizState/index.d.ts +16 -0
  113. package/lib/types/hooks/useQuizState/useQuizApiState.d.ts +12 -0
  114. package/lib/types/hooks/useQuizState/useQuizLocalState.d.ts +8 -0
  115. package/lib/types/index.d.ts +11 -0
  116. package/lib/types/services/index.d.ts +1 -1
  117. package/lib/types/stories/Quiz/tests/mocks.d.ts +5 -2
  118. package/lib/types/types.d.ts +121 -11
  119. package/lib/types/utils.d.ts +4 -0
  120. package/package.json +1 -1
  121. package/lib/cjs/hooks/useQuizLocalState.js +0 -54
  122. package/lib/mjs/hooks/useQuizLocalState.js +0 -48
  123. package/lib/types/hooks/useQuizApiState.d.ts +0 -11
  124. package/lib/types/hooks/useQuizLocalState.d.ts +0 -10
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const react_1 = require("react");
4
+ const actions_1 = require("../../components/CioQuiz/actions");
5
+ const utils_1 = require("../../utils");
6
+ const useQuizResetClick = (quizStateKey, dispatchLocalState, dispatchApiState, quizResults) => {
7
+ const quizResetClickHandler = (0, react_1.useCallback)(() => {
8
+ if (quizResults) {
9
+ dispatchLocalState({
10
+ type: actions_1.QuestionTypes.Reset,
11
+ });
12
+ dispatchApiState({
13
+ type: actions_1.QuizAPIActionTypes.RESET_QUIZ,
14
+ });
15
+ (0, utils_1.resetQuizSessionStorageState)(quizStateKey);
16
+ }
17
+ }, [dispatchLocalState, dispatchApiState, quizStateKey, quizResults]);
18
+ return quizResetClickHandler;
19
+ };
20
+ exports.default = useQuizResetClick;
@@ -4,7 +4,7 @@ const react_1 = require("react");
4
4
  const services_1 = require("../../services");
5
5
  const utils_1 = require("../../utils");
6
6
  const useQuizResultClick = (cioClient, quizApiState, onQuizResultClick) => {
7
- const resultClickHandler = (0, react_1.useCallback)((result, position) => {
7
+ const quizResultClickHandler = (0, react_1.useCallback)((result, position) => {
8
8
  if (quizApiState.quizResults) {
9
9
  // Tracking call
10
10
  (0, services_1.trackQuizResultClick)(cioClient, quizApiState.quizResults, result, position);
@@ -14,6 +14,6 @@ const useQuizResultClick = (cioClient, quizApiState, onQuizResultClick) => {
14
14
  }
15
15
  }
16
16
  }, [quizApiState, cioClient, onQuizResultClick]);
17
- return resultClickHandler;
17
+ return quizResultClickHandler;
18
18
  };
19
19
  exports.default = useQuizResultClick;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const useQuizApiState_1 = tslib_1.__importDefault(require("./useQuizApiState"));
5
+ const useQuizLocalState_1 = tslib_1.__importDefault(require("./useQuizLocalState"));
6
+ const useQuizState = (quizOptions, cioClient) => {
7
+ const { sessionStateOptions } = quizOptions;
8
+ // Quiz Local state
9
+ const { quizLocalState, dispatchLocalState, hasQuizStoredState, quizStateKey } = (0, useQuizLocalState_1.default)(sessionStateOptions === null || sessionStateOptions === void 0 ? void 0 : sessionStateOptions.sessionStateKey);
10
+ // Quiz API state
11
+ const { quizApiState, dispatchApiState } = (0, useQuizApiState_1.default)(quizOptions, cioClient, quizLocalState, dispatchLocalState);
12
+ return {
13
+ quizApiState,
14
+ quizLocalState,
15
+ dispatchApiState,
16
+ dispatchLocalState,
17
+ hasQuizStoredState,
18
+ quizStateKey,
19
+ };
20
+ };
21
+ exports.default = useQuizState;
@@ -2,18 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const react_1 = require("react");
5
- const actions_1 = require("../components/CioQuiz/actions");
6
- const quizApiReducer_1 = tslib_1.__importStar(require("../components/CioQuiz/quizApiReducer"));
7
- const services_1 = require("../services");
8
- const useFetchQuiz = (quizId, quizLocalState, dispatchLocalState, resultsPageOptions, quizVersionIdProp, cioClient) => {
9
- var _a, _b;
10
- const [quizApiState, dispatch] = (0, react_1.useReducer)(quizApiReducer_1.default, quizApiReducer_1.initialState);
11
- const firstQuestionId = (_a = quizApiState.quizFirstQuestion) === null || _a === void 0 ? void 0 : _a.next_question.id;
12
- const currentQuestionId = (_b = quizApiState.quizCurrentQuestion) === null || _b === void 0 ? void 0 : _b.next_question.id;
13
- const isFirstQuestion = firstQuestionId === currentQuestionId;
5
+ const actions_1 = require("../../components/CioQuiz/actions");
6
+ const quizApiReducer_1 = tslib_1.__importStar(require("../../components/CioQuiz/quizApiReducer"));
7
+ const services_1 = require("../../services");
8
+ const useQuizApiState = (quizOptions, cioClient, quizLocalState, dispatchLocalState) => {
9
+ const [quizApiState, dispatchApiState] = (0, react_1.useReducer)(quizApiReducer_1.default, quizApiReducer_1.initialState);
10
+ const { quizId, quizVersionId: quizVersionIdProp, resultsPageOptions } = quizOptions;
14
11
  (0, react_1.useEffect)(() => {
15
12
  (() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
16
- dispatch({
13
+ dispatchApiState({
17
14
  type: actions_1.QuizAPIActionTypes.SET_IS_LOADING,
18
15
  });
19
16
  if (quizLocalState.isLastAnswer) {
@@ -25,7 +22,7 @@ const useFetchQuiz = (quizId, quizLocalState, dispatchLocalState, resultsPageOpt
25
22
  quizSessionId: quizLocalState.quizSessionId,
26
23
  });
27
24
  // Set quiz results state
28
- dispatch({
25
+ dispatchApiState({
29
26
  type: actions_1.QuizAPIActionTypes.SET_QUIZ_RESULTS,
30
27
  payload: {
31
28
  quizResults,
@@ -33,7 +30,7 @@ const useFetchQuiz = (quizId, quizLocalState, dispatchLocalState, resultsPageOpt
33
30
  });
34
31
  }
35
32
  catch (error) {
36
- dispatch({
33
+ dispatchApiState({
37
34
  type: actions_1.QuizAPIActionTypes.SET_IS_ERROR,
38
35
  });
39
36
  }
@@ -42,7 +39,7 @@ const useFetchQuiz = (quizId, quizLocalState, dispatchLocalState, resultsPageOpt
42
39
  try {
43
40
  const quizVersionId = quizLocalState.quizVersionId || quizVersionIdProp;
44
41
  const { quizSessionId } = quizLocalState;
45
- const questionResult = yield (0, services_1.nextQuestion)(cioClient, quizId, {
42
+ const questionResult = yield (0, services_1.getNextQuestion)(cioClient, quizId, {
46
43
  answers: quizLocalState.answers,
47
44
  quizVersionId,
48
45
  quizSessionId,
@@ -59,7 +56,7 @@ const useFetchQuiz = (quizId, quizLocalState, dispatchLocalState, resultsPageOpt
59
56
  });
60
57
  }
61
58
  // Set current question state
62
- dispatch({
59
+ dispatchApiState({
63
60
  type: actions_1.QuizAPIActionTypes.SET_CURRENT_QUESTION,
64
61
  payload: {
65
62
  quizCurrentQuestion: questionResult,
@@ -67,28 +64,17 @@ const useFetchQuiz = (quizId, quizLocalState, dispatchLocalState, resultsPageOpt
67
64
  });
68
65
  }
69
66
  catch (error) {
70
- dispatch({
67
+ dispatchApiState({
71
68
  type: actions_1.QuizAPIActionTypes.SET_IS_ERROR,
72
69
  });
73
70
  }
74
71
  }
75
72
  }))();
76
73
  // eslint-disable-next-line react-hooks/exhaustive-deps
77
- }, [
78
- cioClient,
79
- quizId,
80
- quizLocalState.answers,
81
- quizLocalState.isLastAnswer,
82
- resultsPageOptions === null || resultsPageOptions === void 0 ? void 0 : resultsPageOptions.numResultsToDisplay,
83
- ]);
84
- const resetQuizApiState = () => {
85
- dispatch({ type: actions_1.QuizAPIActionTypes.RESET_QUIZ });
86
- };
74
+ }, [cioClient, quizId, quizLocalState.answers, resultsPageOptions === null || resultsPageOptions === void 0 ? void 0 : resultsPageOptions.numResultsToDisplay]);
87
75
  return {
88
- cioClient,
89
76
  quizApiState,
90
- isFirstQuestion,
91
- resetQuizApiState,
77
+ dispatchApiState,
92
78
  };
93
79
  };
94
- exports.default = useFetchQuiz;
80
+ exports.default = useQuizApiState;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const react_1 = require("react");
5
+ const quizLocalReducer_1 = tslib_1.__importStar(require("../../components/CioQuiz/quizLocalReducer"));
6
+ const constants_1 = require("../../constants");
7
+ const utils_1 = require("../../utils");
8
+ const useQuizLocalState = (sessionStateKey) => {
9
+ const [quizLocalState, dispatch] = (0, react_1.useReducer)(quizLocalReducer_1.default, quizLocalReducer_1.initialState);
10
+ const quizStateKey = sessionStateKey || constants_1.quizSessionStateKey;
11
+ (0, react_1.useEffect)(() => {
12
+ var _a, _b;
13
+ // don't save state if initial state
14
+ if ((_a = quizLocalState === null || quizLocalState === void 0 ? void 0 : quizLocalState.answers) === null || _a === void 0 ? void 0 : _a.length) {
15
+ (_b = window === null || window === void 0 ? void 0 : window.sessionStorage) === null || _b === void 0 ? void 0 : _b.setItem(quizStateKey, JSON.stringify(quizLocalState));
16
+ }
17
+ }, [quizLocalState, quizStateKey]);
18
+ const hasQuizStoredState = () => (0, utils_1.getStateFromSessionStorage)(quizStateKey) !== null;
19
+ const dispatchLocalState = (0, react_1.useCallback)((action) => {
20
+ (0, utils_1.logger)(action);
21
+ dispatch(action);
22
+ }, []);
23
+ return {
24
+ quizLocalState,
25
+ hasQuizStoredState,
26
+ dispatchLocalState,
27
+ quizStateKey,
28
+ };
29
+ };
30
+ exports.default = useQuizLocalState;
package/lib/cjs/index.js CHANGED
@@ -1,5 +1,30 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResultHeroCard = exports.ResultFilters = exports.ResultContainer = exports.ResultCard = exports.Results = exports.SelectQuestion = exports.CoverQuestion = exports.OpenTextQuestion = exports.QuizQuestions = exports.useCioQuiz = void 0;
3
4
  const tslib_1 = require("tslib");
4
5
  const CioQuiz_1 = tslib_1.__importDefault(require("./components/CioQuiz"));
6
+ // Hook
7
+ var useQuiz_1 = require("./hooks/useQuiz");
8
+ Object.defineProperty(exports, "useCioQuiz", { enumerable: true, get: function () { return tslib_1.__importDefault(useQuiz_1).default; } });
9
+ // Questions Components
10
+ var index_1 = require("./components/QuizQuestions/index");
11
+ Object.defineProperty(exports, "QuizQuestions", { enumerable: true, get: function () { return tslib_1.__importDefault(index_1).default; } });
12
+ var OpenTextTypeQuestion_1 = require("./components/OpenTextTypeQuestion/OpenTextTypeQuestion");
13
+ Object.defineProperty(exports, "OpenTextQuestion", { enumerable: true, get: function () { return tslib_1.__importDefault(OpenTextTypeQuestion_1).default; } });
14
+ var CoverTypeQuestion_1 = require("./components/CoverTypeQuestion/CoverTypeQuestion");
15
+ Object.defineProperty(exports, "CoverQuestion", { enumerable: true, get: function () { return tslib_1.__importDefault(CoverTypeQuestion_1).default; } });
16
+ var SelectTypeQuestion_1 = require("./components/SelectTypeQuestion/SelectTypeQuestion");
17
+ Object.defineProperty(exports, "SelectQuestion", { enumerable: true, get: function () { return tslib_1.__importDefault(SelectTypeQuestion_1).default; } });
18
+ // Results Components
19
+ var Results_1 = require("./components/Results/Results");
20
+ Object.defineProperty(exports, "Results", { enumerable: true, get: function () { return tslib_1.__importDefault(Results_1).default; } });
21
+ var ResultCard_1 = require("./components/ResultCard/ResultCard");
22
+ Object.defineProperty(exports, "ResultCard", { enumerable: true, get: function () { return tslib_1.__importDefault(ResultCard_1).default; } });
23
+ var ResultContainer_1 = require("./components/ResultContainer/ResultContainer");
24
+ Object.defineProperty(exports, "ResultContainer", { enumerable: true, get: function () { return tslib_1.__importDefault(ResultContainer_1).default; } });
25
+ var ResultFilters_1 = require("./components/ResultFilters/ResultFilters");
26
+ Object.defineProperty(exports, "ResultFilters", { enumerable: true, get: function () { return tslib_1.__importDefault(ResultFilters_1).default; } });
27
+ var ResultHeroCard_1 = require("./components/ResultHeroCard/ResultHeroCard");
28
+ Object.defineProperty(exports, "ResultHeroCard", { enumerable: true, get: function () { return tslib_1.__importDefault(ResultHeroCard_1).default; } });
29
+ tslib_1.__exportStar(require("./types"), exports);
5
30
  exports.default = CioQuiz_1.default;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.trackQuizConversion = exports.trackQuizResultClick = exports.trackQuizResultsLoaded = exports.getQuizResults = exports.nextQuestion = exports.getCioClient = void 0;
3
+ exports.trackQuizConversion = exports.trackQuizResultClick = exports.trackQuizResultsLoaded = exports.getQuizResults = exports.getNextQuestion = exports.getCioClient = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  /* eslint-disable @typescript-eslint/naming-convention */
6
6
  const constructorio_client_javascript_1 = tslib_1.__importDefault(require("@constructor-io/constructorio-client-javascript"));
@@ -14,8 +14,8 @@ const getCioClient = (apiKey) => {
14
14
  return undefined;
15
15
  };
16
16
  exports.getCioClient = getCioClient;
17
- const nextQuestion = (cioClient, quizId, parameters) => cioClient === null || cioClient === void 0 ? void 0 : cioClient.quizzes.getQuizNextQuestion(quizId, parameters);
18
- exports.nextQuestion = nextQuestion;
17
+ const getNextQuestion = (cioClient, quizId, parameters) => cioClient === null || cioClient === void 0 ? void 0 : cioClient.quizzes.getQuizNextQuestion(quizId, parameters);
18
+ exports.getNextQuestion = getNextQuestion;
19
19
  const getQuizResults = (cioClient, quizId, parameters) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { return cioClient === null || cioClient === void 0 ? void 0 : cioClient.quizzes.getQuizResults(quizId, parameters); });
20
20
  exports.getQuizResults = getQuizResults;
21
21
  // Tracking requests
@@ -1,12 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getMockContextValue = exports.getMockState = exports.questionOptions = exports.questionOptionsWithImages = exports.getMockQuestionWithImage = exports.getMockQuestion = void 0;
3
+ exports.useMockContextValue = exports.getMockState = exports.questionOptions = exports.questionOptionsWithImages = exports.getMockQuestionWithImage = exports.getMockQuestion = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const constants_1 = require("../../../constants");
6
+ const useOpenTextInputProps_1 = tslib_1.__importDefault(require("../../../hooks/usePropsGetters/useOpenTextInputProps"));
7
+ const useCoverQuestionProps_1 = tslib_1.__importDefault(require("../../../hooks/usePropsGetters/useCoverQuestionProps"));
8
+ const useSelectInputProps_1 = tslib_1.__importDefault(require("../../../hooks/usePropsGetters/useSelectInputProps"));
4
9
  const getMockQuestion = (type) => ({
5
10
  id: 1,
6
11
  title: 'This is question title',
7
12
  description: 'This is question description',
8
13
  cta_text: 'Continue',
9
14
  type,
15
+ input_placeholder: 'Answer here...',
10
16
  });
11
17
  exports.getMockQuestion = getMockQuestion;
12
18
  const getMockImages = () => ({
@@ -37,16 +43,26 @@ exports.questionOptions = [
37
43
  ];
38
44
  const getMockState = (question) => ({
39
45
  answers: {
40
- inputs: { 1: '' },
46
+ inputs: {
47
+ 1: {
48
+ type: question === null || question === void 0 ? void 0 : question.type,
49
+ value: '',
50
+ },
51
+ },
41
52
  isLastAnswer: false,
42
53
  },
43
54
  quiz: {
44
- requestState: 1,
55
+ requestState: constants_1.RequestStates.Success,
45
56
  versionId: '',
46
57
  sessionId: '',
47
- isFirstQuestion: false,
48
58
  currentQuestion: {
49
59
  next_question: question,
60
+ isFirstQuestion: false,
61
+ isOpenQuestion: (question === null || question === void 0 ? void 0 : question.type) === 'open',
62
+ isCoverQuestion: (question === null || question === void 0 ? void 0 : question.type) === 'cover',
63
+ isSingleQuestion: (question === null || question === void 0 ? void 0 : question.type) === 'single',
64
+ isMultipleQuestion: (question === null || question === void 0 ? void 0 : question.type) === 'multiple',
65
+ isSelectQuestion: (question === null || question === void 0 ? void 0 : question.type) === 'single',
50
66
  },
51
67
  results: {
52
68
  response: {
@@ -78,19 +94,58 @@ const getMockState = (question) => ({
78
94
  },
79
95
  },
80
96
  ],
97
+ facets: [],
98
+ groups: [],
99
+ sort_options: [],
100
+ refined_content: [],
101
+ total_num_results: 10,
102
+ features: [],
103
+ result_sources: {},
81
104
  },
105
+ quiz_id: '',
106
+ quiz_session_id: '',
107
+ quiz_version_id: '',
82
108
  },
83
109
  resultsFilters: ['Chocolate', 'Medium'],
84
110
  },
85
111
  });
86
112
  exports.getMockState = getMockState;
87
- const getMockContextValue = (question) => ({
88
- state: (0, exports.getMockState)(question),
89
- previousQuestion: () => { },
90
- nextQuestion: () => { },
91
- addToCart: () => { },
92
- customClickItemCallback: false,
93
- resetQuiz: () => { },
94
- resultClick: () => { },
95
- });
96
- exports.getMockContextValue = getMockContextValue;
113
+ const mockElementProps = {
114
+ className: '',
115
+ type: 'submit',
116
+ onClick: () => { },
117
+ onChange: () => { },
118
+ onKeyDown: () => { },
119
+ role: 'button',
120
+ tabIndex: 0,
121
+ key: 0,
122
+ style: {},
123
+ placeholder: '',
124
+ value: '',
125
+ };
126
+ const useMockContextValue = (question) => {
127
+ const getOpenTextInputProps = (0, useOpenTextInputProps_1.default)(() => { }, () => { }, question);
128
+ const getCoverQuestionProps = (0, useCoverQuestionProps_1.default)(() => { }, question);
129
+ const getSelectInputProps = (0, useSelectInputProps_1.default)(() => { }, () => { }, question);
130
+ return {
131
+ state: (0, exports.getMockState)(question),
132
+ getCoverQuestionProps,
133
+ getOpenTextInputProps,
134
+ getSelectInputProps,
135
+ getAddToCartButtonProps: () => (Object.assign(Object.assign({}, mockElementProps), { className: 'cio-question-cta-button' })),
136
+ getHydrateQuizButtonProps: () => (Object.assign(Object.assign({}, mockElementProps), { className: 'cio-question-cta-button' })),
137
+ getNextQuestionButtonProps: () => (Object.assign(Object.assign({}, mockElementProps), { className: 'cio-question-cta-button' })),
138
+ getPreviousQuestionButtonProps: () => (Object.assign(Object.assign({}, mockElementProps), { className: 'cio-question-back-button' })),
139
+ getQuizImageProps: () => mockElementProps,
140
+ getQuizResultButtonProps: () => mockElementProps,
141
+ getQuizResultLinkProps: () => mockElementProps,
142
+ getResetQuizButtonProps: () => (Object.assign(Object.assign({}, mockElementProps), { className: 'cio-question-redo-button' })),
143
+ primaryColorStyles: {
144
+ '--primary-color-h': '12',
145
+ '--primary-color-s': '14',
146
+ '--primary-color-l': '14',
147
+ },
148
+ customClickItemCallback: false,
149
+ };
150
+ };
151
+ exports.useMockContextValue = useMockContextValue;
package/lib/cjs/utils.js CHANGED
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.convertPrimaryColorsToString = exports.rgbToHsl = exports.sleep = exports.getFilterValuesFromExpression = exports.isFunction = exports.getPreferredColorScheme = exports.getQuestionTypes = exports.stringify = exports.stringifyWithDefaults = exports.functionStrings = exports.getStoryParams = exports.renderImages = void 0;
3
+ exports.convertPrimaryColorsToString = exports.rgbToHsl = exports.sleep = exports.logger = exports.resetQuizSessionStorageState = exports.getStateFromSessionStorage = exports.getFilterValuesFromExpression = exports.isFunction = exports.getPreferredColorScheme = exports.getQuestionTypes = exports.stringify = exports.stringifyWithDefaults = exports.functionStrings = exports.getStoryParams = exports.renderImages = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ /* eslint-disable no-console */
5
6
  const react_1 = tslib_1.__importDefault(require("react"));
6
7
  const actions_1 = require("./components/CioQuiz/actions");
7
8
  const renderImages = (images, cssClasses) => {
@@ -123,6 +124,27 @@ const getFilterValuesFromExpression = (exp) => {
123
124
  return [];
124
125
  };
125
126
  exports.getFilterValuesFromExpression = getFilterValuesFromExpression;
127
+ const getStateFromSessionStorage = (quizStateKey) => {
128
+ var _a;
129
+ const state = (_a = window === null || window === void 0 ? void 0 : window.sessionStorage) === null || _a === void 0 ? void 0 : _a.getItem(quizStateKey);
130
+ if (state) {
131
+ return JSON.parse(state);
132
+ }
133
+ return null;
134
+ };
135
+ exports.getStateFromSessionStorage = getStateFromSessionStorage;
136
+ const resetQuizSessionStorageState = (quizStateKey) => () => {
137
+ var _a;
138
+ (_a = window === null || window === void 0 ? void 0 : window.sessionStorage) === null || _a === void 0 ? void 0 : _a.removeItem(quizStateKey);
139
+ };
140
+ exports.resetQuizSessionStorageState = resetQuizSessionStorageState;
141
+ const logger = (action) => {
142
+ console.group(`%cAction:%c ${action.type}`, 'color: red; font-weight: bold;', 'color: green; font-weight: lighter;');
143
+ console.log('%c type:', 'color: #9E9E9E; font-weight: 700;', action.type);
144
+ console.log('%c payload:', 'color: #00A7F7; font-weight: 700;', action.payload);
145
+ console.groupEnd();
146
+ };
147
+ exports.logger = logger;
126
148
  // Function to emulate pausing between interactions
127
149
  function sleep(ms) {
128
150
  // eslint-disable-next-line
@@ -1,9 +1,14 @@
1
- import React from 'react';
2
- function BackButton(props) {
3
- // eslint-disable-next-line
4
- const { disabled } = props;
5
- return (React.createElement("button", { title: 'Quiz Back Button', type: 'button', className: `cio-question-back-button ${disabled ? 'disabled' : ''}`, ...props },
6
- React.createElement("svg", { width: '8', height: '12', viewBox: '0 0 8 12', fill: 'none', xmlns: 'http://www.w3.org/2000/svg' },
7
- React.createElement("path", { d: 'M6.06313 1.06268L0.964522 5.43176C0.882383 5.50218 0.816449 5.58954 0.771245 5.68785C0.726041 5.78615 0.702637 5.89306 0.702637 6.00126C0.702637 6.10946 0.726041 6.21637 0.771245 6.31467C0.816449 6.41297 0.882383 6.50033 0.964522 6.57076L6.06313 10.9398C6.5498 11.3568 7.30153 11.0111 7.30153 10.3703V1.63093C7.30153 0.990168 6.5498 0.644468 6.06313 1.06268Z', fill: 'currentColor' }))));
1
+ import React, { useContext } from 'react';
2
+ import QuizContext from '../CioQuiz/context';
3
+ function BackButton() {
4
+ const { getPreviousQuestionButtonProps } = useContext(QuizContext);
5
+ if (getPreviousQuestionButtonProps) {
6
+ return (getPreviousQuestionButtonProps && (
7
+ // eslint-disable-next-line react/button-has-type
8
+ React.createElement("button", { ...getPreviousQuestionButtonProps() },
9
+ React.createElement("svg", { width: '8', height: '12', viewBox: '0 0 8 12', fill: 'none', xmlns: 'http://www.w3.org/2000/svg' },
10
+ React.createElement("path", { d: 'M6.06313 1.06268L0.964522 5.43176C0.882383 5.50218 0.816449 5.58954 0.771245 5.68785C0.726041 5.78615 0.702637 5.89306 0.702637 6.00126C0.702637 6.10946 0.726041 6.21637 0.771245 6.31467C0.816449 6.41297 0.882383 6.50033 0.964522 6.57076L6.06313 10.9398C6.5498 11.3568 7.30153 11.0111 7.30153 10.3703V1.63093C7.30153 0.990168 6.5498 0.644468 6.06313 1.06268Z', fill: 'currentColor' })))));
11
+ }
12
+ return null;
8
13
  }
9
14
  export default BackButton;
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
2
  function CTAButton(props) {
3
- const { ctaText = 'Continue', disabled, className = 'cio-button-container', ...rest } = props;
4
- return (React.createElement("div", { className: `${className || ''}` },
5
- React.createElement("button", { type: 'button', className: `${disabled ? 'cio-question-cta-button disabled' : 'cio-question-cta-button'}`, ...rest }, ctaText || 'Continue')));
3
+ const { propsGetters, ctaText = 'Continue', disabled, className = 'cio-button-container', ...rest } = props;
4
+ return (React.createElement("div", { className: `${className || ''}` }, propsGetters && (
5
+ // eslint-disable-next-line react/button-has-type
6
+ React.createElement("button", { ...rest, ...propsGetters() }, ctaText || 'Continue'))));
6
7
  }
7
8
  export default CTAButton;
@@ -5,6 +5,7 @@ export var QuestionTypes;
5
5
  QuestionTypes["Cover"] = "cover";
6
6
  QuestionTypes["SingleSelect"] = "single";
7
7
  QuestionTypes["MultipleSelect"] = "multiple";
8
+ QuestionTypes["Next"] = "next";
8
9
  QuestionTypes["Back"] = "back";
9
10
  QuestionTypes["Reset"] = "reset";
10
11
  QuestionTypes["Hydrate"] = "hydrate";
@@ -8,28 +8,35 @@ import useQuiz from '../../hooks/useQuiz';
8
8
  import SessionPromptModal from '../SessionPromptModal/SessionPromptModal';
9
9
  import { convertPrimaryColorsToString } from '../../utils';
10
10
  export default function CioQuiz(props) {
11
- const { cioClient, state, events: { nextQuestion, previousQuestion, resetQuiz, addToCart, resultClick, hydrateQuiz, hasStoredState, resetStoredState, }, primaryColorStyles, } = useQuiz(props);
11
+ const { cioClient, state, events: { hydrateQuiz, hasSessionStorageState, resetSessionStorageState }, getAddToCartButtonProps, getCoverQuestionProps, getHydrateQuizButtonProps, getNextQuestionButtonProps, getOpenTextInputProps, getPreviousQuestionButtonProps, getQuizImageProps, getQuizResultButtonProps, getQuizResultLinkProps, getResetQuizButtonProps, getSelectInputProps, primaryColorStyles, } = useQuiz(props);
12
12
  const [showSessionPrompt, setShowSessionPrompt] = useState(false);
13
13
  const { resultsPageOptions, sessionStateOptions } = props;
14
14
  useEffect(() => {
15
15
  // Respect showSessionModal if defined, else default to true.
16
16
  if (sessionStateOptions?.showSessionModal !== undefined) {
17
- setShowSessionPrompt(sessionStateOptions?.showSessionModal && hasStoredState());
17
+ setShowSessionPrompt(sessionStateOptions?.showSessionModal && hasSessionStorageState());
18
18
  }
19
19
  else {
20
- setShowSessionPrompt(hasStoredState());
20
+ setShowSessionPrompt(hasSessionStorageState());
21
21
  }
22
22
  // eslint-disable-next-line react-hooks/exhaustive-deps
23
23
  }, []);
24
24
  const contextValue = {
25
25
  cioClient,
26
26
  state,
27
- nextQuestion,
28
- previousQuestion,
29
- resetQuiz,
30
- addToCart,
31
- resultClick,
27
+ getAddToCartButtonProps,
28
+ getCoverQuestionProps,
29
+ getHydrateQuizButtonProps,
30
+ getNextQuestionButtonProps,
31
+ getOpenTextInputProps,
32
+ getPreviousQuestionButtonProps,
33
+ getQuizImageProps,
34
+ getQuizResultButtonProps,
35
+ getQuizResultLinkProps,
36
+ getResetQuizButtonProps,
37
+ getSelectInputProps,
32
38
  customClickItemCallback: !!resultsPageOptions?.onQuizResultClick,
39
+ primaryColorStyles,
33
40
  };
34
41
  if (state.quiz.requestState === RequestStates.Loading) {
35
42
  return (React.createElement("div", { className: 'cio-quiz' },
@@ -40,7 +47,7 @@ export default function CioQuiz(props) {
40
47
  React.createElement("style", null,
41
48
  ".cio-quiz ",
42
49
  convertPrimaryColorsToString(primaryColorStyles)),
43
- React.createElement(SessionPromptModal, { resetStoredState: resetStoredState, continueSession: hydrateQuiz, showSessionPrompt: showSessionPrompt, setShowSessionPrompt: setShowSessionPrompt }),
50
+ React.createElement(SessionPromptModal, { resetStoredState: resetSessionStorageState, continueSession: hydrateQuiz, showSessionPrompt: showSessionPrompt, setShowSessionPrompt: setShowSessionPrompt }),
44
51
  React.createElement(QuizContext.Provider, { value: contextValue },
45
52
  state.quiz.results && React.createElement(ResultContainer, { options: resultsPageOptions }),
46
53
  state.quiz.currentQuestion && React.createElement(QuizQuestions, null))));
@@ -1,5 +1,5 @@
1
1
  import { RequestStates } from '../../constants';
2
- import { getFilterValuesFromExpression } from '../../utils';
2
+ import { getFilterValuesFromExpression, getQuestionTypes } from '../../utils';
3
3
  import { QuizAPIActionTypes } from './actions';
4
4
  export const initialState = {
5
5
  quizRequestState: RequestStates.Stale,
@@ -10,24 +10,36 @@ export default function apiReducer(state, action) {
10
10
  return {
11
11
  ...state,
12
12
  quizRequestState: RequestStates.Loading,
13
+ quizCurrentQuestion: undefined,
14
+ quizResults: undefined,
13
15
  };
14
16
  case QuizAPIActionTypes.SET_IS_ERROR:
15
17
  return {
16
18
  ...state,
17
19
  quizRequestState: RequestStates.Error,
20
+ quizCurrentQuestion: undefined,
18
21
  quizResults: undefined,
19
22
  };
20
- case QuizAPIActionTypes.SET_CURRENT_QUESTION:
23
+ case QuizAPIActionTypes.SET_CURRENT_QUESTION: {
24
+ const { isOpenQuestion, isCoverQuestion, isSingleQuestion, isMultipleQuestion, isSelectQuestion, } = getQuestionTypes(action.payload?.quizCurrentQuestion?.next_question?.type);
25
+ const quizFirstQuestion = state.quizFirstQuestion || action.payload?.quizCurrentQuestion;
21
26
  return {
22
27
  ...state,
23
28
  quizRequestState: RequestStates.Success,
24
- quizCurrentQuestion: action.payload?.quizCurrentQuestion,
29
+ quizCurrentQuestion: {
30
+ ...action.payload?.quizCurrentQuestion,
31
+ isFirstQuestion: quizFirstQuestion?.next_question.id ===
32
+ action.payload?.quizCurrentQuestion?.next_question?.id,
33
+ isOpenQuestion,
34
+ isCoverQuestion,
35
+ isSingleQuestion,
36
+ isMultipleQuestion,
37
+ isSelectQuestion,
38
+ },
39
+ quizFirstQuestion,
25
40
  quizResults: undefined,
26
- // If no current question set first question value
27
- ...(!state.quizCurrentQuestion && {
28
- quizFirstQuestion: action.payload?.quizCurrentQuestion,
29
- }),
30
41
  };
42
+ }
31
43
  case QuizAPIActionTypes.SET_QUIZ_RESULTS: {
32
44
  const filterExpression = action.payload?.quizResults?.request?.collection_filter_expression || null;
33
45
  const quizResultsFilters = [...new Set(getFilterValuesFromExpression(filterExpression))];
@@ -1,4 +1,4 @@
1
- import { QuestionTypes, } from './actions';
1
+ import { QuestionTypes } from './actions';
2
2
  export const initialState = {
3
3
  answers: [],
4
4
  answerInputs: {},
@@ -7,7 +7,10 @@ export const initialState = {
7
7
  function answerInputReducer(state, action) {
8
8
  return {
9
9
  ...state,
10
- [String(action.payload.questionId)]: action.payload.input,
10
+ [String(action.payload.questionId)]: {
11
+ type: action.type,
12
+ value: action.payload.input,
13
+ },
11
14
  };
12
15
  }
13
16
  export default function quizLocalReducer(state, action) {
@@ -15,36 +18,62 @@ export default function quizLocalReducer(state, action) {
15
18
  case QuestionTypes.OpenText:
16
19
  return {
17
20
  ...state,
18
- answers: [...state.answers, ['true']],
19
21
  answerInputs: answerInputReducer(state.answerInputs, action),
20
22
  isLastAnswer: !!action.payload?.isLastQuestion,
21
23
  };
22
24
  case QuestionTypes.Cover:
23
25
  return {
24
26
  ...state,
25
- answers: [...state.answers, ['seen']],
27
+ answerInputs: answerInputReducer(state.answerInputs, action),
26
28
  isLastAnswer: !!action.payload?.isLastQuestion,
27
29
  };
28
30
  case QuestionTypes.SingleSelect:
29
31
  return {
30
32
  ...state,
31
- answers: [...state.answers, action.payload?.input],
32
33
  answerInputs: answerInputReducer(state.answerInputs, action),
33
34
  isLastAnswer: !!action.payload?.isLastQuestion,
34
35
  };
35
36
  case QuestionTypes.MultipleSelect:
36
37
  return {
37
38
  ...state,
38
- answers: [...state.answers, action.payload?.input],
39
39
  answerInputs: answerInputReducer(state.answerInputs, action),
40
40
  isLastAnswer: !!action.payload?.isLastQuestion,
41
41
  };
42
- case QuestionTypes.Back:
42
+ case QuestionTypes.Next: {
43
+ const { answers } = state;
44
+ const newAnswers = [...answers];
45
+ const lastAnswerInputIndex = answers.length;
46
+ const currentAnswerInput = Object.values(state.answerInputs)?.[lastAnswerInputIndex];
47
+ switch (currentAnswerInput.type) {
48
+ case QuestionTypes.OpenText:
49
+ newAnswers.push(['true']);
50
+ break;
51
+ case QuestionTypes.Cover:
52
+ newAnswers.push(['seen']);
53
+ break;
54
+ case QuestionTypes.SingleSelect:
55
+ newAnswers.push(currentAnswerInput.value);
56
+ break;
57
+ case QuestionTypes.MultipleSelect:
58
+ newAnswers.push(currentAnswerInput.value);
59
+ break;
60
+ default:
61
+ newAnswers.push([]);
62
+ }
63
+ return {
64
+ ...state,
65
+ answers: newAnswers,
66
+ };
67
+ }
68
+ case QuestionTypes.Back: {
69
+ const newAnswerInputs = { ...state.answerInputs };
43
70
  return {
44
71
  ...state,
72
+ answerInputs: newAnswerInputs,
45
73
  answers: [...state.answers.slice(0, -1)],
46
74
  isLastAnswer: false,
47
75
  };
76
+ }
48
77
  case QuestionTypes.Reset:
49
78
  return {
50
79
  ...initialState,