@constructor-io/constructorio-ui-quizzes 1.3.6 → 1.3.8

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,9 +5,10 @@ const react_1 = tslib_1.__importDefault(require("react"));
5
5
  const BackButton_1 = tslib_1.__importDefault(require("../BackButton/BackButton"));
6
6
  const CTAButton_1 = tslib_1.__importDefault(require("../CTAButton/CTAButton"));
7
7
  function ControlBar(props) {
8
- const { showBackButton, backButtonHandler, ctaButtonText, nextButtonHandler, isNextButtonDisabled, } = props;
8
+ const { showBackButton, backButtonHandler, ctaButtonText, nextButtonHandler, isNextButtonDisabled, instructions, } = props;
9
9
  return (react_1.default.createElement("div", { className: 'cio-question-buttons-container' },
10
10
  showBackButton && react_1.default.createElement(BackButton_1.default, { onClick: backButtonHandler }),
11
+ instructions && react_1.default.createElement("div", { className: 'cio-question-buttons-container-text' }, instructions),
11
12
  react_1.default.createElement(CTAButton_1.default, { disabled: isNextButtonDisabled, ctaText: ctaButtonText, onClick: nextButtonHandler })));
12
13
  }
13
14
  exports.default = ControlBar;
@@ -25,11 +25,11 @@ function CoverTypeQuestion() {
25
25
  cio-container${hasImage ? '--with-image' : ''}
26
26
  cio-cover-question-container${hasImage ? '--with-image' : ''}
27
27
  `, "data-question-key": question.key },
28
+ hasImage ? (0, utils_1.renderImages)(question.images, 'cio-question-image-container') : '',
28
29
  react_1.default.createElement("div", { className: 'cio-question-content' },
29
30
  react_1.default.createElement(QuestionTitle_1.default, { title: question === null || question === void 0 ? void 0 : question.title }),
30
31
  react_1.default.createElement(QuestionDescription_1.default, { description: question.description }),
31
- react_1.default.createElement(ControlBar_1.default, { nextButtonHandler: onNextClick, backButtonHandler: previousQuestion, showBackButton: !(state === null || state === void 0 ? void 0 : state.quiz.isFirstQuestion), ctaButtonText: question === null || question === void 0 ? void 0 : question.cta_text })),
32
- hasImage ? (0, utils_1.renderImages)(question.images, 'cio-question-image-container') : ''));
32
+ react_1.default.createElement(ControlBar_1.default, { nextButtonHandler: onNextClick, backButtonHandler: previousQuestion, showBackButton: !(state === null || state === void 0 ? void 0 : state.quiz.isFirstQuestion), ctaButtonText: question === null || question === void 0 ? void 0 : question.cta_text }))));
33
33
  }
34
34
  return null;
35
35
  }
@@ -14,10 +14,12 @@ function SelectTypeQuestion() {
14
14
  let question;
15
15
  let type;
16
16
  let hasImages = false;
17
+ let instructions;
17
18
  if (state === null || state === void 0 ? void 0 : state.quiz.currentQuestion) {
18
19
  question = state.quiz.currentQuestion.next_question;
19
20
  type = question.type;
20
21
  hasImages = question.options.some((option) => option.images);
22
+ instructions = type === actions_1.QuestionTypes.MultipleSelect && 'Select one or more options';
21
23
  }
22
24
  const [selected, setSelected] = (0, react_1.useState)({});
23
25
  const isDisabled = Object.keys(selected).length === 0;
@@ -76,7 +78,7 @@ function SelectTypeQuestion() {
76
78
  }, role: 'button', tabIndex: 0, key: option.id },
77
79
  option.images ? (0, utils_1.renderImages)(option.images, 'cio-question-option-image') : '',
78
80
  react_1.default.createElement("div", { className: 'cio-question-option-value' }, option === null || option === void 0 ? void 0 : option.value))))),
79
- react_1.default.createElement(ControlBar_1.default, { nextButtonHandler: onNextClick, isNextButtonDisabled: isDisabled, backButtonHandler: previousQuestion, showBackButton: !(state === null || state === void 0 ? void 0 : state.quiz.isFirstQuestion), ctaButtonText: question === null || question === void 0 ? void 0 : question.cta_text })));
81
+ react_1.default.createElement(ControlBar_1.default, { nextButtonHandler: onNextClick, isNextButtonDisabled: isDisabled, backButtonHandler: previousQuestion, showBackButton: !(state === null || state === void 0 ? void 0 : state.quiz.isFirstQuestion), ctaButtonText: question === null || question === void 0 ? void 0 : question.cta_text, instructions: instructions })));
80
82
  }
81
83
  return null;
82
84
  }
package/lib/cjs/utils.js CHANGED
@@ -1,6 +1,6 @@
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.defaultOnQuizResultsLoadedCode = exports.defaultOnQuizResultClickCode = exports.defaultOnAddToCartClickCode = exports.getStoryParams = exports.renderImages = void 0;
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;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const actions_1 = require("./components/CioQuiz/actions");
@@ -41,29 +41,35 @@ ${templateCode}
41
41
  };
42
42
  };
43
43
  exports.getStoryParams = getStoryParams;
44
- exports.defaultOnAddToCartClickCode = `"onAddToCartClick": (item) => console.dir(item)`;
45
- exports.defaultOnQuizResultClickCode = `"onQuizResultClick": (result, position) => console.dir(result, position)`;
46
- exports.defaultOnQuizResultsLoadedCode = `"onQuizResultsLoaded": (results) => console.dir(results)`;
44
+ exports.functionStrings = {
45
+ onAddToCartClick: `(item) => console.dir(item)`,
46
+ onQuizResultClick: `(result, position) => console.dir(result, position)`,
47
+ onQuizResultsLoaded: `(results) => console.dir(results)`,
48
+ cioJsClient: `cioJsClient`,
49
+ };
47
50
  const stringifyWithDefaults = (obj) => {
48
- const { resultsPageOptions, cioJsClient } = obj, rest = tslib_1.__rest(obj, ["resultsPageOptions", "cioJsClient"]);
49
- const { onAddToCartClick, onQuizResultsLoaded, onQuizResultClick } = resultsPageOptions;
50
- let res = JSON.stringify(Object.assign(Object.assign({}, rest), { resultsPageOptions }), null, ' ');
51
- if (cioJsClient) {
52
- res = res.replace('"resultsPageOptions": {', `"cioJsClient": cioJsClient,
53
- "resultsPageOptions": {`);
54
- }
55
- if (onQuizResultsLoaded) {
56
- res = res.replace('"resultsPageOptions": {', `"resultsPageOptions": {
57
- ${exports.defaultOnQuizResultsLoadedCode},`);
58
- }
59
- if (onQuizResultClick) {
60
- res = res.replace('"resultsPageOptions": {', `"resultsPageOptions": {
61
- ${exports.defaultOnQuizResultClickCode},`);
62
- }
63
- if (onAddToCartClick) {
64
- res = res.replace('"resultsPageOptions": {', `"resultsPageOptions": {
65
- ${exports.defaultOnAddToCartClickCode},`);
66
- }
51
+ // Stringify non-function values normally. Add a template block for functions to be replaced later
52
+ const customJsonTransformer = (key, value) => {
53
+ if (value instanceof Function) {
54
+ return `${key}_CODE`;
55
+ }
56
+ if (key === 'cioJsClient') {
57
+ return `${key}_CODE`;
58
+ }
59
+ return value;
60
+ };
61
+ let res = JSON.stringify(obj, customJsonTransformer, ' ');
62
+ // Replace template blocks with function strings
63
+ Array.from(res.matchAll(/"(\w*)_CODE"/g)).forEach((match) => {
64
+ const [codePlaceholder, key] = match;
65
+ const functionString = exports.functionStrings[key];
66
+ if (functionString) {
67
+ res = res.replaceAll(codePlaceholder, functionString);
68
+ }
69
+ else {
70
+ console.error(`Function string for ${key} not found.`); // eslint-disable-line
71
+ }
72
+ });
67
73
  return res;
68
74
  };
69
75
  exports.stringifyWithDefaults = stringifyWithDefaults;
@@ -2,9 +2,10 @@ import React from 'react';
2
2
  import BackButton from '../BackButton/BackButton';
3
3
  import CTAButton from '../CTAButton/CTAButton';
4
4
  function ControlBar(props) {
5
- const { showBackButton, backButtonHandler, ctaButtonText, nextButtonHandler, isNextButtonDisabled, } = props;
5
+ const { showBackButton, backButtonHandler, ctaButtonText, nextButtonHandler, isNextButtonDisabled, instructions, } = props;
6
6
  return (React.createElement("div", { className: 'cio-question-buttons-container' },
7
7
  showBackButton && React.createElement(BackButton, { onClick: backButtonHandler }),
8
+ instructions && React.createElement("div", { className: 'cio-question-buttons-container-text' }, instructions),
8
9
  React.createElement(CTAButton, { disabled: isNextButtonDisabled, ctaText: ctaButtonText, onClick: nextButtonHandler })));
9
10
  }
10
11
  export default ControlBar;
@@ -21,11 +21,11 @@ export default function CoverTypeQuestion() {
21
21
  cio-container${hasImage ? '--with-image' : ''}
22
22
  cio-cover-question-container${hasImage ? '--with-image' : ''}
23
23
  `, "data-question-key": question.key },
24
+ hasImage ? renderImages(question.images, 'cio-question-image-container') : '',
24
25
  React.createElement("div", { className: 'cio-question-content' },
25
26
  React.createElement(QuestionTitle, { title: question?.title }),
26
27
  React.createElement(QuestionDescription, { description: question.description }),
27
- React.createElement(ControlBar, { nextButtonHandler: onNextClick, backButtonHandler: previousQuestion, showBackButton: !state?.quiz.isFirstQuestion, ctaButtonText: question?.cta_text })),
28
- hasImage ? renderImages(question.images, 'cio-question-image-container') : ''));
28
+ React.createElement(ControlBar, { nextButtonHandler: onNextClick, backButtonHandler: previousQuestion, showBackButton: !state?.quiz.isFirstQuestion, ctaButtonText: question?.cta_text }))));
29
29
  }
