@constructor-io/constructorio-ui-quizzes 1.6.0 → 1.7.1

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.
@@ -11,6 +11,7 @@ const Spinner_1 = tslib_1.__importDefault(require("../Spinner/Spinner"));
11
11
  const useQuiz_1 = tslib_1.__importDefault(require("../../hooks/useQuiz"));
12
12
  const SessionPromptModal_1 = tslib_1.__importDefault(require("../SessionPromptModal/SessionPromptModal"));
13
13
  const utils_1 = require("../../utils");
14
+ const ProgressBar_1 = tslib_1.__importDefault(require("../ProgressBar/ProgressBar"));
14
15
  function CioQuiz(props) {
15
16
  var _a;
16
17
  const { cioClient, state, events: { hydrateQuiz, hasSessionStorageState, resetSessionStorageState }, getAddToCartButtonProps, getAddToFavoritesButtonProps, getCoverQuestionProps, getHydrateQuizButtonProps, getNextQuestionButtonProps, getOpenTextInputProps, getPreviousQuestionButtonProps, getQuizImageProps, getQuizResultButtonProps, getQuizResultLinkProps, getResetQuizButtonProps, getSelectInputProps, primaryColorStyles, } = (0, useQuiz_1.default)(props);
@@ -65,6 +66,7 @@ function CioQuiz(props) {
65
66
  (0, utils_1.convertPrimaryColorsToString)(primaryColorStyles)),
66
67
  react_1.default.createElement(SessionPromptModal_1.default, { resetStoredState: resetSessionStorageState, continueSession: hydrateQuiz, showSessionPrompt: showSessionPrompt, setShowSessionPrompt: setShowSessionPrompt }),
67
68
  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,
69
+ react_1.default.createElement(ProgressBar_1.default, null),
68
70
  react_1.default.createElement(QuizQuestions_1.default, null),
69
71
  react_1.default.createElement(ControlBar_1.default, { ctaButtonText: (questionData === null || questionData === void 0 ? void 0 : questionData.cta_text) || undefined })))))));
70
72
  }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const react_1 = tslib_1.__importStar(require("react"));
5
+ const context_1 = tslib_1.__importDefault(require("../CioQuiz/context"));
6
+ function ProgressBar() {
7
+ const { state } = (0, react_1.useContext)(context_1.default);
8
+ const currentQuestion = state === null || state === void 0 ? void 0 : state.quiz.currentQuestion;
9
+ if (!currentQuestion)
10
+ return null;
11
+ return (react_1.default.createElement("div", { className: 'cio-question-progress-affixed-container' },
12
+ react_1.default.createElement("div", { className: 'cio-question-progress-progress-container' },
13
+ react_1.default.createElement("div", { className: 'cio-question-progress-progress-bar', style: {
14
+ width: `${((currentQuestion.next_question.id - 1) / currentQuestion.total_questions) * 100}%`,
15
+ } }))));
16
+ }
17
+ exports.default = ProgressBar;
@@ -12,9 +12,12 @@ function QuizQuestions() {
12
12
  const { state } = (0, react_1.useContext)(context_1.default);
13
13
  const nextQuestion = (_a = state === null || state === void 0 ? void 0 : state.quiz.currentQuestion) === null || _a === void 0 ? void 0 : _a.next_question;
14
14
  const questionTypes = (0, utils_1.getQuestionTypes)(nextQuestion === null || nextQuestion === void 0 ? void 0 : nextQuestion.type);
15
- return (react_1.default.createElement(react_1.default.Fragment, null,
16
- questionTypes.isOpenQuestion && react_1.default.createElement(OpenTextTypeQuestion_1.default, { key: nextQuestion === null || nextQuestion === void 0 ? void 0 : nextQuestion.id }),
17
- questionTypes.isCoverQuestion && react_1.default.createElement(CoverTypeQuestion_1.default, { key: nextQuestion === null || nextQuestion === void 0 ? void 0 : nextQuestion.id }),
18
- questionTypes.isSelectQuestion && react_1.default.createElement(SelectTypeQuestion_1.default, { key: nextQuestion === null || nextQuestion === void 0 ? void 0 : nextQuestion.id })));
15
+ if (nextQuestion) {
16
+ return (react_1.default.createElement(react_1.default.Fragment, null,
17
+ questionTypes.isOpenQuestion && react_1.default.createElement(OpenTextTypeQuestion_1.default, { key: nextQuestion === null || nextQuestion === void 0 ? void 0 : nextQuestion.id }),
18
+ questionTypes.isCoverQuestion && react_1.default.createElement(CoverTypeQuestion_1.default, { key: nextQuestion === null || nextQuestion === void 0 ? void 0 : nextQuestion.id }),
19
+ questionTypes.isSelectQuestion && react_1.default.createElement(SelectTypeQuestion_1.default, { key: nextQuestion === null || nextQuestion === void 0 ? void 0 : nextQuestion.id })));
20
+ }
21
+ return null;
19
22
  }
