@pie-element/multiple-choice 13.5.0-beta.7 → 14.0.0-next.20261002094057

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 (150) hide show
  1. package/author.js +2 -0
  2. package/configure.js +2 -0
  3. package/controller.js +1 -0
  4. package/dist/author/defaults.d.ts +205 -0
  5. package/dist/author/defaults.js +151 -0
  6. package/dist/author/index.d.ts +26 -0
  7. package/dist/author/index.js +119 -0
  8. package/dist/author/main.d.ts +34 -0
  9. package/dist/author/main.js +287 -0
  10. package/dist/author/utils.d.ts +9 -0
  11. package/dist/author/utils.js +7 -0
  12. package/dist/browser/Radio-CfqdhvRH.js +9769 -0
  13. package/dist/browser/Radio-CfqdhvRH.js.map +1 -0
  14. package/dist/browser/assets/Symbola-4c507403.woff2 +0 -0
  15. package/dist/browser/author/index.js +35079 -0
  16. package/dist/browser/author/index.js.map +1 -0
  17. package/dist/browser/controller/index.js +204 -0
  18. package/dist/browser/controller/index.js.map +1 -0
  19. package/dist/browser/delivery/index.js +303 -0
  20. package/dist/browser/delivery/index.js.map +1 -0
  21. package/dist/browser/dist-CHbLnyuX.js +111 -0
  22. package/dist/browser/dist-CHbLnyuX.js.map +1 -0
  23. package/dist/browser/editor-runtime/Radio-D3ynJgVj.js +9769 -0
  24. package/dist/browser/editor-runtime/Radio-D3ynJgVj.js.map +1 -0
  25. package/dist/browser/editor-runtime/assets/Symbola-4c507403.woff2 +0 -0
  26. package/dist/browser/editor-runtime/author/index.js +18670 -0
  27. package/dist/browser/editor-runtime/author/index.js.map +1 -0
  28. package/dist/browser/editor-runtime/controller/index.js +204 -0
  29. package/dist/browser/editor-runtime/controller/index.js.map +1 -0
  30. package/dist/browser/editor-runtime/delivery/index.js +303 -0
  31. package/dist/browser/editor-runtime/delivery/index.js.map +1 -0
  32. package/dist/browser/editor-runtime/dist-CHbLnyuX.js +111 -0
  33. package/dist/browser/editor-runtime/dist-CHbLnyuX.js.map +1 -0
  34. package/dist/browser/editor-runtime/main-BzlfiDu3.js +2553 -0
  35. package/dist/browser/editor-runtime/main-BzlfiDu3.js.map +1 -0
  36. package/dist/browser/editor-runtime/print/index.js +45 -0
  37. package/dist/browser/editor-runtime/print/index.js.map +1 -0
  38. package/dist/browser/main-0JQfvG0B.js +2553 -0
  39. package/dist/browser/main-0JQfvG0B.js.map +1 -0
  40. package/dist/browser/print/index.js +45 -0
  41. package/dist/browser/print/index.js.map +1 -0
  42. package/dist/controller/defaults.d.ts +35 -0
  43. package/dist/controller/defaults.js +29 -0
  44. package/dist/controller/index.d.ts +65 -0
  45. package/dist/controller/index.js +129 -0
  46. package/dist/controller/utils.d.ts +10 -0
  47. package/dist/controller/utils.js +8 -0
  48. package/dist/delivery/choice-input.d.ts +44 -0
  49. package/dist/delivery/choice-input.js +280 -0
  50. package/dist/delivery/choice.d.ts +20 -0
  51. package/dist/delivery/choice.js +106 -0
  52. package/dist/delivery/feedback-tick.d.ts +20 -0
  53. package/dist/delivery/feedback-tick.js +104 -0
  54. package/dist/delivery/index.d.ts +37 -0
  55. package/dist/delivery/index.js +217 -0
  56. package/dist/delivery/main.d.ts +31 -0
  57. package/dist/delivery/main.js +51 -0
  58. package/dist/delivery/multiple-choice.d.ts +61 -0
  59. package/dist/delivery/multiple-choice.js +245 -0
  60. package/dist/delivery/session-updater.d.ts +10 -0
  61. package/dist/delivery/session-updater.js +9 -0
  62. package/dist/delivery/utils.d.ts +10 -0
  63. package/dist/delivery/utils.js +4 -0
  64. package/dist/index.d.ts +1 -0
  65. package/dist/index.iife.d.ts +8 -0
  66. package/dist/index.iife.js +148 -0
  67. package/dist/index.js +2 -0
  68. package/dist/node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js +16 -0
  69. package/dist/print/index.d.ts +15 -0
  70. package/dist/print/index.js +45 -0
  71. package/dist/runtime-support.d.ts +12 -0
  72. package/dist/runtime-support.js +12 -0
  73. package/module/print.js +18205 -1
  74. package/module/print.js.map +1 -0
  75. package/package.json +107 -30
  76. package/print.js +2 -0
  77. package/CHANGELOG.json +0 -1972
  78. package/CHANGELOG.md +0 -2777
  79. package/LICENSE.md +0 -5
  80. package/PRINT.md +0 -35
  81. package/README.md +0 -56
  82. package/choice.png +0 -0
  83. package/configure/CHANGELOG.json +0 -1387
  84. package/configure/CHANGELOG.md +0 -2117
  85. package/configure/lib/__tests__/root.test.js +0 -279
  86. package/configure/lib/defaults.js +0 -203
  87. package/configure/lib/defaults.js.map +0 -1
  88. package/configure/lib/index.js +0 -203
  89. package/configure/lib/index.js.map +0 -1
  90. package/configure/lib/main.js +0 -484
  91. package/configure/lib/main.js.map +0 -1
  92. package/configure/lib/utils.js +0 -18
  93. package/configure/lib/utils.js.map +0 -1
  94. package/configure/package.json +0 -22
  95. package/controller/CHANGELOG.json +0 -527
  96. package/controller/CHANGELOG.md +0 -1448
  97. package/controller/lib/__tests__/index.test.js +0 -561
  98. package/controller/lib/__tests__/utils.test.js +0 -8
  99. package/controller/lib/defaults.js +0 -33
  100. package/controller/lib/defaults.js.map +0 -1
  101. package/controller/lib/index.js +0 -298
  102. package/controller/lib/index.js.map +0 -1
  103. package/controller/lib/utils.js +0 -15
  104. package/controller/lib/utils.js.map +0 -1
  105. package/controller/package.json +0 -15
  106. package/docs/config-schema.json +0 -2993
  107. package/docs/config-schema.json.md +0 -2217
  108. package/docs/demo/config.js +0 -8
  109. package/docs/demo/generate.js +0 -61
  110. package/docs/demo/index.html +0 -1
  111. package/docs/demo/pie.manifest.json +0 -11
  112. package/docs/demo/session.js +0 -7
  113. package/docs/pie-schema.json +0 -1332
  114. package/docs/pie-schema.json.md +0 -1015
  115. package/lib/__tests__/choice-input-test.js +0 -49
  116. package/lib/__tests__/choice-input.test.js +0 -49
  117. package/lib/__tests__/index-test.js +0 -206
  118. package/lib/__tests__/index.test.js +0 -221
  119. package/lib/__tests__/key-events-test.js +0 -95
  120. package/lib/__tests__/key-events.test.js +0 -107
  121. package/lib/__tests__/multiple-choice-test.js +0 -101
  122. package/lib/__tests__/multiple-choice.test.js +0 -256
  123. package/lib/__tests__/session-updater-test.js +0 -70
  124. package/lib/__tests__/session-updater.test.js +0 -70
  125. package/lib/choice-input.js +0 -383
  126. package/lib/choice-input.js.map +0 -1
  127. package/lib/choice.js +0 -192
  128. package/lib/choice.js.map +0 -1
  129. package/lib/feedback-tick.js +0 -134
  130. package/lib/feedback-tick.js.map +0 -1
  131. package/lib/index.js +0 -405
  132. package/lib/index.js.map +0 -1
  133. package/lib/main.js +0 -63
  134. package/lib/main.js.map +0 -1
  135. package/lib/multiple-choice.js +0 -399
  136. package/lib/multiple-choice.js.map +0 -1
  137. package/lib/print.js +0 -94
  138. package/lib/print.js.map +0 -1
  139. package/lib/session-updater.js +0 -37
  140. package/lib/session-updater.js.map +0 -1
  141. package/lib/utils.js +0 -14
  142. package/lib/utils.js.map +0 -1
  143. package/module/configure.js +0 -1
  144. package/module/controller.js +0 -3045
  145. package/module/demo.js +0 -86
  146. package/module/element.js +0 -1
  147. package/module/index.html +0 -21
  148. package/module/manifest.json +0 -14
  149. package/module/print-demo.js +0 -124
  150. package/module/print.html +0 -18