30
30
  return null;
31
31
  }
@@ -10,10 +10,12 @@ function SelectTypeQuestion() {
10
10
  let question;
11
11
  let type;
12
12
  let hasImages = false;
13
+ let instructions;
13
14
  if (state?.quiz.currentQuestion) {
14
15
  question = state.quiz.currentQuestion.next_question;
15
16
  type = question.type;
16
17
  hasImages = question.options.some((option) => option.images);
18
+ instructions = type === QuestionTypes.MultipleSelect && 'Select one or more options';
17
19
  }
18
20
  const [selected, setSelected] = useState({});
19
21
  const isDisabled = Object.keys(selected).length === 0;
@@ -71,7 +73,7 @@ function SelectTypeQuestion() {
71
73
  }, role: 'button', tabIndex: 0, key: option.id },
72
74
  option.images ? renderImages(option.images, 'cio-question-option-image') : '',
73
75
  React.createElement("div", { className: 'cio-question-option-value' }, option?.value))))),
74
- React.createElement(ControlBar, { nextButtonHandler: onNextClick, isNextButtonDisabled: isDisabled, backButtonHandler: previousQuestion, showBackButton: !state?.quiz.isFirstQuestion, ctaButtonText: question?.cta_text })));
76
+ React.createElement(ControlBar, { nextButtonHandler: onNextClick, isNextButtonDisabled: isDisabled, backButtonHandler: previousQuestion, showBackButton: !state?.quiz.isFirstQuestion, ctaButtonText: question?.cta_text, instructions: instructions })));
75
77
  }
