@constructor-io/constructorio-ui-quizzes 1.4.7 → 1.5.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.
@@ -5,12 +5,14 @@ const react_1 = tslib_1.__importStar(require("react"));
5
5
  const context_1 = tslib_1.__importDefault(require("./context"));
6
6
  const QuizQuestions_1 = tslib_1.__importDefault(require("../QuizQuestions"));
7
7
  const ResultContainer_1 = tslib_1.__importDefault(require("../ResultContainer/ResultContainer"));
8
+ const ControlBar_1 = tslib_1.__importDefault(require("../ControlBar/ControlBar"));
8
9
  const constants_1 = require("../../constants");
9
10
  const Spinner_1 = tslib_1.__importDefault(require("../Spinner/Spinner"));
10
11
  const useQuiz_1 = tslib_1.__importDefault(require("../../hooks/useQuiz"));
11
12
  const SessionPromptModal_1 = tslib_1.__importDefault(require("../SessionPromptModal/SessionPromptModal"));
12
13
  const utils_1 = require("../../utils");
13
14
  function CioQuiz(props) {
15
+ var _a;
14
16
  const { cioClient, state, events: { hydrateQuiz, hasSessionStorageState, resetSessionStorageState }, getAddToCartButtonProps, getCoverQuestionProps, getHydrateQuizButtonProps, getNextQuestionButtonProps, getOpenTextInputProps, getPreviousQuestionButtonProps, getQuizImageProps, getQuizResultButtonProps, getQuizResultLinkProps, getResetQuizButtonProps, getSelectInputProps, primaryColorStyles, } = (0, useQuiz_1.default)(props);
15
17
  const [showSessionPrompt, setShowSessionPrompt] = (0, react_1.useState)(false);
16
18
  const { resultsPageOptions, sessionStateOptions } = props;
@@ -46,16 +48,23 @@ function CioQuiz(props) {
46
48
  primaryColorStyles,
47
49
  };
48
50
  if (state.quiz.requestState === constants_1.RequestStates.Loading) {
49
- return (react_1.default.createElement("div", { className: 'cio-quiz' },
51
+ return (react_1.default.createElement("div", { className: 'cio-quiz cio-quiz-loading' },
50
52
  react_1.default.createElement(Spinner_1.default, null)));
51
53
  }
54
+ const questionData = (_a = state.quiz.currentQuestion) === null || _a === void 0 ? void 0 : _a.next_question;
55
+ const questionType = questionData === null || questionData === void 0 ? void 0 : questionData.type;
56
+ const questionImages = questionData === null || questionData === void 0 ? void 0 : questionData.images;
57
+ const displayBackgroundImage = (questionType === 'single' || questionType === 'multiple') && questionImages;
52
58
  if (state.quiz.requestState === constants_1.RequestStates.Success) {
53
59
  return (react_1.default.createElement("div", { className: 'cio-quiz' },
60
+ displayBackgroundImage && (0, utils_1.renderImages)(questionImages, 'cio-question-background-image'),
54
61
  react_1.default.createElement("style", null,
55
62
  ".cio-quiz ",
56
63
  (0, utils_1.convertPrimaryColorsToString)(primaryColorStyles)),
57
64
  react_1.default.createElement(SessionPromptModal_1.default, { resetStoredState: resetSessionStorageState, continueSession: hydrateQuiz, showSessionPrompt: showSessionPrompt, setShowSessionPrompt: setShowSessionPrompt }),
58
- react_1.default.createElement(context_1.default.Provider, { value: contextValue }, state.quiz.results || state.quiz.skipToResults ? (react_1.default.createElement(ResultContainer_1.default, { options: resultsPageOptions })) : (state.quiz.currentQuestion && react_1.default.createElement(QuizQuestions_1.default, null)))));
65
+ react_1.default.createElement(context_1.default.Provider, { value: contextValue }, state.quiz.results || state.quiz.skipToResults ? (react_1.default.createElement(ResultContainer_1.default, { options: resultsPageOptions })) : (state.quiz.currentQuestion && (react_1.default.createElement(react_1.default.Fragment, null,
66
+ react_1.default.createElement(QuizQuestions_1.default, null),
67
+ react_1.default.createElement(ControlBar_1.default, { ctaButtonText: (questionData === null || questionData === void 0 ? void 0 : questionData.cta_text) || undefined })))))));
59
68
  }
60
69
  return null;
61
70
  }