20
23
  exports.default = QuizQuestions;
@@ -20,7 +20,16 @@ const getQuizResults = (cioClient, quizId, parameters) => tslib_1.__awaiter(void
20
20
  exports.getQuizResults = getQuizResults;
21
21
  // Tracking requests
22
22
  const trackQuizResultsLoaded = (cioClient, quizResults) => {
23
+ var _a;
23
24
  const { quiz_id, quiz_session_id, quiz_version_id, result_id, request, response } = quizResults;
25
+ const items = (_a = response === null || response === void 0 ? void 0 : response.results) === null || _a === void 0 ? void 0 : _a.map((result) => {
26
+ var _a, _b;
27
+ return ({
28
+ itemId: (_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.id,
29
+ variationId: (_b = result === null || result === void 0 ? void 0 : result.data) === null || _b === void 0 ? void 0 : _b.variation_id,
30
+ itemName: result === null || result === void 0 ? void 0 : result.value,
31
+ });
32
+ });
24
33
  cioClient === null || cioClient === void 0 ? void 0 : cioClient.tracker.trackQuizResultsLoaded({
25
34
  quizId: quiz_id,
26
35
  quizVersionId: quiz_version_id,
@@ -30,6 +39,7 @@ const trackQuizResultsLoaded = (cioClient, quizResults) => {
30
39
  resultCount: response === null || response === void 0 ? void 0 : response.total_num_results,
31
40
  resultPage: request === null || request === void 0 ? void 0 : request.page,
32
41
  resultId: result_id,
42
+ items,
33
43
  });
34
44
  };
35
45
  exports.trackQuizResultsLoaded = trackQuizResultsLoaded;
@@ -64,6 +64,7 @@ const getMockState = (question) => ({
64
64
  isSingleQuestion: (question === null || question === void 0 ? void 0 : question.type) === 'single',
65
65
  isMultipleQuestion: (question === null || question === void 0 ? void 0 : question.type) === 'multiple',
66
66
  isSelectQuestion: (question === null || question === void 0 ? void 0 : question.type) === 'single',
67
+ total_questions: 1,
67
68
  },
68
69
  results: {
69
70
  response: {
@@ -8,6 +8,7 @@ import Spinner from '../Spinner/Spinner';
8
8
  import useQuiz from '../../hooks/useQuiz';
9
9
  import SessionPromptModal from '../SessionPromptModal/SessionPromptModal';
10
10
  import { convertPrimaryColorsToString, renderImages } from '../../utils';
11
+ import ProgressBar from '../ProgressBar/ProgressBar';
11
12
  export default function CioQuiz(props) {
12
13
  const { cioClient, state, events: { hydrateQuiz, hasSessionStorageState, resetSessionStorageState }, getAddToCartButtonProps, getAddToFavoritesButtonProps, getCoverQuestionProps, getHydrateQuizButtonProps, getNextQuestionButtonProps, getOpenTextInputProps, getPreviousQuestionButtonProps, getQuizImageProps, getQuizResultButtonProps, getQuizResultLinkProps, getResetQuizButtonProps, getSelectInputProps, primaryColorStyles, } = useQuiz(props);
13
14
  const [showSessionPrompt, setShowSessionPrompt] = useState(false);
@@ -61,6 +62,7 @@ export default function CioQuiz(props) {
61
62
  convertPrimaryColorsToString(primaryColorStyles)),
62
63
  React.createElement(SessionPromptModal, { resetStoredState: resetSessionStorageState, continueSession: hydrateQuiz, showSessionPrompt: showSessionPrompt, setShowSessionPrompt: setShowSessionPrompt }),
63
64
  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,
65
+ React.createElement(ProgressBar, null),
64
66
  React.createElement(QuizQuestions, null),
65
67
  React.createElement(ControlBar, { ctaButtonText: questionData?.cta_text || undefined })))))));
66
68
  }