76
78
  return null;
77
79
  }
package/lib/mjs/utils.js CHANGED
@@ -35,29 +35,35 @@ ${templateCode}
35
35
  },
36
36
  };
37
37
  };
38
- export const defaultOnAddToCartClickCode = `"onAddToCartClick": (item) => console.dir(item)`;
39
- export const defaultOnQuizResultClickCode = `"onQuizResultClick": (result, position) => console.dir(result, position)`;
40
- export const defaultOnQuizResultsLoadedCode = `"onQuizResultsLoaded": (results) => console.dir(results)`;
38
+ export const functionStrings = {
39
+ onAddToCartClick: `(item) => console.dir(item)`,
40
+ onQuizResultClick: `(result, position) => console.dir(result, position)`,
41
+ onQuizResultsLoaded: `(results) => console.dir(results)`,
42
+ cioJsClient: `cioJsClient`,
43
+ };
41
44
  export const stringifyWithDefaults = (obj) => {
42
- const { resultsPageOptions, cioJsClient, ...rest } = obj;
43
- const { onAddToCartClick, onQuizResultsLoaded, onQuizResultClick } = resultsPageOptions;
44
- let res = JSON.stringify({ ...rest, resultsPageOptions }, null, ' ');
45
- if (cioJsClient) {
46
- res = res.replace('"resultsPageOptions": {', `"cioJsClient": cioJsClient,
47
- "resultsPageOptions": {`);
48
- }
49
- if (onQuizResultsLoaded) {
50
- res = res.replace('"resultsPageOptions": {', `"resultsPageOptions": {
51
- ${defaultOnQuizResultsLoadedCode},`);
52
- }
53
- if (onQuizResultClick) {
54
- res = res.replace('"resultsPageOptions": {', `"resultsPageOptions": {
55
- ${defaultOnQuizResultClickCode},`);
56
- }
57
- if (onAddToCartClick) {
58
- res = res.replace('"resultsPageOptions": {', `"resultsPageOptions": {
59
- ${defaultOnAddToCartClickCode},`);
60
- }
45
+ // Stringify non-function values normally. Add a template block for functions to be replaced later
46
+ const customJsonTransformer = (key, value) => {
47
+ if (value instanceof Function) {
48
+ return `${key}_CODE`;
49
+ }
50
+ if (key === 'cioJsClient') {
51
+ return `${key}_CODE`;
52
+ }
53
+ return value;
54
+ };
55
+ let res = JSON.stringify(obj, customJsonTransformer, ' ');
56
+ // Replace template blocks with function strings
57
+ Array.from(res.matchAll(/"(\w*)_CODE"/g)).forEach((match) => {
58
+ const [codePlaceholder, key] = match;
59
+ const functionString = functionStrings[key];
60
+ if (functionString) {
61
+ res = res.replaceAll(codePlaceholder, functionString);
62
+ }
63
+ else {
64
+ console.error(`Function string for ${key} not found.`); // eslint-disable-line
65
+ }
66
+ });
61
67
  return res;
62
68
  };