@@ -6,7 +6,6 @@ const QuestionTitle_1 = tslib_1.__importDefault(require("../QuestionTitle/Questi
6
6
  const context_1 = tslib_1.__importDefault(require("../CioQuiz/context"));
7
7
  const QuestionDescription_1 = tslib_1.__importDefault(require("../QuestionDescription/QuestionDescription"));
8
8
  const utils_1 = require("../../utils");
9
- const ControlBar_1 = tslib_1.__importDefault(require("../ControlBar/ControlBar"));
10
9
  function CoverTypeQuestion() {
11
10
  var _a;
12
11
  const { state } = (0, react_1.useContext)(context_1.default);
@@ -23,8 +22,7 @@ function CoverTypeQuestion() {
23
22
  hasImage ? (0, utils_1.renderImages)(question.images, 'cio-question-image-container') : '',
24
23
  react_1.default.createElement("div", { className: 'cio-question-content' },
25
24
  react_1.default.createElement(QuestionTitle_1.default, { title: question === null || question === void 0 ? void 0 : question.title }),
26
- react_1.default.createElement(QuestionDescription_1.default, { description: question.description }),
27
- react_1.default.createElement(ControlBar_1.default, { ctaButtonText: question === null || question === void 0 ? void 0 : question.cta_text }))));
25
+ react_1.default.createElement(QuestionDescription_1.default, { description: question.description }))));
28
26
  }
29
27
  return null;
30
28
  }
@@ -6,7 +6,6 @@ const QuestionTitle_1 = tslib_1.__importDefault(require("../QuestionTitle/Questi
6
6
  const QuestionDescription_1 = tslib_1.__importDefault(require("../QuestionDescription/QuestionDescription"));
7
7
  const utils_1 = require("../../utils");
8
8
  const context_1 = tslib_1.__importDefault(require("../CioQuiz/context"));
9
- const ControlBar_1 = tslib_1.__importDefault(require("../ControlBar/ControlBar"));
10
9
  function OpenTextQuestion() {
11
10
  var _a;
12
11
  const { state, getOpenTextInputProps } = (0, react_1.useContext)(context_1.default);
@@ -24,8 +23,7 @@ function OpenTextQuestion() {
24
23
  react_1.default.createElement("div", { className: 'cio-question-content' },
25
24
  react_1.default.createElement(QuestionTitle_1.default, { title: question.title }),
26
25
  react_1.default.createElement(QuestionDescription_1.default, { description: question.description }),
27
- getOpenTextInputProps && react_1.default.createElement("input", Object.assign({}, getOpenTextInputProps())),
28
- react_1.default.createElement(ControlBar_1.default, { ctaButtonText: question === null || question === void 0 ? void 0 : question.cta_text }))));
26
+ getOpenTextInputProps && react_1.default.createElement("input", Object.assign({}, getOpenTextInputProps())))));
29
27
  }
30
28
  return null;
31
29
  }
