@pie-element/multiple-choice 13.3.4 → 13.3.5-ng.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 (117) hide show
  1. package/configure.js +2 -0
  2. package/controller.js +1 -0
  3. package/dist/author/defaults.d.ts +205 -0
  4. package/dist/author/defaults.js +151 -0
  5. package/dist/author/index.d.ts +26 -0
  6. package/dist/author/index.js +119 -0
  7. package/dist/author/main.d.ts +34 -0
  8. package/dist/author/main.js +287 -0
  9. package/dist/author/utils.d.ts +9 -0
  10. package/dist/author/utils.js +7 -0
  11. package/dist/browser/Radio-Bbu0BH_k.js +9581 -0
  12. package/dist/browser/Radio-Bbu0BH_k.js.map +1 -0
  13. package/dist/browser/author/index.js +37436 -0
  14. package/dist/browser/author/index.js.map +1 -0
  15. package/dist/browser/controller/index.js +204 -0
  16. package/dist/browser/controller/index.js.map +1 -0
  17. package/dist/browser/delivery/index.js +251 -0
  18. package/dist/browser/delivery/index.js.map +1 -0
  19. package/dist/browser/dist-CHbLnyuX.js +111 -0
  20. package/dist/browser/dist-CHbLnyuX.js.map +1 -0
  21. package/dist/browser/main-DahQxQZC.js +2451 -0
  22. package/dist/browser/main-DahQxQZC.js.map +1 -0
  23. package/dist/browser/multiple-choice.css +2 -0
  24. package/dist/browser/print/index.js +43 -0
  25. package/dist/browser/print/index.js.map +1 -0
  26. package/dist/controller/defaults.d.ts +35 -0
  27. package/dist/controller/defaults.js +29 -0
  28. package/dist/controller/index.d.ts +65 -0
  29. package/dist/controller/index.js +129 -0
  30. package/dist/controller/utils.d.ts +10 -0
  31. package/dist/controller/utils.js +8 -0
  32. package/dist/delivery/choice-input.d.ts +44 -0
  33. package/dist/delivery/choice-input.js +280 -0
  34. package/dist/delivery/choice.d.ts +20 -0
  35. package/dist/delivery/choice.js +105 -0
  36. package/dist/delivery/feedback-tick.d.ts +20 -0
  37. package/dist/delivery/feedback-tick.js +104 -0
  38. package/dist/delivery/index.d.ts +37 -0
  39. package/dist/delivery/index.js +215 -0
  40. package/dist/delivery/main.d.ts +31 -0
  41. package/dist/delivery/main.js +51 -0
  42. package/dist/delivery/multiple-choice.d.ts +61 -0
  43. package/dist/delivery/multiple-choice.js +245 -0
  44. package/dist/delivery/session-updater.d.ts +10 -0
  45. package/dist/delivery/session-updater.js +9 -0
  46. package/dist/delivery/utils.d.ts +10 -0
  47. package/dist/delivery/utils.js +4 -0
  48. package/dist/index.d.ts +1 -0
  49. package/dist/index.iife.d.ts +8 -0
  50. package/dist/index.iife.js +148 -0
  51. package/dist/index.js +2 -0
  52. package/dist/node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js +16 -0
  53. package/dist/print/index.d.ts +15 -0
  54. package/dist/print/index.js +43 -0
  55. package/dist/runtime-support.d.ts +12 -0
  56. package/dist/runtime-support.js +12 -0
  57. package/module/print.js +17945 -1
  58. package/module/print.js.map +1 -0
  59. package/package.json +94 -28
  60. package/CHANGELOG.json +0 -1972
  61. package/CHANGELOG.md +0 -2764
  62. package/LICENSE.md +0 -5
  63. package/PRINT.md +0 -35
  64. package/README.md +0 -56
  65. package/choice.png +0 -0
  66. package/configure/CHANGELOG.json +0 -1387
  67. package/configure/CHANGELOG.md +0 -2106
  68. package/configure/lib/defaults.js +0 -203
  69. package/configure/lib/defaults.js.map +0 -1
  70. package/configure/lib/index.js +0 -203
  71. package/configure/lib/index.js.map +0 -1
  72. package/configure/lib/main.js +0 -484
  73. package/configure/lib/main.js.map +0 -1
  74. package/configure/lib/utils.js +0 -18
  75. package/configure/lib/utils.js.map +0 -1
  76. package/configure/package.json +0 -22
  77. package/controller/CHANGELOG.json +0 -527
  78. package/controller/CHANGELOG.md +0 -1411
  79. package/controller/lib/defaults.js +0 -33
  80. package/controller/lib/defaults.js.map +0 -1
  81. package/controller/lib/index.js +0 -288
  82. package/controller/lib/index.js.map +0 -1
  83. package/controller/lib/utils.js +0 -15
  84. package/controller/lib/utils.js.map +0 -1
  85. package/controller/package.json +0 -15
  86. package/docs/config-schema.json +0 -2993
  87. package/docs/config-schema.json.md +0 -2217
  88. package/docs/demo/config.js +0 -8
  89. package/docs/demo/generate.js +0 -61
  90. package/docs/demo/index.html +0 -1
  91. package/docs/demo/session.js +0 -7
  92. package/docs/pie-schema.json +0 -1332
  93. package/docs/pie-schema.json.md +0 -1015
  94. package/lib/choice-input.js +0 -383
  95. package/lib/choice-input.js.map +0 -1
  96. package/lib/choice.js +0 -192
  97. package/lib/choice.js.map +0 -1
  98. package/lib/feedback-tick.js +0 -134
  99. package/lib/feedback-tick.js.map +0 -1
  100. package/lib/index.js +0 -403
  101. package/lib/index.js.map +0 -1
  102. package/lib/main.js +0 -63
  103. package/lib/main.js.map +0 -1
  104. package/lib/multiple-choice.js +0 -397
  105. package/lib/multiple-choice.js.map +0 -1
  106. package/lib/print.js +0 -94
  107. package/lib/print.js.map +0 -1
  108. package/lib/session-updater.js +0 -37
  109. package/lib/session-updater.js.map +0 -1
  110. package/module/configure.js +0 -1
  111. package/module/controller.js +0 -3034
  112. package/module/demo.js +0 -86
  113. package/module/element.js +0 -1
  114. package/module/index.html +0 -21
  115. package/module/manifest.json +0 -14
  116. package/module/print-demo.js +0 -124
  117. package/module/print.html +0 -18