63
69
  export const stringify = (obj) => JSON.stringify(obj, null, ' ');
package/lib/styles.css CHANGED
@@ -69,7 +69,6 @@
69
69
  /* Container */
70
70
  .cio-container {
71
71
  display: flex;
72
- align-items: center;
73
72
  justify-content: center;
74
73
  margin-top: 2rem;
75
74
  padding-bottom: var(--bottom-bar-height);
@@ -129,7 +128,6 @@
129
128
  .cio-question-content {
130
129
  display: flex;
131
130
  flex-direction: column;
132
- height: 100%;
133
131
  padding: 1rem;
134
132
  }
135
133
 
@@ -157,6 +155,7 @@
157
155
  width: 100%;
158
156
  object-fit: cover;
159
157
  max-height: var(--container-image-small-height);
158
+ height: var(--container-image-small-height); /* Fixed height for layout shifts*/
160
159
  display: flex;
161
160
  }
162
161
 
@@ -192,6 +191,9 @@
192
191
  background-color: rgba(255, 255, 255, 0.87);
193
192
  align-items: center;
194
193
  }
194
+ .cio-question-buttons-container-text {
195
+ display: none;
196
+ }
195
197
  .cio-question-cta-button {
196
198
  background: var(--primary-color);
197
199
  color: #ffffff;
@@ -254,7 +256,6 @@
254
256
 
255
257
  /* Cover Page Component */
256
258
  .cio-cover-question-container--with-image {
257
- flex-direction: column-reverse;
258
259
  padding: 0;
259
260
  padding-bottom: var(--bottom-bar-height);
260
261
  }
@@ -594,6 +595,15 @@
594
595
  .cio-result-card {
595
596
  flex-basis: 30%;
596
597
  }
598
+
599
+ /* Control Bar Instructions */
600
+ .cio-question-buttons-container-text {
601
+ text-align: center;
602
+ flex-grow: 1;
603
+ color: var(--gray-dust-100);
604
+ font-size: 1.125rem;
605
+ display: block;
606
+ }
597
607
  }
598
608
 
599
609
  /* Big Tablet */
@@ -608,6 +618,9 @@
608
618
  align-items: center;
609
619
  flex-direction: row;
610
620
  }
621
+ .cio-cover-question-container--with-image {
622
+ flex-direction: row-reverse;
623
+ }
611
624
 
612
625
  /* Input */
613
626
  .cio-question-input-text {
@@ -5,6 +5,7 @@ interface ControlBarProps {
5
5
  backButtonHandler?: () => void;
6
6
  nextButtonHandler: () => void;
7
7
  ctaButtonText?: string;
8
+ instructions?: string;
8
9
  }
9
10
  declare function ControlBar(props: ControlBarProps): JSX.Element;
10
11
  export default ControlBar;
@@ -12,9 +12,12 @@ export declare const getStoryParams: (storyCode: any, templateCode: any, importC
12
12
  };
13
13
  };
14
14
  };
15
- export declare const defaultOnAddToCartClickCode = "\"onAddToCartClick\": (item) => console.dir(item)";
16
- export declare const defaultOnQuizResultClickCode = "\"onQuizResultClick\": (result, position) => console.dir(result, position)";
17
- export declare const defaultOnQuizResultsLoadedCode = "\"onQuizResultsLoaded\": (results) => console.dir(results)";
15
+ export declare const functionStrings: {
16
+ onAddToCartClick: string;
17
+ onQuizResultClick: string;
18
+ onQuizResultsLoaded: string;
19
+ cioJsClient: string;
20
+ };
18
21
  export declare const stringifyWithDefaults: (obj: {
19
22
  cioJsClient?: any;
20
23
  resultsPageOptions: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructor-io/constructorio-ui-quizzes",
3
- "version": "1.3.6",
3
+ "version": "1.3.8",
4
4
  "description": "Constructor.io Quizzes UI library for web applications",
5
5
  "author": "constructor.io",
6
6
  "license": "MIT",