@@ -6,7 +6,6 @@ const QuestionTitle_1 = tslib_1.__importDefault(require("../QuestionTitle/Questi
6
6
  const QuestionDescription_1 = tslib_1.__importDefault(require("../QuestionDescription/QuestionDescription"));
7
7
  const context_1 = tslib_1.__importDefault(require("../CioQuiz/context"));
8
8
  const utils_1 = require("../../utils");
9
- const ControlBar_1 = tslib_1.__importDefault(require("../ControlBar/ControlBar"));
10
9
  const actions_1 = require("../CioQuiz/actions");
11
10
  function SelectTypeQuestion() {
12
11
  var _a;
@@ -29,8 +28,7 @@ function SelectTypeQuestion() {
29
28
  ? 'cio-question-options-container-text-only'
30
29
  : 'cio-question-options-container'}` }, (_a = question === null || question === void 0 ? void 0 : question.options) === null || _a === void 0 ? void 0 : _a.map((option) => getSelectInputProps && (react_1.default.createElement("div", Object.assign({}, getSelectInputProps(option)),
31
30
  option.images ? (0, utils_1.renderImages)(option.images, 'cio-question-option-image') : '',
32
- react_1.default.createElement("div", { className: 'cio-question-option-value' }, option === null || option === void 0 ? void 0 : option.value))))),
33
- react_1.default.createElement(ControlBar_1.default, { ctaButtonText: (question === null || question === void 0 ? void 0 : question.cta_text) || 'Continue' })));
31
+ react_1.default.createElement("div", { className: 'cio-question-option-value' }, option === null || option === void 0 ? void 0 : option.value)))))));
34
32
  }
35
33
  return null;
36
34
  }
@@ -2,11 +2,12 @@ import React, { useEffect, useState } from 'react';
2
2
  import QuizContext from './context';
3
3
  import QuizQuestions from '../QuizQuestions';
4
4
  import ResultContainer from '../ResultContainer/ResultContainer';
5
+ import ControlBar from '../ControlBar/ControlBar';
5
6
  import { RequestStates } from '../../constants';
6
7
  import Spinner from '../Spinner/Spinner';
7
8
  import useQuiz from '../../hooks/useQuiz';
8
9
  import SessionPromptModal from '../SessionPromptModal/SessionPromptModal';
9
- import { convertPrimaryColorsToString } from '../../utils';
10
+ import { convertPrimaryColorsToString, renderImages } from '../../utils';
10
11
  export default function CioQuiz(props) {
11
12
  const { cioClient, state, events: { hydrateQuiz, hasSessionStorageState, resetSessionStorageState }, getAddToCartButtonProps, getCoverQuestionProps, getHydrateQuizButtonProps, getNextQuestionButtonProps, getOpenTextInputProps, getPreviousQuestionButtonProps, getQuizImageProps, getQuizResultButtonProps, getQuizResultLinkProps, getResetQuizButtonProps, getSelectInputProps, primaryColorStyles, } = useQuiz(props);
12
13
  const [showSessionPrompt, setShowSessionPrompt] = useState(false);
@@ -43,16 +44,23 @@ export default function CioQuiz(props) {
43
44
  primaryColorStyles,
44
45
  };
45
46
  if (state.quiz.requestState === RequestStates.Loading) {
46
- return (React.createElement("div", { className: 'cio-quiz' },
47
+ return (React.createElement("div", { className: 'cio-quiz cio-quiz-loading' },
47
48
  React.createElement(Spinner, null)));
48
49
  }
50
+ const questionData = state.quiz.currentQuestion?.next_question;
51
+ const questionType = questionData?.type;
52
+ const questionImages = questionData?.images;
53
+ const displayBackgroundImage = (questionType === 'single' || questionType === 'multiple') && questionImages;
49
54
  if (state.quiz.requestState === RequestStates.Success) {
50
55
  return (React.createElement("div", { className: 'cio-quiz' },
56
+ displayBackgroundImage && renderImages(questionImages, 'cio-question-background-image'),
51
57
  React.createElement("style", null,
52
58
  ".cio-quiz ",
53
59
  convertPrimaryColorsToString(primaryColorStyles)),
54
60
  React.createElement(SessionPromptModal, { resetStoredState: resetSessionStorageState, continueSession: hydrateQuiz, showSessionPrompt: showSessionPrompt, setShowSessionPrompt: setShowSessionPrompt }),
55
- React.createElement(QuizContext.Provider, { value: contextValue }, state.quiz.results || state.quiz.skipToResults ? (React.createElement(ResultContainer, { options: resultsPageOptions })) : (state.quiz.currentQuestion && React.createElement(QuizQuestions, null)))));
61
+ React.createElement(QuizContext.Provider, { value: contextValue }, state.quiz.results || state.quiz.skipToResults ? (React.createElement(ResultContainer, { options: resultsPageOptions })) : (state.quiz.currentQuestion && (React.createElement(React.Fragment, null,
62
+ React.createElement(QuizQuestions, null),
63
+ React.createElement(ControlBar, { ctaButtonText: questionData?.cta_text || undefined })))))));
56
64
  }
57
65
  return null;
58
66
  }
@@ -3,7 +3,6 @@ import QuestionTitle from '../QuestionTitle/QuestionTitle';
3
3
  import QuizContext from '../CioQuiz/context';
4
4
  import QuestionDescription from '../QuestionDescription/QuestionDescription';
5
5
  import { renderImages } from '../../utils';
6
- import ControlBar from '../ControlBar/ControlBar';
7
6
  export default function CoverTypeQuestion() {
8
7
  const { state } = useContext(QuizContext);
9
8
  let question;
@@ -19,8 +18,7 @@ export default function CoverTypeQuestion() {
19
18
  hasImage ? renderImages(question.images, 'cio-question-image-container') : '',
20
19
  React.createElement("div", { className: 'cio-question-content' },
21
20
  React.createElement(QuestionTitle, { title: question?.title }),
22
- React.createElement(QuestionDescription, { description: question.description }),
23
- React.createElement(ControlBar, { ctaButtonText: question?.cta_text }))));
21
+ React.createElement(QuestionDescription, { description: question.description }))));
24
22
  }
25
23
  return null;
26
24
  }
@@ -3,7 +3,6 @@ import QuestionTitle from '../QuestionTitle/QuestionTitle';
3
3
  import QuestionDescription from '../QuestionDescription/QuestionDescription';
4
4
  import { renderImages } from '../../utils';
5
5
  import QuizContext from '../CioQuiz/context';
6
- import ControlBar from '../ControlBar/ControlBar';
7
6
  function OpenTextQuestion() {
8
7
  const { state, getOpenTextInputProps } = useContext(QuizContext);
9
8
  let question;
@@ -20,8 +19,7 @@ function OpenTextQuestion() {
20
19
  React.createElement("div", { className: 'cio-question-content' },
21
20
  React.createElement(QuestionTitle, { title: question.title }),
22
21
  React.createElement(QuestionDescription, { description: question.description }),
23
- getOpenTextInputProps && React.createElement("input", { ...getOpenTextInputProps() }),
24
- React.createElement(ControlBar, { ctaButtonText: question?.cta_text }))));
22
+ getOpenTextInputProps && React.createElement("input", { ...getOpenTextInputProps() }))));
25
23
  }
26
24
  return null;
27
25
  }
@@ -3,7 +3,6 @@ import QuestionTitle from '../QuestionTitle/QuestionTitle';
3
3
  import QuestionDescription from '../QuestionDescription/QuestionDescription';
4
4
  import QuizContext from '../CioQuiz/context';
5
5
  import { renderImages } from '../../utils';
6
- import ControlBar from '../ControlBar/ControlBar';
7
6
  import { QuestionTypes } from '../CioQuiz/actions';
8
7
  function SelectTypeQuestion() {
9
8
  const { state, getSelectInputProps } = useContext(QuizContext);
@@ -25,8 +24,7 @@ function SelectTypeQuestion() {
25
24
  ? 'cio-question-options-container-text-only'
26
25
  : 'cio-question-options-container'}` }, question?.options?.map((option) => getSelectInputProps && (React.createElement("div", { ...getSelectInputProps(option) },
27
26
  option.images ? renderImages(option.images, 'cio-question-option-image') : '',
28
- React.createElement("div", { className: 'cio-question-option-value' }, option?.value))))),
29
- React.createElement(ControlBar, { ctaButtonText: question?.cta_text || 'Continue' })));
27
+ React.createElement("div", { className: 'cio-question-option-value' }, option?.value)))))));
30
28
  }