@@ -0,0 +1,13 @@
1
+ import React, { useContext } from 'react';
2
+ import QuizContext from '../CioQuiz/context';
3
+ export default function ProgressBar() {
4
+ const { state } = useContext(QuizContext);
5
+ const currentQuestion = state?.quiz.currentQuestion;
6
+ if (!currentQuestion)
7
+ return null;
8
+ return (React.createElement("div", { className: 'cio-question-progress-affixed-container' },
9
+ React.createElement("div", { className: 'cio-question-progress-progress-container' },
10
+ React.createElement("div", { className: 'cio-question-progress-progress-bar', style: {
11
+ width: `${((currentQuestion.next_question.id - 1) / currentQuestion.total_questions) * 100}%`,
12
+ } }))));
13
+ }
@@ -8,8 +8,11 @@ export default function QuizQuestions() {
8
8
  const { state } = useContext(QuizContext);
9
9
  const nextQuestion = state?.quiz.currentQuestion?.next_question;
10
10
  const questionTypes = getQuestionTypes(nextQuestion?.type);
11
- return (React.createElement(React.Fragment, null,
12
- questionTypes.isOpenQuestion && React.createElement(OpenTextQuestion, { key: nextQuestion?.id }),
13
- questionTypes.isCoverQuestion && React.createElement(CoverTypeQuestion, { key: nextQuestion?.id }),
14
- questionTypes.isSelectQuestion && React.createElement(SelectTypeQuestion, { key: nextQuestion?.id })));
11
+ if (nextQuestion) {
12
+ return (React.createElement(React.Fragment, null,
13
+ questionTypes.isOpenQuestion && React.createElement(OpenTextQuestion, { key: nextQuestion?.id }),
14
+ questionTypes.isCoverQuestion && React.createElement(CoverTypeQuestion, { key: nextQuestion?.id }),
15
+ questionTypes.isSelectQuestion && React.createElement(SelectTypeQuestion, { key: nextQuestion?.id })));
16
+ }
17
+ return null;
15
18
  }
@@ -14,6 +14,11 @@ export const getQuizResults = async (cioClient, quizId, parameters) => cioClient
14
14
  // Tracking requests