@@ -0,0 +1,45 @@
1
+ import { Ht as e, I as t, N as n } from "../Radio-CfqdhvRH.js";
2
+ import { t as r } from "../main-0JQfvG0B.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__ */ e(t(), 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), t = this._options && o.createElement(r, {
14
+ model: e,
15
+ session: {},
16
+ options: this._options
17
+ });
18
+ this._root ||= s(this), this._root.render(t), requestAnimationFrame(() => {
19
+ requestAnimationFrame(() => {
20
+ c("render complete - render math"), n(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
+ this._rerender();
37
+ }
38
+ disconnectedCallback() {
39
+ this._rerender.cancel(), this._root &&= (this._root.unmount(), null);
40
+ }
41
+ };
42
+ //#endregion
43
+ export { u as default };
44
+
45
+ //# 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 // Disconnecting unmounts the React root, so a reinserted element renders again.\n this._rerender();\n }\n\n disconnectedCallback() {\n this._rerender.cancel();\n if (this._root) {\n this._root.unmount();\n this._root = null;\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;EAElB,KAAK,UAAU;CACjB;CAEA,uBAAuB;EAErB,AADA,KAAK,UAAU,OAAO,GACtB,AAEE,KAAK,WADL,KAAK,MAAM,QAAQ,GACN;CAEjB;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 };