31
29
  return null;
32
30
  }
package/lib/styles.css CHANGED
@@ -57,13 +57,17 @@
57
57
  min-height: 100%;
58
58
  height: 100%;
59
59
  overflow: auto;
60
- display: flex;
61
- justify-content: center;
62
60
  background-color: #ffffff;
63
61
  color: var(--gray-dust-500);
64
62
  font-size: 16px;
65
63
  }
66
64
 
65
+ /* Container for the loading spinner */
66
+ .cio-quiz.cio-quiz-loading {
67
+ display: flex;
68
+ justify-content: center;
69
+ }
70
+
67
71
  .cio-quiz button {
68
72
  cursor: pointer;
69
73
  }
@@ -77,7 +81,9 @@
77
81
  width: 100%;
78
82
  position: relative;
79
83
  align-self: start;
80
- min-height: calc(100% - 2rem); /* Full height - margin */
84
+ height: calc(
85
+ 100% - 2rem - calc(var(--bottom-bar-height))
86
+ ); /* Full height - margin - control bar */
81
87
  }
82
88
  .cio-container--with-image {
83
89
  display: flex;
@@ -86,7 +92,15 @@
86
92
  padding-bottom: var(--bottom-bar-height);
87
93
  position: relative;
88
94
  align-self: start;
89
- min-height: 100%;
95
+ height: calc(100% - calc(var(--bottom-bar-height))); /* Full height - margin - control bar */
96
+ }
97
+
98
+ /* Background image */
99
+ .cio-question-background-image {
100
+ height: calc(100% - 4px);
101
+ width: 100%;
102
+ position: absolute;
103
+ z-index: -1;
90
104
  }
91
105
 
92
106
  /* Session Prompt Modal */