15
15
  export const trackQuizResultsLoaded = (cioClient, quizResults) => {
16
16
  const { quiz_id, quiz_session_id, quiz_version_id, result_id, request, response } = quizResults;
17
+ const items = response?.results?.map((result) => ({
18
+ itemId: result?.data?.id,
19
+ variationId: result?.data?.variation_id,
20
+ itemName: result?.value,
21
+ }));
17
22
  cioClient?.tracker.trackQuizResultsLoaded({
18
23
  quizId: quiz_id,
19
24
  quizVersionId: quiz_version_id,
@@ -23,6 +28,7 @@ export const trackQuizResultsLoaded = (cioClient, quizResults) => {
23
28
  resultCount: response?.total_num_results,
24
29
  resultPage: request?.page,
25
30
  resultId: result_id,
31
+ items,
26
32
  });
27
33
  };
28
34
  export const trackQuizResultClick = (cioClient, quizResults, result, position) => {
@@ -76,6 +76,7 @@ export const getMockState = (question) => ({
76
76
  isSingleQuestion: question?.type === 'single',
77
77
  isMultipleQuestion: question?.type === 'multiple',
78
78
  isSelectQuestion: question?.type === 'single',
79
+ total_questions: 1,
79
80
  },
80
81
  results: {
81
82
  response: {
package/lib/styles.css CHANGED
@@ -284,6 +284,9 @@
284
284
  padding: 0;
285
285
  padding-bottom: var(--bottom-bar-height);
286
286
  }
287
+ .cio-cover-question-container--with-image .cio-question-image {
288
+ height: auto;
289
+ }
287
290
 
288
291
  /** Select Component */
289
292
  /* Options */
@@ -395,6 +398,35 @@
395
398
  margin-bottom: -1rem;
396
399
  }
397
400
 
401
+ /* Affixed progress bar */
402
+ .cio-quiz .cio-question-progress-affixed-container {
403
+ position: fixed;
404
+ top: 8px;
405
+ right: 16px;
406
+ z-index: 100;
407
+ display: flex;
408
+ flex-direction: row;
409
+ align-items: center;
410
+ gap: 7px;
411
+ font-size: 0.75rem;
412
+ padding: 8px;
413
+ color: white;
414
+ mix-blend-mode: difference;
415
+ }
416
+ .cio-quiz .cio-question-progress-progress-container {
417
+ width: 100px;
418
+ border-color: white;
419
+ height: 6px;
420
+ border-width: 1px;
421
+ border-style: solid;
422
+ background: transparent;
423
+ border-radius: 4px;
424
+ }
425
+ .cio-quiz .cio-question-progress-progress-bar {
426
+ background: white;
427
+ height: 100%;
428
+ }
429
+
398
430
  /* Results component */
399
431
  .cio-quiz .cio-results-container {
400
432
  width: 100%;
@@ -605,7 +637,7 @@
605
637
  margin-top: 1px;
606
638
  }
607
639
 
608
- /* Media Queries */
640
+ /* Container Queries */
609
641
 
610
642
  /* Small Tablet */
611
643
  @container quiz (min-width: 640px) {
@@ -745,7 +777,6 @@
745
777
  flex-wrap: wrap;
746
778
  justify-content: center;
747
779
  margin-bottom: 2rem;
748
- margin-top: 0;
749
780
  }
750
781
  .cio-quiz .cio-question-option-container-text-only {
751
782
  margin: 0;
@@ -0,0 +1,2 @@
1
+ /// <reference types="react" />
2
+ export default function ProgressBar(): JSX.Element | null;
@@ -1,2 +1,2 @@
1
1
  /// <reference types="react" />
2
- export default function QuizQuestions(): JSX.Element;
2
+ export default function QuizQuestions(): JSX.Element | null;
@@ -2,12 +2,12 @@ import { Question } from '@constructor-io/constructorio-client-javascript/lib/ty
2
2
  import { QuizReturnState } from '../../../types';
3
3
  import { QuestionTypes } from '../../../components/CioQuiz/actions';
4
4
  import { QuizContextValue } from '../../../components/CioQuiz/context';
5
- export declare const getMockQuestion: (type: QuestionTypes) => {
5
+ export declare const getMockQuestion: (type: `${QuestionTypes}`) => {
6
6
  id: number;
7
7
  title: string;
8
8
  description: string;
9
9
  cta_text: string;
10
- type: QuestionTypes;
10
+ type: "reset" | "open" | "cover" | "single" | "multiple" | "next" | "back" | "hydrate" | "complete";
11
11
  input_placeholder: string;
12
12
  };
13
13
  export declare const getMockQuestionWithImage: (type: QuestionTypes) => {
@@ -18,7 +18,7 @@ export declare const getMockQuestionWithImage: (type: QuestionTypes) => {
18
18
  title: string;
19
19
  description: string;
20
20
  cta_text: string;
21
- type: QuestionTypes;
21
+ type: "reset" | "open" | "cover" | "single" | "multiple" | "next" | "back" | "hydrate" | "complete";
22
22
  input_placeholder: string;
23
23
  };
24
24
  export declare const questionOptionsWithImages: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructor-io/constructorio-ui-quizzes",
3
- "version": "1.6.0",
3
+ "version": "1.7.1",
4
4
  "description": "Constructor.io Quizzes UI library for web applications",
5
5
  "author": "constructor.io",
6
6
  "license": "MIT",
@@ -58,7 +58,7 @@
58
58
  "check-license": "license-checker --production --onlyAllow 'Apache-2.0;BSD-3-Clause;MIT;0BSD;BSD-2-Clause' --excludePackages 'picocolors@1.0.0'"
59
59
  },
60
60
  "peerDependencies": {
61
- "@constructor-io/constructorio-client-javascript": "^2.35.14",
61
+ "@constructor-io/constructorio-client-javascript": "^2.35.17",
62
62
  "react": ">=16.12.0",
63
63
  "react-dom": ">=16.12.0",
64
64
  "tslib": "^2.4.0"
@@ -71,6 +71,7 @@
71
71
  "@storybook/addon-essentials": "7.0.11",
72
72
  "@storybook/addon-interactions": "^7.0.11",
73
73
  "@storybook/addon-links": "7.0.11",
74
+ "@storybook/addon-docs": "7.0.11",
74
75
  "@storybook/jest": "^0.1.0",
75
76
  "@storybook/react-webpack5": "7.0.11",
76
77
  "@storybook/test-runner": "0.10.0",
@@ -79,6 +80,7 @@
79
80
  "@types/react-dom": "^18.0.9",
80
81
  "@typescript-eslint/eslint-plugin": "^5.47.0",
81
82
  "@typescript-eslint/parser": "^5.47.0",
83
+ "chromatic": "^6.21.0",
82
84
  "eslint": "^8.30.0",
83
85
  "eslint-config-airbnb": "^19.0.4",
84
86
  "eslint-config-airbnb-typescript": "^17.0.0",