@@ -0,0 +1,43 @@
1
+ import { F as e, M as t, Vt as n } from "../Radio-Bbu0BH_k.js";
2
+ import { t as r } from "../main-DahQxQZC.js";
3
+ import { c as i, l as a } from "../dist-CHbLnyuX.js";
4
+ import o from "react";
5
+ import { createRoot as s } from "react-dom/client";
6
+ var c = (0, (/* @__PURE__ */ n(e(), 1)).default)("pie-element:multiple-choice:print"), l = (e, t) => {
7
+ let n = t.role === "instructor";
8
+ return e.prompt = e.promptEnabled === !1 ? void 0 : e.prompt, e.teacherInstructions = n && e.teacherInstructionsEnabled !== !1 ? e.teacherInstructions : void 0, e.showTeacherInstructions = n, e.alwaysShowCorrect = n, e.mode = n ? "evaluate" : e.mode, e.disabled = !0, e.animationsDisabled = !0, e.lockChoiceOrder = !0, e.choicesLayout = e.choicesLayout || "vertical", e.choices = a(e.choices).map((t) => (t.rationale = n && e.rationaleEnabled !== !1 ? t.rationale : void 0, t.hideTick = n, t.feedback = void 0, t)), e.keyMode = e.choicePrefix || "letters", e;
9
+ }, u = class extends HTMLElement {
10
+ constructor() {
11
+ super(), this._options = null, this._model = null, this._session = [], this._root = null, this._rerender = i(() => {
12
+ if (this._model && this._session) {
13
+ let e = l(this._model, this._options), n = this._options && o.createElement(r, {
14
+ model: e,
15
+ session: {},
16
+ options: this._options
17
+ });
18
+ this._root ||= s(this), this._root.render(n), requestAnimationFrame(() => {
19
+ requestAnimationFrame(() => {
20
+ c("render complete - render math"), t(this);
21
+ });
22
+ });
23
+ } else c("skip");
24
+ }, 50, {
25
+ leading: !1,
26
+ trailing: !0
27
+ });
28
+ }
29
+ set options(e) {
30
+ this._options = e;
31
+ }
32
+ set model(e) {
33
+ this._model = e, this._rerender();
34
+ }
35
+ connectedCallback() {}
36
+ disconnectedCallback() {
37
+ this._root && this._root.unmount();
38
+ }
39
+ };
40
+ //#endregion
41
+ export { u as default };
42
+
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/print/index.tsx"],"sourcesContent":["// @ts-nocheck\n/**\n * @synced-from pie-elements/packages/multiple-choice/src/print.js\n * @auto-generated\n *\n * This file is automatically synced from pie-elements and converted to TypeScript.\n * Manual edits will be overwritten on next sync.\n * To make changes, edit the upstream JavaScript file and run sync again.\n */\n\nimport React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { cloneDeep, debounce } from '@pie-element/shared-lodash';\nimport Main from '../delivery/main.js';\nimport { renderMath } from '@pie-element/shared-math-rendering-mathjax';\nimport debug from 'debug';\n\nconst log = debug('pie-element:multiple-choice:print');\n\n/**\n * Live in same package as main element - so we can access some of the shared comps!\n *\n * - update pslb to build print if src/print.js is there\n * - update demo el\n * - get configure/controller building\n */\n\nconst preparePrintModel = (model, opts) => {\n const instr = opts.role === 'instructor';\n\n model.prompt = model.promptEnabled !== false ? model.prompt : undefined;\n model.teacherInstructions =\n instr && model.teacherInstructionsEnabled !== false ? model.teacherInstructions : undefined;\n model.showTeacherInstructions = instr;\n model.alwaysShowCorrect = instr;\n model.mode = instr ? 'evaluate' : model.mode;\n\n model.disabled = true;\n model.animationsDisabled = true;\n model.lockChoiceOrder = true;\n model.choicesLayout = model.choicesLayout || 'vertical';\n\n const choices = cloneDeep(model.choices);\n\n model.choices = choices.map((c) => {\n c.rationale = instr && model.rationaleEnabled !== false ? c.rationale : undefined;\n c.hideTick = instr;\n c.feedback = undefined;\n return c;\n });\n\n model.keyMode = model.choicePrefix || 'letters';\n\n return model;\n};\n\nexport default class MultipleChoicePrint extends HTMLElement {\n constructor() {\n super();\n this._options = null;\n this._model = null;\n this._session = [];\n this._root = null;\n this._rerender = debounce(\n () => {\n if (this._model && this._session) {\n const printModel = preparePrintModel(this._model, this._options);\n\n const element =\n this._options &&\n React.createElement(Main, {\n model: printModel,\n session: {},\n options: this._options,\n });\n\n if (!this._root) {\n this._root = createRoot(this);\n }\n this._root.render(element);\n // Use double requestAnimationFrame so React has committed to the DOM before we render math\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n log('render complete - render math');\n renderMath(this);\n });\n });\n } else {\n log('skip');\n }\n },\n 50,\n { leading: false, trailing: true },\n );\n }\n set options(o) {\n this._options = o;\n }\n\n set model(s) {\n this._model = s;\n this._rerender();\n }\n\n connectedCallback() {}\n\n disconnectedCallback() {\n if (this._root) {\n this._root.unmount();\n }\n }\n}\n"],"mappings":";;;;;AAiBA,IAAM,KAAA,IAAA,wBAAA,EAAA,CAAA,QAAA,CAAY,mCAAmC,GAU/C,KAAqB,GAAO,MAAS;CACzC,IAAM,IAAQ,EAAK,SAAS;CAyB5B,OAvBA,EAAM,SAAS,EAAM,kBAAkB,KAAuB,KAAA,IAAf,EAAM,QACrD,EAAM,sBACJ,KAAS,EAAM,+BAA+B,KAAQ,EAAM,sBAAsB,KAAA,GACpF,EAAM,0BAA0B,GAChC,EAAM,oBAAoB,GAC1B,EAAM,OAAO,IAAQ,aAAa,EAAM,MAExC,EAAM,WAAW,IACjB,EAAM,qBAAqB,IAC3B,EAAM,kBAAkB,IACxB,EAAM,gBAAgB,EAAM,iBAAiB,YAI7C,EAAM,UAFU,EAAU,EAAM,OAEhB,CAAA,CAAQ,KAAK,OAC3B,EAAE,YAAY,KAAS,EAAM,qBAAqB,KAAQ,EAAE,YAAY,KAAA,GACxE,EAAE,WAAW,GACb,EAAE,WAAW,KAAA,GACN,EACR,GAED,EAAM,UAAU,EAAM,gBAAgB,WAE/B;AACT,GAEqB,IAArB,cAAiD,YAAY;CAC3D,cAAc;EAMZ,AALA,MAAM,GACN,KAAK,WAAW,MAChB,KAAK,SAAS,MACd,KAAK,WAAW,CAAC,GACjB,KAAK,QAAQ,MACb,KAAK,YAAY,QACT;GACJ,IAAI,KAAK,UAAU,KAAK,UAAU;IAChC,IAAM,IAAa,EAAkB,KAAK,QAAQ,KAAK,QAAQ,GAEzD,IACJ,KAAK,YACL,EAAM,cAAc,GAAM;KACxB,OAAO;KACP,SAAS,CAAC;KACV,SAAS,KAAK;IAChB,CAAC;IAOH,AALA,AACE,KAAK,UAAQ,EAAW,IAAI,GAE9B,KAAK,MAAM,OAAO,CAAO,GAEzB,4BAA4B;KAC1B,4BAA4B;MAE1B,AADA,EAAI,+BAA+B,GACnC,EAAW,IAAI;KACjB,CAAC;IACH,CAAC;GACH,OACE,EAAI,MAAM;EAEd,GACA,IACA;GAAE,SAAS;GAAO,UAAU;EAAK,CACnC;CACF;CACA,IAAI,QAAQ,GAAG;EACb,KAAK,WAAW;CAClB;CAEA,IAAI,MAAM,GAAG;EAEX,AADA,KAAK,SAAS,GACd,KAAK,UAAU;CACjB;CAEA,oBAAoB,CAAC;CAErB,uBAAuB;EACrB,AAAI,KAAK,SACP,KAAK,MAAM,QAAQ;CAEvB;AACF"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @synced-from pie-elements/packages/multiple-choice/controller/src/defaults.js
3
+ * @auto-generated
4
+ *
5
+ * This file is automatically synced from pie-elements and converted to TypeScript.
6
+ * Manual edits will be overwritten on next sync.
7
+ * To make changes, edit the upstream JavaScript file and run sync again.
8
+ */
9
+ declare const _default: {
10
+ choiceMode: string;
11
+ choicePrefix: string;
12
+ choices: never[];
13
+ choicesLayout: string;
14
+ feedbackEnabled: boolean;
15
+ gridColumns: number;
16
+ lockChoiceOrder: boolean;
17
+ partialScoring: boolean;
18
+ prompt: string;
19
+ promptEnabled: boolean;
20
+ rationale: string;
21
+ rationaleEnabled: boolean;
22
+ scoringType: string;
23
+ studentInstructionsEnabled: boolean;
24
+ teacherInstructions: string;
25
+ teacherInstructionsEnabled: boolean;
26
+ toolbarEditorPosition: string;
27
+ selectedAnswerBackgroundColor: string;
28
+ selectedAnswerStrokeColor: string;
29
+ selectedAnswerStrokeWidth: string;
30
+ hoverAnswerBackgroundColor: string;
31
+ hoverAnswerStrokeColor: string;
32
+ hoverAnswerStrokeWidth: string;
33
+ keyboardEventsEnabled: boolean;
34
+ };
35
+ export default _default;
@@ -0,0 +1,29 @@
1
+ //#region src/controller/defaults.ts
2
+ var e = {
3
+ choiceMode: "checkbox",
4
+ choicePrefix: "letters",
5
+ choices: [],
6
+ choicesLayout: "vertical",
7
+ feedbackEnabled: !1,
8
+ gridColumns: 2,
9
+ lockChoiceOrder: !0,
10
+ partialScoring: !0,
11
+ prompt: "",
12
+ promptEnabled: !0,
13
+ rationale: "",
14
+ rationaleEnabled: !0,
15
+ scoringType: "auto",
16
+ studentInstructionsEnabled: !0,
17
+ teacherInstructions: "",
18
+ teacherInstructionsEnabled: !0,
19
+ toolbarEditorPosition: "bottom",
20
+ selectedAnswerBackgroundColor: "initial",
21
+ selectedAnswerStrokeColor: "initial",
22
+ selectedAnswerStrokeWidth: "initial",
23
+ hoverAnswerBackgroundColor: "initial",
24
+ hoverAnswerStrokeColor: "initial",
25
+ hoverAnswerStrokeWidth: "initial",
26
+ keyboardEventsEnabled: !1
27
+ };
28
+ //#endregion
29
+ export { e as default };
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @synced-from pie-elements/packages/multiple-choice/controller/src/index.js
3
+ * @auto-generated
4
+ *
5
+ * This file is automatically synced from pie-elements and converted to TypeScript.
6
+ * Manual edits will be overwritten on next sync.
7
+ * To make changes, edit the upstream JavaScript file and run sync again.
8
+ */
9
+ export declare function createDefaultModel(model?: {}): Promise<unknown>;
10
+ export declare const normalize: (question: any) => any;
11
+ /**
12
+ *
13
+ * @param {*} question
14
+ * @param {*} session
15
+ * @param {*} env
16
+ * @param {*} updateSession - optional - a function that will set the properties passed into it on the session.
17
+ */
18
+ export declare function model(question: any, session: any, env: any, updateSession: any): Promise<{
19
+ disabled: boolean;
20
+ mode: any;
21
+ prompt: any;
22
+ choicesLayout: any;
23
+ gridColumns: any;
24
+ choiceMode: any;
25
+ keyMode: any;
26
+ choices: any;
27
+ responseCorrect: any;
28
+ language: any;
29
+ extraCSSRules: any;
30
+ fontSizeFactor: any;
31
+ isSelectionButtonBelow: any;
32
+ selectedAnswerBackgroundColor: any;
33
+ selectedAnswerStrokeColor: any;
34
+ selectedAnswerStrokeWidth: any;
35
+ hoverAnswerBackgroundColor: any;
36
+ hoverAnswerStrokeColor: any;
37
+ hoverAnswerStrokeWidth: any;
38
+ minSelections: any;
39
+ maxSelections: any;
40
+ keyboardEventsEnabled: any;
41
+ autoplayAudioEnabled: any;
42
+ completeAudioEnabled: any;
43
+ customAudioButton: any;
44
+ }>;
45
+ export declare const getScore: (config: any, session: any) => number;
46
+ /**
47
+ * Generates detailed trace log for scoring evaluation
48
+ * @param {Object} model - the question model
49
+ * @param {Object} session - the student session
50
+ * @param {Object} env - the environment
51
+ * @returns {Array} traceLog - array of trace messages
52
+ */
53
+ export declare const getLogTrace: (model: any, session: any, env: any) => string[];
54
+ /**
55
+ *
56
+ * The score is partial by default for checkbox mode, allOrNothing for radio mode.
57
+ * To disable partial scoring for checkbox mode you either set model.partialScoring = false or env.partialScoring = false. the value in `env` will
58
+ * override the value in `model`.
59
+ * @param {Object} model - the main model
60
+ * @param {*} session
61
+ * @param {Object} env
62
+ */
63
+ export declare function outcome(model: any, session: any, env: any): Promise<unknown>;
64
+ export declare const createCorrectResponseSession: (question: any, env: any) => Promise<unknown>;
65
+ export declare const validate: (model?: {}, config?: {}) => {};
@@ -0,0 +1,129 @@
1
+ import { isResponseCorrect as e } from "./utils.js";
2
+ import t from "./defaults.js";
3
+ import { isEmpty as n } from "@pie-element/shared-lodash";
4
+ import { getShuffledChoices as r, lockChoices as i, partialScoring as a } from "@pie-element/shared-controller-utils";
5
+ //#region src/controller/index.ts
6
+ var o = (e, t, n) => (r) => {
7
+ let { role: i, mode: a } = t || {}, o = {
8
+ label: r.label,
9
+ value: r.value
10
+ };
11
+ if (i === "instructor" && (a === "view" || a === "evaluate") ? o.rationale = e.rationaleEnabled ? r.rationale : null : o.rationale = null, a === "evaluate" && (o.correct = !!r.correct, e.feedbackEnabled)) {
12
+ let e = r.feedback && r.feedback.type || "none";
13
+ e === "default" ? o.feedback = n[r.correct ? "correct" : "incorrect"] : e === "custom" && (o.feedback = r.feedback.value);
14
+ }
15
+ return o;
16
+ };
17
+ function s(e = {}) {
18
+ return new Promise((n) => n({
19
+ ...t,
20
+ ...e
21
+ }));
22
+ }
23
+ var c = (e) => {
24
+ let { verticalMode: n, choicesLayout: r, ...i } = e || {};
25
+ return {
26
+ ...t,
27
+ ...i,
28
+ choicesLayout: r || n === !1 && "horizontal" || t.choicesLayout
29
+ };
30
+ };
31
+ async function l(t, n, a, s) {
32
+ let l = c(t), u = Object.assign({
33
+ correct: "Correct",
34
+ incorrect: "Incorrect"
35
+ }, l.defaultFeedback), d = (l.choices || []).map(o(l, a, u));
36
+ i(l, n, a) || (d = await r(d, n, s, "value"));
37
+ let f = {
38
+ disabled: a.mode !== "gather",
39
+ mode: a.mode,
40
+ prompt: l.promptEnabled ? l.prompt : null,
41
+ choicesLayout: l.choicesLayout,
42
+ gridColumns: l.gridColumns,
43
+ choiceMode: l.choiceMode,
44
+ keyMode: l.choicePrefix,
45
+ choices: d,
46
+ responseCorrect: a.mode === "evaluate" ? e(l, n) : void 0,
47
+ language: l.language,
48
+ extraCSSRules: l.extraCSSRules,
49
+ fontSizeFactor: l.fontSizeFactor,
50
+ isSelectionButtonBelow: l.isSelectionButtonBelow,
51
+ selectedAnswerBackgroundColor: l.selectedAnswerBackgroundColor || "initial",
52
+ selectedAnswerStrokeColor: l.selectedAnswerStrokeColor || "initial",
53
+ selectedAnswerStrokeWidth: l.selectedAnswerStrokeWidth || "initial",
54
+ hoverAnswerBackgroundColor: l.hoverAnswerBackgroundColor || "initial",
55
+ hoverAnswerStrokeColor: l.hoverAnswerStrokeColor || "initial",
56
+ hoverAnswerStrokeWidth: l.hoverAnswerStrokeWidth || "initial",
57
+ minSelections: l.minSelections,
58
+ maxSelections: l.maxSelections,
59
+ keyboardEventsEnabled: l.keyboardEventsEnabled,
60
+ autoplayAudioEnabled: l.autoplayAudioEnabled,
61
+ completeAudioEnabled: l.completeAudioEnabled,
62
+ customAudioButton: l.customAudioButton
63
+ }, { role: p, mode: m } = a || {};
64
+ return p === "instructor" && (m === "view" || m === "evaluate") ? f.teacherInstructions = l.teacherInstructionsEnabled ? l.teacherInstructions : null : f.teacherInstructions = null, f;
65
+ }
66
+ var u = (e, t) => {
67
+ if (!t || n(t)) return 0;
68
+ let r = t.value || [], i = (e.choices || []).filter((e) => e.correct), a = r.reduce((e, t) => e + +!!i.find((e) => e.value === t), 0);
69
+ i.length < r.length && (a -= r.length - i.length, a < 0 && (a = 0));
70
+ let o = i.length ? a / i.length : 0;
71
+ return parseFloat(o.toFixed(2));
72
+ }, d = (e, t, n) => {
73
+ let r = [], i = t?.value || [], o = e.choiceMode === "radio" ? "multiple-choice (radio)" : "multiple-select (checkbox)";
74
+ r.push(`Question type: ${o}.`), i.length ? r.push(`Student selected ${i.length} answer(s): ${i.join(", ")}.`) : r.push("Student did not select any answers.");
75
+ let s = (e.choices || []).filter((e) => e.correct), c = s.map((e) => e.value);
76
+ if (r.push(`${s.length} correct answer(s) are defined for this question.`), i.length) {
77
+ let e = i.filter((e) => c.includes(e)), t = i.filter((e) => !c.includes(e));
78
+ r.push(`Student selected ${e.length} correct and ${t.length} incorrect answer(s).`);
79
+ }
80
+ let l = a.enabled(e, n) && e.choiceMode !== "radio" ? "partial scoring" : "all-or-nothing scoring";
81
+ r.push(`Score calculated using ${l}.`);
82
+ let d = u(e, t);
83
+ return r.push(`Final score: ${d}.`), r;
84
+ };
85
+ function f(e, t, r) {
86
+ return new Promise((i) => {
87
+ if (!t || n(t)) i({
88
+ score: 0,
89
+ empty: !0,
90
+ traceLog: ["Student did not select any answers. Score is 0."]
91
+ });
92
+ else {
93
+ let n = d(e, t, r), o = u(e, t);
94
+ i({
95
+ score: a.enabled(e, r) && e.choiceMode !== "radio" ? o : +(o === 1),
96
+ empty: !1,
97
+ traceLog: n
98
+ });
99
+ }
100
+ });
101
+ }
102
+ var p = (e, t) => new Promise((n) => {
103
+ if (t.mode !== "evaluate" && t.role === "instructor") {
104
+ let { choices: t } = e || { choices: [] };
105
+ n({
106
+ id: "1",
107
+ value: t.filter((e) => e.correct).map((e) => e.value)
108
+ });
109
+ } else n(null);
110
+ }), m = (e) => (e || "").replace(/(<(?!img|iframe|source)([^>]+)>)/gi, ""), h = (e = {}, t = {}) => {
111
+ let { choices: r } = e, { minAnswerChoices: i = 2, maxAnswerChoices: a } = t, o = [...r || []].reverse(), s = {}, c = {}, l = {};
112
+ ["teacherInstructions", "prompt"].forEach((n) => {
113
+ t[n]?.required && !m(e[n]) && (l[n] = "This field is required.");
114
+ });
115
+ let u = !1, d = 0;
116
+ o.forEach((e, n) => {
117
+ let { correct: r, value: i, label: a, rationale: l } = e;
118
+ r && (u = !0, d++), m(a) ? o.slice(n + 1).some((e) => e.label === a) && (s[i] = "Content should be unique.") : s[i] = "Content should not be empty.", t.rationale?.required && !m(l) && (c[i] = "This field is required.");
119
+ });
120
+ let f = (r || []).length;
121
+ if (f < i ? l.answerChoices = `There should be at least ${i} choices defined.` : f > a && (l.answerChoices = `No more than ${a} choices should be defined.`), !u) l.correctResponse = "No correct response defined.";
122
+ else {
123
+ let { maxSelections: t, choiceMode: n } = e;
124
+ n !== "radio" && t != null && d > t && (l.correctResponse = `The number of correct answers (${d}) exceeds max selections (${t}). Students won't be able to select all correct answers.`);
125
+ }
126
+ return n(s) || (l.choices = s), n(c) || (l.rationale = c), l;
127
+ };
128
+ //#endregion
129
+ export { p as createCorrectResponseSession, s as createDefaultModel, d as getLogTrace, u as getScore, l as model, c as normalize, f as outcome, h as validate };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @synced-from pie-elements/packages/multiple-choice/controller/src/utils.js
3
+ * @auto-generated
4
+ *
5
+ * This file is automatically synced from pie-elements and converted to TypeScript.
6
+ * Manual edits will be overwritten on next sync.
7
+ * To make changes, edit the upstream JavaScript file and run sync again.
8
+ */
9
+ export declare const getCorrectResponse: (choices: any) => any;
10
+ export declare const isResponseCorrect: (question: any, session: any) => any;
@@ -0,0 +1,8 @@
1
+ import { isEqual as e } from "@pie-element/shared-lodash";
2
+ //#region src/controller/utils.ts
3
+ var t = (e) => e.filter((e) => e.correct).map((e) => e.value).sort(), n = (n, r) => {
4
+ let i = t(n.choices);
5
+ return r && e((r.value || []).sort(), i);
6
+ };
7
+ //#endregion
8
+ export { t as getCorrectResponse, n as isResponseCorrect };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @synced-from pie-elements/packages/multiple-choice/src/choice-input.jsx
3
+ * @auto-generated
4
+ *
5
+ * This file is automatically synced from pie-elements and converted to TypeScript.
6
+ * Manual edits will be overwritten on next sync.
7
+ * To make changes, edit the upstream JavaScript file and run sync again.
8
+ */
9
+ import React from 'react';
10
+ import PropTypes from 'prop-types';
11
+ export declare const StyledFormControlLabel: any;
12
+ export declare const StyledCheckbox: (props: any) => React.JSX.Element;
13
+ export declare const StyledRadio: (props: any) => React.JSX.Element;
14
+ export declare class ChoiceInput extends React.Component {
15
+ static propTypes: {
16
+ choiceMode: PropTypes.Requireable<string>;
17
+ displayKey: PropTypes.Requireable<string>;
18
+ checked: PropTypes.Validator<boolean>;
19
+ correctness: PropTypes.Requireable<string>;
20
+ disabled: PropTypes.Validator<boolean>;
21
+ feedback: PropTypes.Requireable<string>;
22
+ label: PropTypes.Validator<string>;
23
+ rationale: PropTypes.Requireable<string>;
24
+ onChange: PropTypes.Validator<(...args: any[]) => any>;
25
+ value: PropTypes.Validator<string>;
26
+ className: PropTypes.Requireable<string>;
27
+ tagName: PropTypes.Requireable<string>;
28
+ hideTick: PropTypes.Requireable<boolean>;
29
+ isEvaluateMode: PropTypes.Requireable<boolean>;
30
+ choicesLayout: PropTypes.Requireable<string>;
31
+ isSelectionButtonBelow: PropTypes.Requireable<boolean>;
32
+ };
33
+ static defaultProps: {
34
+ rationale: null;
35
+ checked: boolean;
36
+ isEvaluateMode: boolean;
37
+ };
38
+ constructor(props: any);
39
+ onToggleChoice(event: any): void;
40
+ generateChoiceId(): string;
41
+ handleKeyDown: any;
42
+ render(): React.JSX.Element;
43
+ }
44
+ export default ChoiceInput;
@@ -0,0 +1,280 @@
1
+ import { clsx as e } from "../node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js";
2
+ import t from "./feedback-tick.js";
3
+ import n from "react";
4
+ import r from "prop-types";
5
+ import * as i from "@pie-lib/render-ui";
6
+ import { Feedback as a, PreviewPrompt as o, color as s } from "@pie-lib/render-ui";
7
+ import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
8
+ import { styled as d } from "@mui/material/styles";
9
+ import f from "@mui/material/Box";
10
+ import p from "@mui/material/FormControlLabel";
11
+ import m from "@mui/material/Checkbox";
12
+ import h from "@mui/material/Radio";
13
+ //#region src/delivery/choice-input.tsx
14
+ function g(e) {
15
+ return typeof e == "function" || typeof e == "object" && !!e && typeof e.$$typeof == "symbol";
16
+ }
17
+ function _(e, t) {
18
+ return !e || g(e) ? e : g(e.default) ? e.default : t && g(e[t]) ? e[t] : t && g(e[t]?.default) ? e[t].default : e;
19
+ }
20
+ var v = _(o, "PreviewPrompt") || _(S.PreviewPrompt, "PreviewPrompt"), y = _(a, "Feedback") || _(S.Feedback, "Feedback"), b = i, x = b.default, S = x && typeof x == "object" ? x : b, C = "multiple-choice-component", w = d(f)({
21
+ display: "flex",
22
+ alignItems: "center",
23
+ backgroundColor: s.background()
24
+ }), T = d(f)({
25
+ display: "flex",
26
+ alignItems: "center",
27
+ backgroundColor: s.background(),
28
+ flex: 1,
29
+ "& .MuiFormControlLabel-root": { marginLeft: "-14px" },
30
+ "& label": {
31
+ color: s.text(),
32
+ "& > span": { fontSize: "inherit" },
33
+ "& > .MuiButtonBase-root": { padding: "12px" }
34
+ }
35
+ }), E = d("span")(({ theme: e }) => ({
36
+ display: "flex",
37
+ alignItems: "center",
38
+ "& > span": { marginLeft: `-${e.spacing(1)}` }
39
+ })), D = d("span")({
40
+ position: "absolute",
41
+ left: "-10000px",
42
+ top: "auto",
43
+ width: "1px",
44
+ height: "1px",
45
+ overflow: "hidden"
46
+ }), O = d(p)({
47
+ "& .MuiFormControlLabel-label": {
48
+ color: `${s.text()} !important`,
49
+ backgroundColor: s.background(),
50
+ letterSpacing: "normal"
51
+ },
52
+ "&.Mui-disabled *": { cursor: "not-allowed !important" }
53
+ }), k = (e, t) => ({ [`&.${C}`]: { color: `var(--choice-input-${e}, ${t}) !important` } }), A = (e) => {
54
+ let t = (t) => e ? `${e}-${t}` : t;
55
+ return {
56
+ [t("root")]: {
57
+ ...k("color", s.text()),
58
+ ...e === "correct" ? k("correct-color", s.text()) : {},
59
+ ...e === "incorrect" ? k("incorrect-color", s.incorrect()) : {}
60
+ },
61
+ [t("checked")]: {
62
+ ...e === "correct" ? k("correct-selected-color", s.correct()) : {},
63
+ ...e === "incorrect" ? k("incorrect-checked", s.incorrect()) : {},
64
+ ...e ? {} : k("selected-color", s.primary())
65
+ },
66
+ [t("disabled")]: {
67
+ ...k("disabled-color", s.text()),
68
+ ...e === "correct" ? k("correct-disabled-color", s.disabled()) : {},
69
+ ...e === "incorrect" ? k("incorrect-disabled-color", s.disabled()) : {},
70
+ opacity: .6,
71
+ cursor: "not-allowed !important",
72
+ pointerEvents: "initial !important"
73
+ },
74
+ focusVisibleUnchecked: {
75
+ outline: `2px solid ${s.keyBoardFocusIndicator()}`,
76
+ backgroundColor: "transparent"
77
+ },
78
+ focusVisibleChecked: {
79
+ outline: `2px solid ${s.keyBoardFocusIndicator()}`,
80
+ backgroundColor: "transparent"
81
+ }
82
+ };
83
+ }, j = d(m, { shouldForwardProp: (e) => e !== "correctness" })(({ correctness: e }) => {
84
+ let t = A(e), n = (t) => e ? `${e}-${t}` : t;
85
+ return {
86
+ [`&.${C}`]: {
87
+ ...t[n("root")],
88
+ "&.Mui-checked": t[n("checked")],
89
+ "&.Mui-disabled": e ? {} : t[n("disabled")],
90
+ "&:hover:not(.Mui-disabled) svg": {
91
+ boxShadow: `0px 0px 0px 2px ${s.keyBoardFocusIndicator()}`,
92
+ borderRadius: "4px"
93
+ }
94
+ },
95
+ "&.Mui-focusVisible": {
96
+ "&:not(.Mui-checked)": t.focusVisibleUnchecked,
97
+ "&.Mui-checked": t.focusVisibleChecked
98
+ }
99
+ };
100
+ }), M = (e) => {
101
+ let { correctness: t, checked: n, onChange: r, disabled: i, value: a, id: o, onKeyDown: s, inputRef: c } = e;
102
+ return /* @__PURE__ */ l(j, {
103
+ id: o,
104
+ slotProps: { input: { ref: c } },
105
+ onKeyDown: s,
106
+ disableRipple: !0,
107
+ checked: n,
108
+ onChange: r,
109
+ disabled: i,
110
+ value: a,
111
+ correctness: t,
112
+ className: C
113
+ });
114
+ }, N = d(h, { shouldForwardProp: (e) => e !== "correctness" })(({ correctness: e }) => {
115
+ let t = A(e), n = (t) => e ? `${e}-${t}` : t;
116
+ return {
117
+ [`&.${C}`]: {
118
+ ...t[n("root")],
119
+ "&.Mui-checked": t[n("checked")],
120
+ "&.Mui-disabled": e ? {} : t[n("disabled")],
121
+ "&.Mui-focusVisible:not(.Mui-checked)": t.focusVisibleUnchecked,
122
+ "&.Mui-focusVisible.Mui-checked": t.focusVisibleChecked,
123
+ "&:hover:not(.Mui-disabled) svg": {
124
+ boxShadow: `0px 0px 0px 2px ${s.keyBoardFocusIndicator()}`,
125
+ borderRadius: "50%"
126
+ }
127
+ },
128
+ "&.Mui-focusVisible": {
129
+ "& input": { outline: 0 },
130
+ "& .MuiTouchRipple-root": { display: "none" }
131
+ }
132
+ };
133
+ }), P = (e) => {
134
+ let { correctness: t, checked: n, onChange: r, disabled: i, value: a, id: o, tagName: s, inputRef: c } = e;
135
+ return /* @__PURE__ */ l(N, {
136
+ id: o,
137
+ slotProps: { input: { ref: c } },
138
+ disableRipple: !0,
139
+ checked: n,
140
+ onChange: r,
141
+ disabled: i,
142
+ value: a,
143
+ correctness: t,
144
+ className: C,
145
+ name: s
146
+ });
147
+ }, F = class extends n.Component {
148
+ static propTypes = {
149
+ choiceMode: r.oneOf(["radio", "checkbox"]),
150
+ displayKey: r.string,
151
+ checked: r.bool.isRequired,
152
+ correctness: r.string,
153
+ disabled: r.bool.isRequired,
154
+ feedback: r.string,
155
+ label: r.string.isRequired,
156
+ rationale: r.string,
157
+ onChange: r.func.isRequired,
158
+ value: r.string.isRequired,
159
+ className: r.string,
160
+ tagName: r.string,
161
+ hideTick: r.bool,
162
+ isEvaluateMode: r.bool,
163
+ choicesLayout: r.oneOf([
164
+ "vertical",
165
+ "grid",
166
+ "horizontal"
167
+ ]),
168
+ isSelectionButtonBelow: r.bool
169
+ };
170
+ static defaultProps = {
171
+ rationale: null,
172
+ checked: !1,
173
+ isEvaluateMode: !1
174
+ };
175
+ constructor(e) {
176
+ super(e), this.onToggleChoice = this.onToggleChoice.bind(this), this.choiceId = this.generateChoiceId(), this.descId = `${this.choiceId}-desc`;
177
+ }
178
+ onToggleChoice(e) {
179
+ this.props.onChange(e);
180
+ }
181
+ generateChoiceId() {
182
+ return "choice-" + (Math.random() * 1e4).toFixed();
183
+ }
184
+ handleKeyDown = (e) => {
185
+ let { choiceMode: t } = this.props;
186
+ if (t !== "checkbox") return;
187
+ let n = e.key === "ArrowDown", r = e.key === "ArrowUp";
188
+ if (!n && !r) return;
189
+ e.preventDefault();
190
+ let i = document.getElementById(this.choiceId);
191
+ if (!i) return;
192
+ let a = i.closest("fieldset");
193
+ if (!a) return;
194
+ let o = Array.from(a.querySelectorAll("input[type=\"checkbox\"]")), s = o.findIndex((e) => e === i);
195
+ if (s === -1) return;
196
+ let c = o[n ? s + 1 : s - 1];
197
+ c && c.focus();
198
+ };
199
+ render() {
200
+ let { choiceMode: n, disabled: r, displayKey: i, feedback: a, label: o, correctness: s, className: d, rationale: f, hideTick: p, isEvaluateMode: m, choicesLayout: h, value: g, checked: _, tagName: b, isSelectionButtonBelow: x } = this.props, S = n === "checkbox" ? M : P, k = n === "checkbox" ? "checkbox" : "radio-button", A = {
201
+ ...h === "horizontal" && { [`& .${C}`]: {
202
+ padding: "8px",
203
+ margin: "4px 0 4px 4px"
204
+ } },
205
+ ...x && h !== "grid" && { "& > label": { alignItems: "flex-start" } },
206
+ ...x && h === "grid" && {
207
+ justifyContent: "center",
208
+ "& > label": { alignItems: "center" }
209
+ }
210
+ }, j = typeof o == "string" && (o.includes("<math") || o.includes("\\(") || o.includes("\\[") || o.includes("<img") || o.includes("data-latex") || o.includes("data-raw") || o.includes("<mjx-container")), N = i ? /* @__PURE__ */ l(D, {
211
+ id: this.descId,
212
+ children: j ? `Pick the answer below, ${i}` : i
213
+ }) : null, F = /* @__PURE__ */ l(c, { children: i && !x ? /* @__PURE__ */ u(w, {
214
+ component: "span",
215
+ children: [/* @__PURE__ */ u("span", {
216
+ "aria-hidden": "true",
217
+ children: [
218
+ i,
219
+ ".",
220
+ "\xA0"
221
+ ]
222
+ }), /* @__PURE__ */ l(v, {
223
+ className: "prompt-label",
224
+ prompt: o,
225
+ tagName: "span"
226
+ })]
227
+ }) : /* @__PURE__ */ l(v, {
228
+ className: "prompt-label",
229
+ prompt: o,
230
+ tagName: "span"
231
+ }) }), I = {
232
+ disabled: r,
233
+ checked: _,
234
+ correctness: s,
235
+ tagName: b,
236
+ value: g,
237
+ id: this.choiceId,
238
+ onChange: this.onToggleChoice,
239
+ onKeyDown: this.handleKeyDown,
240
+ ...N ? { "aria-describedby": this.descId } : {}
241
+ }, L = x ? /* @__PURE__ */ u(E, { children: [
242
+ N,
243
+ /* @__PURE__ */ l(S, {
244
+ ...I,
245
+ style: { padding: 0 }
246
+ }),
247
+ /* @__PURE__ */ l("span", {
248
+ "aria-hidden": "true",
249
+ children: i ? `${i}.` : ""
250
+ })
251
+ ] }) : /* @__PURE__ */ u(c, { children: [N, /* @__PURE__ */ l(S, { ...I })] });
252
+ return /* @__PURE__ */ u("div", {
253
+ className: e(d, "corespring-" + k, "choice-input"),
254
+ children: [
255
+ /* @__PURE__ */ u(w, { children: [!p && m && /* @__PURE__ */ l(t, { correctness: s }), /* @__PURE__ */ l(T, {
256
+ className: "checkbox-holder",
257
+ sx: A,
258
+ children: /* @__PURE__ */ l(O, {
259
+ label: F,
260
+ value: g,
261
+ htmlFor: this.choiceId,
262
+ labelPlacement: x ? "top" : void 0,
263
+ control: L
264
+ })
265
+ })] }),
266
+ f && /* @__PURE__ */ l(v, {
267
+ className: "rationale",
268
+ defaultClassName: "rationale",
269
+ prompt: f
270
+ }),
271
+ /* @__PURE__ */ l(y, {
272
+ feedback: a,
273
+ correctness: s
274
+ })
275
+ ]
276
+ });
277
+ }
278
+ };
279
+ //#endregion
280
+ export { F as ChoiceInput, F as default, M as StyledCheckbox, O as StyledFormControlLabel, P as StyledRadio };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @synced-from pie-elements/packages/multiple-choice/src/choice.jsx
3
+ * @auto-generated
4
+ *
5
+ * This file is automatically synced from pie-elements and converted to TypeScript.
6
+ * Manual edits will be overwritten on next sync.
7
+ * To make changes, edit the upstream JavaScript file and run sync again.
8
+ */
9
+ import React from 'react';
10
+ export declare class Choice extends React.Component {
11
+ static propTypes: {};
12
+ state: {
13
+ isHovered: boolean;
14
+ };
15
+ handleMouseEnter: any;
16
+ handleMouseLeave: any;
17
+ onChange: any;
18
+ render(): React.JSX.Element;
19
+ }
20
+ export default Choice;