@@ -163,8 +177,9 @@
163
177
  width: 100%;
164
178
  object-fit: cover;
165
179
  max-height: var(--container-image-small-height);
166
- height: var(--container-image-small-height); /* Fixed height for layout shifts*/
180
+ height: var(--container-image-small-height); /* Fixed height for layout shifts */
167
181
  display: flex;
182
+ align-self: stretch;
168
183
  }
169
184
 
170
185
  /* Input */
@@ -192,7 +207,7 @@
192
207
  height: var(--bottom-bar-height);
193
208
  padding: 8px 16px;
194
209
  display: flex;
195
- position: absolute;
210
+ position: sticky;
196
211
  bottom: 0px;
197
212
  left: 0px;
198
213
  background: white;
@@ -280,6 +295,7 @@
280
295
  display: flex;
281
296
  flex-direction: column;
282
297
  cursor: pointer;
298
+ background-color: white;
283
299
  }
284
300
  .cio-question-option-container.selected {
285
301
  outline: 3px solid var(--primary-color-variant-600);
@@ -302,12 +318,15 @@
302
318
  display: flex;
303
319
  flex-direction: column;
304
320
  align-items: center;
305
- align-self: start;
306
321
  max-width: 1200px;
307
322
  padding: 1rem;
308
323
  margin-top: 2rem;
309
- min-height: calc(100% - 3rem); /* Full height - padding - margin */
324
+ min-height: calc(
325
+ 100% - 2rem - calc(var(--bottom-bar-height))
326
+ ); /* Full height - padding - margin */
310
327
  width: 100%;
328
+ margin-right: auto;
329
+ margin-left: auto;
311
330
  }
312
331
  .cio-question-options-container {
313
332
  display: flex;
@@ -337,6 +356,7 @@
337
356
  width: 100%;
338
357
  margin: auto;
339
358
  cursor: pointer;
359
+ background-color: white;
340
360
  }
341
361
 
342
362
  /* Option Image */
@@ -383,6 +403,8 @@
383
403
  padding: 2rem 1rem;
384
404
  display: flex;
385
405
  flex-direction: column;
406
+ margin-right: auto;
407
+ margin-left: auto;
386
408
  }
387
409
  .cio-results-title {
388
410
  margin-top: 0;
@@ -579,7 +601,6 @@
579
601
 
580
602
  /* Image */
581
603
  .cio-question-image-container {
582
- height: 100%;
583
604
  flex-basis: 50%;
584
605
  flex-shrink: 0;
585
606
  border-radius: 4px;
@@ -628,6 +649,7 @@
628
649
  .cio-container {
629
650
  align-items: center;
630
651
  margin-top: 0;
652
+ height: calc(100% - calc(var(--bottom-bar-height))); /* Full height - control bar */
631
653
  }
632
654
  .cio-container--with-image {
633
655
  padding: 6% 2%;
@@ -646,10 +668,8 @@
646
668
 
647
669
  /* Image */
648
670
  .cio-question-image-container {
649
- max-height: 100%;
650
- }
651
- .cio-cover-question-container--with-image .cio-question-image-container {
652
671
  max-height: unset;
672
+ height: unset;
653
673
  }
654
674
 
655
675
  /* Content */
@@ -667,14 +687,6 @@
667
687
  margin-bottom: 2rem;
668
688
  }
669
689
 
670
- /* CTA Button Component */
671
- .cio-question-buttons-container {
672
- position: sticky;
673
- padding: 0;
674
- margin: 0;
675
- align-items: center;
676
- }
677
-
678
690
  /* Cover Component */
679
691
  .cio-cover-question-container--with-image {
680
692
  padding: 0;
@@ -691,9 +703,11 @@
691
703
  }
692
704
  .cio-select-question-container {
693
705
  justify-content: center;
694
- margin: 0;
706
+ margin-bottom: 0;
707
+ margin-top: 0;
695
708
  padding: 2rem;
696
709
  padding-bottom: 0;
710
+ min-height: calc(100% - calc(var(--bottom-bar-height))); /* Full height - padding - margin */
697
711
  }
698
712
  .cio-question-option-container {
699
713
  width: calc(25% - 13px);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructor-io/constructorio-ui-quizzes",
3
- "version": "1.4.7",
3
+ "version": "1.5.0",
4
4
  "description": "Constructor.io Quizzes UI library for web applications",
5
5
  "author": "constructor.io",
6
6
  "license": "MIT",