@pie-element/inline-dropdown 11.0.4-next.20261011174919 → 11.0.4

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.
@@ -137,7 +137,7 @@ var v = (t, n) => {
137
137
  }, y = (e, t, n) => {
138
138
  let r = [], { value: i = {} } = t || {}, a = m(e), o = Object.keys(a), s = o.length;
139
139
  if (r.push(`${s} dropdown response area(s) defined in this question.`), i && Object.keys(i).length > 0) {
140
- let e = Object.entries(i).filter(([e, t]) => t && t.trim()).length;
140
+ let e = Object.entries(i).filter(([, e]) => e && e.trim()).length;
141
141
  r.push(`Student selected options in ${e} out of ${s} dropdown(s).`), o.forEach((e) => {
142
142
  let t = i && i[e] || "", n = a[e] || [];
143
143
  t.trim() ? r.push(`Dropdown ${parseInt(e) + 1}: student selected '${t}' (correct options: [${n.map((e) => `'${e}'`).join(", ")}]).`) : r.push(`Dropdown ${parseInt(e) + 1}: no selection made (correct options: [${n.map((e) => `'${e}'`).join(", ")}]).`);
@@ -186,8 +186,10 @@ var x = (e, t) => new Promise((n) => {
186
186
  t[n]?.required && !S(e[n]) && (o[n] = "This field is required.");
187
187
  });
188
188
  let s = ((n || "").match(/\{\{(\d+)\}\}/g) || []).length;
189
- return s > i ? o.responseAreasError = `No more than ${i} response areas should be defined.` : s < 1 && (o.responseAreasError = "There should be defined at least 1 response area."), (Object.keys(r) || []).forEach((e) => {
190
- r[e] && r[e].length > a && (o.responseAreaChoicesError = `No more than ${a} choices per response area should be defined.`);
189
+ i !== void 0 && s > i ? o.responseAreasError = `No more than ${i} response areas should be defined.` : s < 1 && (o.responseAreasError = "There should be defined at least 1 response area.");
190
+ let c = r;
191
+ return (Object.keys(c) || []).forEach((e) => {
192
+ c[e] && a !== void 0 && c[e].length > a && (o.responseAreaChoicesError = `No more than ${a} choices per response area should be defined.`);
191
193
  }), o;
192
194
  };
193
195
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../../shared/controller-utils/dist/index.js","../../../../src/controller/defaults.ts","../../../../src/controller/utils.ts","../../../../src/controller/index.ts"],"sourcesContent":["//#region \\0rolldown/runtime.js\nvar e = Object.defineProperty, t = (t, n) => {\n\tlet r = {};\n\tfor (var i in t) e(r, i, {\n\t\tget: t[i],\n\t\tenumerable: !0\n\t});\n\treturn n || e(r, Symbol.toStringTag, { value: \"Module\" }), r;\n};\n//#endregion\n//#region src/persistence.ts\nfunction n(e) {\n\treturn Array.isArray(e) ? e.filter((e) => e != null) : [];\n}\nfunction r(e) {\n\tlet t = [...e];\n\tfor (let e = t.length - 1; e > 0; e--) {\n\t\tlet n = Math.floor(Math.random() * (e + 1));\n\t\t[t[e], t[n]] = [t[n], t[e]];\n\t}\n\treturn t;\n}\nfunction i(e) {\n\treturn e == null ? !0 : Array.isArray(e) ? e.length === 0 : typeof e == \"object\" && Object.keys(e).length === 0;\n}\nasync function a(e, t, a, o = \"value\") {\n\tlet s = n(t?.data?.shuffledValues ?? t?.shuffledValues ?? []);\n\tif (!t) {\n\t\tconsole.warn(\"Unable to save shuffled choices because there's no session.\");\n\t\treturn;\n\t}\n\tif (!i(s)) return n(s.map((t) => e.find((e) => e[o] === t)));\n\tlet c = r(e);\n\tif (a && typeof a == \"function\") try {\n\t\tlet e = n(c.map((e) => e[o]));\n\t\ti(e) ? console.error(`shuffledValues is an empty array - refusing to call updateSession. shuffledChoices: ${JSON.stringify(c)}, key: ${o}`) : await a(t.id, t.element, { shuffledValues: e });\n\t} catch (e) {\n\t\tconsole.warn(\"Unable to save shuffled order for choices\"), console.error(e);\n\t}\n\telse console.warn(\"Unable to save shuffled choices, shuffle will happen every time.\");\n\treturn c;\n}\nfunction o(e, t, n) {\n\treturn !!(e.lockChoiceOrder || n?.[\"@pie-element\"]?.lockChoiceOrder);\n}\n//#endregion\n//#region src/partial-scoring.ts\nvar s = /* @__PURE__ */ t({ enabled: () => c });\nfunction c(e, t, n) {\n\treturn e?.partialScoring === !1 || t?.partialScoring === !1 ? !1 : typeof n != \"boolean\" || n;\n}\n//#endregion\nexport { a as getShuffledChoices, o as lockChoices, s as partialScoring };\n","// @ts-nocheck\n\nexport default {\n alternateResponse: {},\n choiceRationaleEnabled: true,\n choices: {},\n disabled: false,\n displayType: 'block',\n markup: '',\n mode: 'gather',\n prompt: '',\n promptEnabled: true,\n rationale: '',\n rationaleEnabled: true,\n shuffle: true,\n studentInstructionsEnabled: true,\n teacherInstructions: '',\n teacherInstructionsEnabled: true,\n toolbarEditorPosition: 'bottom',\n};\n","// @ts-nocheck\n\nimport { forEach } from '@pie-element/shared-lodash';\n\nexport const getAllCorrectResponses = ({ choices, alternateResponse }) => {\n alternateResponse = alternateResponse || {};\n const correctAnswers = {};\n\n forEach(choices, (respArea, key) => {\n if (!correctAnswers[key]) {\n correctAnswers[key] = [];\n }\n\n if (respArea) {\n respArea.forEach((choice) => {\n if (choice.correct) {\n correctAnswers[key].push(choice.value);\n\n if (alternateResponse[key]) {\n correctAnswers[key] = [...correctAnswers[key], ...alternateResponse[key]];\n }\n }\n });\n }\n });\n\n return correctAnswers;\n};\n","// @ts-nocheck\n\nimport { isEmpty, map, reduce } from '@pie-element/shared-lodash';\nimport { lockChoices, getShuffledChoices, partialScoring } from '@pie-element/shared-controller-utils';\nimport defaults from './defaults.js';\n\nimport { getAllCorrectResponses } from './utils.js';\n\nconst getFeedback = (correct) => {\n if (correct) {\n return 'correct';\n }\n\n return 'incorrect';\n};\n\nexport const normalize = (question) => ({ ...defaults, ...question });\n\n/**\n *\n * @param {*} question\n * @param {*} session\n * @param {*} env\n * @param {*} updateSession - optional - a function that will set the properties passed into it on the session.\n */\nexport async function model(question, session, env, updateSession) {\n const normalizedQuestion = normalize(question);\n const { value = {} } = session || {};\n let choices = reduce(\n normalizedQuestion.choices,\n (obj, area, key) => {\n obj[key] = map(area, (choice) => choice);\n\n return obj;\n },\n {},\n );\n\n let feedback = {};\n\n if (env.mode === 'evaluate') {\n const allCorrectResponses = getAllCorrectResponses(normalizedQuestion);\n const respAreaLength = Object.keys(allCorrectResponses).length;\n let correctResponses = 0;\n\n for (let i = 0; i < respAreaLength; i++) {\n const result = reduce(\n allCorrectResponses,\n (obj, choices, key) => {\n const answer = (value && value[key]) || '';\n const correctChoice = choices[i] || '';\n const isCorrect = answer && correctChoice && correctChoice === answer;\n\n obj.feedback[key] = getFeedback(isCorrect);\n\n if (isCorrect) {\n obj.correctResponses += 1;\n }\n\n return obj;\n },\n { correctResponses: 0, feedback: {} },\n );\n\n if (result.correctResponses >= correctResponses) {\n correctResponses = result.correctResponses;\n feedback = result.feedback;\n }\n\n if (result.correctResponses === respAreaLength) {\n break;\n }\n }\n }\n\n const lockChoiceOrder = lockChoices(normalizedQuestion, session, env);\n\n if (!lockChoiceOrder) {\n const shuffledValues = {};\n const keys = Object.keys(choices);\n\n const us = (part) => (id, element, update) => {\n return new Promise((resolve) => {\n shuffledValues[part] = update.shuffledValues;\n resolve();\n });\n };\n\n let i;\n\n for (i = 0; i < keys.length; i++) {\n const key = keys[i];\n const storedValues = session?.shuffledValues?.[key];\n\n choices[key] = await getShuffledChoices(\n choices[key],\n // the shuffledValues structure was updated to an object like { choice_key: [] }\n // and we need to override shuffledValues if it's not an array\n { shuffledValues: Array.isArray(storedValues) ? storedValues : [] },\n us(key),\n 'value',\n );\n }\n\n if (!isEmpty(shuffledValues)) {\n if (session && updateSession && typeof updateSession === 'function') {\n updateSession(session.id, session.element, {\n shuffledValues,\n }).catch((e) => {\n // eslint-disable-next-line no-console\n console.error('update session failed', e);\n });\n }\n }\n }\n\n let teacherInstructions = null;\n let rationale = null;\n\n const choicesWillNullRationales = (Object.keys(choices) || []).reduce((acc, currentValue) => {\n acc[currentValue] = (choices[currentValue] || []).map((choice) => ({\n ...choice,\n rationale: null,\n }));\n\n return acc;\n }, {});\n\n if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {\n rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : null;\n teacherInstructions = normalizedQuestion.teacherInstructionsEnabled ? normalizedQuestion.teacherInstructions : null;\n\n choices = normalizedQuestion.choiceRationaleEnabled ? normalizedQuestion.choices : choicesWillNullRationales;\n } else {\n rationale = null;\n teacherInstructions = null;\n choices = choicesWillNullRationales;\n }\n\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n prompt: normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : null,\n displayType: normalizedQuestion.displayType,\n markup: normalizedQuestion.markup,\n choices,\n feedback,\n\n responseCorrect: env.mode === 'evaluate' ? getScore(normalizedQuestion, session) === 1 : undefined,\n rationale,\n teacherInstructions,\n language: normalizedQuestion.language,\n extraCSSRules: normalizedQuestion.extraCSSRules,\n };\n\n return out;\n}\n\nexport const getScore = (config, session) => {\n const { value = {} } = session || {};\n const maxScore = config && config.choices ? Object.keys(config.choices).length : 0;\n const allCorrectResponses = getAllCorrectResponses(config);\n let correctCount = 0;\n\n for (let i = 0; i < maxScore; i++) {\n const result = reduce(\n allCorrectResponses,\n (total, choices, key) => {\n const answer = (value && value[key]) || '';\n const correctChoice = choices[i] || '';\n\n if (correctChoice && answer && correctChoice === answer) {\n return total;\n }\n\n return total - 1;\n },\n maxScore,\n );\n\n if (result > correctCount) {\n correctCount = result;\n }\n\n if (result === maxScore) {\n break;\n }\n }\n\n const str = (correctCount / maxScore).toFixed(2);\n\n return parseFloat(str);\n};\n\n/**\n * Generates detailed trace log for scoring evaluation\n * @param {Object} model - the question model\n * @param {Object} session - the student session\n * @param {Object} env - the environment\n * @returns {Array} traceLog - array of trace messages\n */\nexport const getLogTrace = (model, session, env) => {\n const traceLog = [];\n const { value = {} } = session || {};\n const allCorrectResponses = getAllCorrectResponses(model);\n const responseAreaKeys = Object.keys(allCorrectResponses);\n const totalAreas = responseAreaKeys.length;\n \n traceLog.push(`${totalAreas} dropdown response area(s) defined in this question.`);\n \n if (value && Object.keys(value).length > 0) {\n const selectedAreas = Object.entries(value).filter(([key, val]) => val && val.trim()).length;\n traceLog.push(`Student selected options in ${selectedAreas} out of ${totalAreas} dropdown(s).`);\n \n responseAreaKeys.forEach((areaKey) => {\n const studentSelection = (value && value[areaKey]) || '';\n const correctOptions = allCorrectResponses[areaKey] || [];\n \n if (studentSelection.trim()) {\n traceLog.push(`Dropdown ${parseInt(areaKey) + 1}: student selected '${studentSelection}' (correct options: [${correctOptions.map(opt => `'${opt}'`).join(', ')}]).`);\n } else {\n traceLog.push(`Dropdown ${parseInt(areaKey) + 1}: no selection made (correct options: [${correctOptions.map(opt => `'${opt}'`).join(', ')}]).`);\n }\n });\n } else {\n traceLog.push('Student did not make any selections in the dropdowns.');\n }\n\n const partialScoringEnabled = partialScoring.enabled(model, env);\n traceLog.push(\n `Scoring method: ${\n partialScoringEnabled ? 'partial scoring' : 'all-or-nothing scoring'\n }.`\n );\n\n const score = getScore(model, session);\n traceLog.push(`Final score: ${score}.`);\n\n return traceLog;\n}\n\n/**\n *\n * The score is partial by default for checkbox mode, allOrNothing for radio mode.\n * To disable partial scoring for checkbox mode you either set model.partialScoring = false or env.partialScoring =\n * false. the value in `env` will override the value in `model`.\n * @param {Object} model - the main model\n * @param {boolean} model.partialScoring - is partial scoring enabled (if undefined set to to true)\n * @param {*} session\n * @param {Object} env\n * @param {boolean} env.partialScoring - is partial scoring enabled (if undefined default to true) This overrides\n * `model.partialScoring`.\n */\nexport function outcome(model, session, env = {}) {\n return new Promise((resolve) => {\n if (!session || isEmpty(session)) {\n resolve({ \n score: 0, \n empty: true, \n traceLog: ['Student did not make any selections in the dropdowns. Score is 0.'] \n });\n } else {\n const traceLog = getLogTrace(model, session, env);\n const score = getScore(model, session);\n const partialScoringEnabled = partialScoring.enabled(model, env);\n\n resolve({\n score: partialScoringEnabled ? score : Math.floor(score),\n empty: false,\n traceLog\n });\n }\n });\n}\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const { choices } = question;\n const value = {};\n\n if (choices) {\n Object.keys(choices).forEach((key, i) => {\n const correctChoices = choices[key] && choices[key].filter((c) => c.correct);\n\n value[i] = correctChoices && correctChoices[0].value;\n });\n }\n\n resolve({\n id: '1',\n value,\n });\n } else {\n resolve(null);\n }\n });\n};\n\n// remove all html tags\nconst getInnerText = (html) => (html || '').replaceAll(/<[^>]*>/g, '');\n\n// remove all html tags except img, iframe and source tag for audio\nconst getContent = (html) => (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/gi, '');\n\nexport const validate = (model = {}, config = {}) => {\n const { markup, choices } = model;\n const { maxResponseAreas, maxResponseAreaChoices } = config;\n const errors = {};\n\n ['teacherInstructions', 'prompt', 'rationale'].forEach((field) => {\n if (config[field]?.required && !getContent(model[field])) {\n errors[field] = 'This field is required.';\n }\n });\n\n const nbOfResponseAreas = ((markup || '').match(/\\{\\{(\\d+)\\}\\}/g) || []).length;\n\n if (nbOfResponseAreas > maxResponseAreas) {\n errors.responseAreasError = `No more than ${maxResponseAreas} response areas should be defined.`;\n } else if (nbOfResponseAreas < 1) {\n errors.responseAreasError = 'There should be defined at least 1 response area.';\n }\n\n (Object.keys(choices) || []).forEach((choiceKey) => {\n if (choices[choiceKey] && choices[choiceKey].length > maxResponseAreaChoices) {\n errors.responseAreaChoicesError = `No more than ${maxResponseAreaChoices} choices per response area should be defined.`;\n }\n });\n\n return errors;\n};\n"],"mappings":";;AACA,IAAI,IAAI,OAAO,gBAAgB,KAAK,GAAG,MAAM;CAC5C,IAAI,IAAI,CAAC;CACT,KAAK,IAAI,KAAK,GAAG,EAAE,GAAG,GAAG;EACxB,KAAK,EAAE;EACP,YAAY,CAAC;CACd,CAAC;CACD,OAAO,KAAK,EAAE,GAAG,OAAO,aAAa,EAAE,OAAO,SAAS,CAAC,GAAG;AAC5D;AAGA,SAAS,EAAE,GAAG;CACb,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,QAAQ,MAAM,KAAK,IAAI,IAAI,CAAC;AACzD;AACA,SAAS,EAAE,GAAG;CACb,IAAI,IAAI,CAAC,GAAG,CAAC;CACb,KAAK,IAAI,IAAI,EAAE,SAAS,GAAG,IAAI,GAAG,KAAK;EACtC,IAAI,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE;EAC1C,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE;CAC3B;CACA,OAAO;AACR;AACA,SAAS,EAAE,GAAG;CACb,OAAO,KAAK,OAAO,CAAC,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,WAAW,IAAI,OAAO,KAAK,YAAY,OAAO,KAAK,CAAC,CAAC,CAAC,WAAW;AAC/G;AACA,eAAe,EAAE,GAAG,GAAG,GAAG,IAAI,SAAS;CACtC,IAAI,IAAI,EAAE,GAAG,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,CAAC;CAC5D,IAAI,CAAC,GAAG;EACP,QAAQ,KAAK,6DAA6D;EAC1E;CACD;CACA,IAAI,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC3D,IAAI,IAAI,EAAE,CAAC;CACX,IAAI,KAAK,OAAO,KAAK,YAAY,IAAI;EACpC,IAAI,IAAI,EAAE,EAAE,KAAK,MAAM,EAAE,EAAE,CAAC;EAC5B,EAAE,CAAC,IAAI,QAAQ,MAAM,uFAAuF,KAAK,UAAU,CAAC,EAAE,SAAS,GAAG,IAAI,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC;CAC7L,SAAS,GAAG;EACX,QAAQ,KAAK,2CAA2C,GAAG,QAAQ,MAAM,CAAC;CAC3E;MACK,QAAQ,KAAK,kEAAkE;CACpF,OAAO;AACR;AACA,SAAS,EAAE,GAAG,GAAG,GAAG;CACnB,OAAO,CAAC,EAAE,EAAE,mBAAmB,IAAI,eAAe,EAAE;AACrD;AAGA,IAAI,IAAoB,kBAAE,EAAE,eAAe,EAAE,CAAC;AAC9C,SAAS,EAAE,GAAG,GAAG,GAAG;CACnB,OAAO,GAAG,mBAAmB,CAAC,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,OAAO,KAAK,aAAa;AAC7F;;;AChDA,IAAA,IAAe;CACb,mBAAmB,CAAC;CACpB,wBAAwB;CACxB,SAAS,CAAC;CACV,UAAU;CACV,aAAa;CACb,QAAQ;CACR,MAAM;CACN,QAAQ;CACR,eAAe;CACf,WAAW;CACX,kBAAkB;CAClB,SAAS;CACT,4BAA4B;CAC5B,qBAAqB;CACrB,4BAA4B;CAC5B,uBAAuB;AACzB,GCfa,KAA0B,EAAE,YAAS,2BAAwB;CACxE,MAAyC,CAAC;CAC1C,IAAM,IAAiB,CAAC;CAoBxB,OAlBA,EAAQ,IAAU,GAAU,MAAQ;EAKlC,AAJK,EAAe,OAClB,EAAe,KAAO,CAAC,IAGrB,KACF,EAAS,SAAS,MAAW;GAC3B,AAAI,EAAO,YACT,EAAe,EAAI,CAAC,KAAK,EAAO,KAAK,GAEjC,EAAkB,OACpB,EAAe,KAAO,CAAC,GAAG,EAAe,IAAM,GAAG,EAAkB,EAAI;EAG9E,CAAC;CAEL,CAAC,GAEM;AACT,GCnBM,KAAe,MACf,IACK,YAGF,aAGI,KAAa,OAAc;CAAE,GAAG;CAAU,GAAG;AAAS;AASnE,eAAsB,EAAM,GAAU,GAAS,GAAK,GAAe;CACjE,IAAM,IAAqB,EAAU,CAAQ,GACvC,EAAE,WAAQ,CAAC,MAAM,KAAW,CAAC,GAC/B,IAAU,EACZ,EAAmB,UAClB,GAAK,GAAM,OACV,EAAI,KAAO,EAAI,IAAO,MAAW,CAAM,GAEhC,IAET,CAAC,CACH,GAEI,IAAW,CAAC;CAEhB,IAAI,EAAI,SAAS,YAAY;EAC3B,IAAM,IAAsB,EAAuB,CAAkB,GAC/D,IAAiB,OAAO,KAAK,CAAmB,CAAC,CAAC,QACpD,IAAmB;EAEvB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAgB,KAAK;GACvC,IAAM,IAAS,EACb,IACC,GAAK,GAAS,MAAQ;IACrB,IAAM,IAAU,KAAS,EAAM,MAAS,IAClC,IAAgB,EAAQ,MAAM,IAC9B,IAAY,KAAU,KAAiB,MAAkB;IAQ/D,OANA,EAAI,SAAS,KAAO,EAAY,CAAS,GAErC,MACF,EAAI,oBAAoB,IAGnB;GACT,GACA;IAAE,kBAAkB;IAAG,UAAU,CAAC;GAAE,CACtC;GAOA,IALI,EAAO,oBAAoB,MAC7B,IAAmB,EAAO,kBAC1B,IAAW,EAAO,WAGhB,EAAO,qBAAqB,GAC9B;EAEJ;CACF;CAIA,IAAI,CAFoB,EAAY,GAAoB,GAAS,CAE5D,GAAiB;EACpB,IAAM,IAAiB,CAAC,GAClB,IAAO,OAAO,KAAK,CAAO,GAE1B,KAAM,OAAU,GAAI,GAAS,MAC1B,IAAI,SAAS,MAAY;GAE9B,AADA,EAAe,KAAQ,EAAO,gBAC9B,EAAQ;EACV,CAAC,GAGC;EAEJ,KAAK,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK;GAChC,IAAM,IAAM,EAAK,IACX,IAAe,GAAS,iBAAiB;GAE/C,EAAQ,KAAO,MAAM,EACnB,EAAQ,IAGR,EAAE,gBAAgB,MAAM,QAAQ,CAAY,IAAI,IAAe,CAAC,EAAE,GAClE,EAAG,CAAG,GACN,OACF;EACF;EAEA,AAAK,EAAQ,CAAc,KACrB,KAAW,KAAiB,OAAO,KAAkB,cACvD,EAAc,EAAQ,IAAI,EAAQ,SAAS,EACzC,kBACF,CAAC,CAAC,CAAC,OAAO,MAAM;GAEd,QAAQ,MAAM,yBAAyB,CAAC;EAC1C,CAAC;CAGP;CAEA,IAAI,IAAsB,MACtB,IAAY,MAEV,KAA6B,OAAO,KAAK,CAAO,KAAK,CAAC,EAAA,CAAG,QAAQ,GAAK,OAC1E,EAAI,MAAiB,EAAQ,MAAiB,CAAC,EAAA,CAAG,KAAK,OAAY;EACjE,GAAG;EACH,WAAW;CACb,EAAE,GAEK,IACN,CAAC,CAAC;CA6BL,OA3BI,EAAI,SAAS,iBAAiB,EAAI,SAAS,UAAU,EAAI,SAAS,eACpE,IAAY,EAAmB,mBAAmB,EAAmB,YAAY,MACjF,IAAsB,EAAmB,6BAA6B,EAAmB,sBAAsB,MAE/G,IAAU,EAAmB,yBAAyB,EAAmB,UAAU,MAEnF,IAAY,MACZ,IAAsB,MACtB,IAAU,IAmBL;EAfL,UAAU,EAAI,SAAS;EACvB,MAAM,EAAI;EACV,QAAQ,EAAmB,gBAAgB,EAAmB,SAAS;EACvE,aAAa,EAAmB;EAChC,QAAQ,EAAmB;EAC3B;EACA;EAEA,iBAAiB,EAAI,SAAS,aAAa,EAAS,GAAoB,CAAO,MAAM,IAAI,KAAA;EACzF;EACA;EACA,UAAU,EAAmB;EAC7B,eAAe,EAAmB;CAG7B;AACT;AAEA,IAAa,KAAY,GAAQ,MAAY;CAC3C,IAAM,EAAE,WAAQ,CAAC,MAAM,KAAW,CAAC,GAC7B,IAAW,KAAU,EAAO,UAAU,OAAO,KAAK,EAAO,OAAO,CAAC,CAAC,SAAS,GAC3E,IAAsB,EAAuB,CAAM,GACrD,IAAe;CAEnB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAU,KAAK;EACjC,IAAM,IAAS,EACb,IACC,GAAO,GAAS,MAAQ;GACvB,IAAM,IAAU,KAAS,EAAM,MAAS,IAClC,IAAgB,EAAQ,MAAM;GAMpC,OAJI,KAAiB,KAAU,MAAkB,IACxC,IAGF,IAAQ;EACjB,GACA,CACF;EAMA,IAJI,IAAS,MACX,IAAe,IAGb,MAAW,GACb;CAEJ;CAEA,IAAM,KAAO,IAAe,EAAA,CAAU,QAAQ,CAAC;CAE/C,OAAO,WAAW,CAAG;AACvB,GASa,KAAe,GAAO,GAAS,MAAQ;CAClD,IAAM,IAAW,CAAC,GACZ,EAAE,WAAQ,CAAC,MAAM,KAAW,CAAC,GAC7B,IAAsB,EAAuB,CAAK,GAClD,IAAmB,OAAO,KAAK,CAAmB,GAClD,IAAa,EAAiB;CAIpC,IAFA,EAAS,KAAK,GAAG,EAAW,qDAAqD,GAE7E,KAAS,OAAO,KAAK,CAAK,CAAC,CAAC,SAAS,GAAG;EAC1C,IAAM,IAAgB,OAAO,QAAQ,CAAK,CAAC,CAAC,QAAQ,CAAC,GAAK,OAAS,KAAO,EAAI,KAAK,CAAC,CAAC,CAAC;EAGtF,AAFA,EAAS,KAAK,+BAA+B,EAAc,UAAU,EAAW,cAAc,GAE9F,EAAiB,SAAS,MAAY;GACpC,IAAM,IAAoB,KAAS,EAAM,MAAa,IAChD,IAAiB,EAAoB,MAAY,CAAC;GAExD,AAAI,EAAiB,KAAK,IACxB,EAAS,KAAK,YAAY,SAAS,CAAO,IAAI,EAAE,sBAAsB,EAAiB,uBAAuB,EAAe,KAAI,MAAO,IAAI,EAAI,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,IAAI,IAEnK,EAAS,KAAK,YAAY,SAAS,CAAO,IAAI,EAAE,yCAAyC,EAAe,KAAI,MAAO,IAAI,EAAI,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,IAAI;EAElJ,CAAC;CACH,OACE,EAAS,KAAK,uDAAuD;CAGvE,IAAM,IAAwB,EAAe,QAAQ,GAAO,CAAG;CAC/D,EAAS,KACP,mBACE,IAAwB,oBAAoB,yBAC7C,EACH;CAEA,IAAM,IAAQ,EAAS,GAAO,CAAO;CAGrC,OAFA,EAAS,KAAK,gBAAgB,EAAM,EAAE,GAE/B;AACT;AAcA,SAAgB,EAAQ,GAAO,GAAS,IAAM,CAAC,GAAG;CAChD,OAAO,IAAI,SAAS,MAAY;EAC9B,IAAI,CAAC,KAAW,EAAQ,CAAO,GAC7B,EAAQ;GACN,OAAO;GACP,OAAO;GACP,UAAU,CAAC,mEAAmE;EAChF,CAAC;OACI;GACL,IAAM,IAAW,EAAY,GAAO,GAAS,CAAG,GAC1C,IAAQ,EAAS,GAAO,CAAO;GAGrC,EAAQ;IACN,OAH4B,EAAe,QAAQ,GAAO,CAGnD,IAAwB,IAAQ,KAAK,MAAM,CAAK;IACvD,OAAO;IACP;GACF,CAAC;EACH;CACF,CAAC;AACH;AAEA,IAAa,KAAgC,GAAU,MAC9C,IAAI,SAAS,MAAY;CAC9B,IAAI,EAAI,SAAS,cAAc,EAAI,SAAS,cAAc;EACxD,IAAM,EAAE,eAAY,GACd,IAAQ,CAAC;EAUf,AARI,KACF,OAAO,KAAK,CAAO,CAAC,CAAC,SAAS,GAAK,MAAM;GACvC,IAAM,IAAiB,EAAQ,MAAQ,EAAQ,EAAI,CAAC,QAAQ,MAAM,EAAE,OAAO;GAE3E,EAAM,KAAK,KAAkB,EAAe,EAAE,CAAC;EACjD,CAAC,GAGH,EAAQ;GACN,IAAI;GACJ;EACF,CAAC;CACH,OACE,EAAQ,IAAI;AAEhB,CAAC,GAOG,KAAc,OAAU,KAAQ,GAAA,CAAI,QAAQ,sCAAsC,EAAE,GAE7E,KAAY,IAAQ,CAAC,GAAG,IAAS,CAAC,MAAM;CACnD,IAAM,EAAE,WAAQ,eAAY,GACtB,EAAE,qBAAkB,8BAA2B,GAC/C,IAAS,CAAC;CAEhB;EAAC;EAAuB;EAAU;CAAW,CAAC,CAAC,SAAS,MAAU;EAChE,AAAI,EAAO,EAAM,EAAE,YAAY,CAAC,EAAW,EAAM,EAAM,MACrD,EAAO,KAAS;CAEpB,CAAC;CAED,IAAM,MAAsB,KAAU,GAAA,CAAI,MAAM,gBAAgB,KAAK,CAAC,EAAA,CAAG;CAczE,OAZI,IAAoB,IACtB,EAAO,qBAAqB,gBAAgB,EAAiB,sCACpD,IAAoB,MAC7B,EAAO,qBAAqB,uDAG7B,OAAO,KAAK,CAAO,KAAK,CAAC,EAAA,CAAG,SAAS,MAAc;EAClD,AAAI,EAAQ,MAAc,EAAQ,EAAU,CAAC,SAAS,MACpD,EAAO,2BAA2B,gBAAgB,EAAuB;CAE7E,CAAC,GAEM;AACT"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../../shared/controller-utils/dist/index.js","../../../../src/controller/defaults.ts","../../../../src/controller/utils.ts","../../../../src/controller/index.ts"],"sourcesContent":["//#region \\0rolldown/runtime.js\nvar e = Object.defineProperty, t = (t, n) => {\n\tlet r = {};\n\tfor (var i in t) e(r, i, {\n\t\tget: t[i],\n\t\tenumerable: !0\n\t});\n\treturn n || e(r, Symbol.toStringTag, { value: \"Module\" }), r;\n};\n//#endregion\n//#region src/persistence.ts\nfunction n(e) {\n\treturn Array.isArray(e) ? e.filter((e) => e != null) : [];\n}\nfunction r(e) {\n\tlet t = [...e];\n\tfor (let e = t.length - 1; e > 0; e--) {\n\t\tlet n = Math.floor(Math.random() * (e + 1));\n\t\t[t[e], t[n]] = [t[n], t[e]];\n\t}\n\treturn t;\n}\nfunction i(e) {\n\treturn e == null ? !0 : Array.isArray(e) ? e.length === 0 : typeof e == \"object\" && Object.keys(e).length === 0;\n}\nasync function a(e, t, a, o = \"value\") {\n\tlet s = n(t?.data?.shuffledValues ?? t?.shuffledValues ?? []);\n\tif (!t) {\n\t\tconsole.warn(\"Unable to save shuffled choices because there's no session.\");\n\t\treturn;\n\t}\n\tif (!i(s)) return n(s.map((t) => e.find((e) => e[o] === t)));\n\tlet c = r(e);\n\tif (a && typeof a == \"function\") try {\n\t\tlet e = n(c.map((e) => e[o]));\n\t\ti(e) ? console.error(`shuffledValues is an empty array - refusing to call updateSession. shuffledChoices: ${JSON.stringify(c)}, key: ${o}`) : await a(t.id, t.element, { shuffledValues: e });\n\t} catch (e) {\n\t\tconsole.warn(\"Unable to save shuffled order for choices\"), console.error(e);\n\t}\n\telse console.warn(\"Unable to save shuffled choices, shuffle will happen every time.\");\n\treturn c;\n}\nfunction o(e, t, n) {\n\treturn !!(e.lockChoiceOrder || n?.[\"@pie-element\"]?.lockChoiceOrder);\n}\n//#endregion\n//#region src/partial-scoring.ts\nvar s = /* @__PURE__ */ t({ enabled: () => c });\nfunction c(e, t, n) {\n\treturn e?.partialScoring === !1 || t?.partialScoring === !1 ? !1 : typeof n != \"boolean\" || n;\n}\n//#endregion\nexport { a as getShuffledChoices, o as lockChoices, s as partialScoring };\n","import type { InlineDropdownModel } from '../types.js';\n\nexport default {\n alternateResponse: {},\n choiceRationaleEnabled: true,\n choices: {},\n disabled: false,\n displayType: 'block',\n markup: '',\n mode: 'gather',\n prompt: '',\n promptEnabled: true,\n rationale: '',\n rationaleEnabled: true,\n shuffle: true,\n studentInstructionsEnabled: true,\n teacherInstructions: '',\n teacherInstructionsEnabled: true,\n toolbarEditorPosition: 'bottom',\n} satisfies Omit<InlineDropdownModel, 'id' | 'element'>;\n","import { forEach } from '@pie-element/shared-lodash';\nimport type { Choice, InlineDropdownModel } from '../types.js';\n\nexport const getAllCorrectResponses = ({\n choices,\n alternateResponse,\n}: Partial<Pick<InlineDropdownModel, 'choices' | 'alternateResponse'>>) => {\n alternateResponse = alternateResponse || {};\n const correctAnswers: Record<string, string[]> = {};\n\n forEach<Choice[]>(choices, (respArea, key) => {\n if (!correctAnswers[key]) {\n correctAnswers[key] = [];\n }\n\n if (respArea) {\n respArea.forEach((choice) => {\n if (choice.correct) {\n correctAnswers[key].push(choice.value);\n\n if (alternateResponse[key]) {\n correctAnswers[key] = [...correctAnswers[key], ...alternateResponse[key]];\n }\n }\n });\n }\n });\n\n return correctAnswers;\n};\n","import { isEmpty, map, reduce } from '@pie-element/shared-lodash';\nimport { lockChoices, getShuffledChoices, partialScoring } from '@pie-element/shared-controller-utils';\nimport type { PieEnvironment, PieUpdateSession } from '@pie-element/shared-types';\nimport defaults from './defaults.js';\n\nimport { getAllCorrectResponses } from './utils.js';\nimport type {\n Choice,\n Choices,\n InlineDropdownConfiguration,\n InlineDropdownModel,\n InlineDropdownSession,\n} from '../types.js';\n\n/** Errors `validate()` reports, keyed by field. */\nexport type InlineDropdownValidationErrors = {\n teacherInstructions?: string;\n prompt?: string;\n rationale?: string;\n responseAreasError?: string;\n responseAreaChoicesError?: string;\n};\n\n/** A choice as the controller hands it to the delivery: rationales are `null` unless the instructor sees them */\ntype DeliveryChoice = Omit<Choice, 'rationale'> & { rationale?: string | null };\n\nconst getFeedback = (correct: unknown) => {\n if (correct) {\n return 'correct';\n }\n\n return 'incorrect';\n};\n\nexport const normalize = (question: InlineDropdownModel) => ({ ...defaults, ...question });\n\n/**\n *\n * @param {*} question\n * @param {*} session\n * @param {*} env\n * @param {*} updateSession - optional - a function that will set the properties passed into it on the session.\n */\nexport async function model(\n question: InlineDropdownModel,\n session: InlineDropdownSession | null | undefined,\n env: PieEnvironment,\n updateSession?: PieUpdateSession,\n) {\n const normalizedQuestion = normalize(question);\n const { value = {} } = session || {};\n let choices = reduce<Choice[], Record<string, DeliveryChoice[] | undefined>>(\n normalizedQuestion.choices,\n (obj, area, key) => {\n obj[key] = map(area, (choice) => choice);\n\n return obj;\n },\n {},\n );\n\n let feedback: Record<string, string> = {};\n\n if (env.mode === 'evaluate') {\n const allCorrectResponses = getAllCorrectResponses(normalizedQuestion);\n const respAreaLength = Object.keys(allCorrectResponses).length;\n let correctResponses = 0;\n\n for (let i = 0; i < respAreaLength; i++) {\n const result = reduce<string[], { correctResponses: number; feedback: Record<string, string> }>(\n allCorrectResponses,\n (obj, choices, key) => {\n const answer = (value && value[key]) || '';\n const correctChoice = choices[i] || '';\n const isCorrect = answer && correctChoice && correctChoice === answer;\n\n obj.feedback[key] = getFeedback(isCorrect);\n\n if (isCorrect) {\n obj.correctResponses += 1;\n }\n\n return obj;\n },\n { correctResponses: 0, feedback: {} },\n );\n\n if (result.correctResponses >= correctResponses) {\n correctResponses = result.correctResponses;\n feedback = result.feedback;\n }\n\n if (result.correctResponses === respAreaLength) {\n break;\n }\n }\n }\n\n // `lockChoices` ignores the session, so the per-area `shuffledValues` shape does not matter to it.\n const lockChoiceOrder = lockChoices(normalizedQuestion, session as Parameters<typeof lockChoices>[1], env);\n\n if (!lockChoiceOrder) {\n const shuffledValues: Record<string, string[]> = {};\n const keys = Object.keys(choices);\n\n const us =\n (part: string): PieUpdateSession =>\n (_id, _element, update) => {\n return new Promise((resolve) => {\n shuffledValues[part] = update.shuffledValues as string[];\n resolve();\n });\n };\n\n let i;\n\n for (i = 0; i < keys.length; i++) {\n const key = keys[i];\n const storedValues = (session?.shuffledValues as Record<string, string[]> | undefined)?.[key];\n\n choices[key] = await getShuffledChoices(\n choices[key] as DeliveryChoice[],\n // the shuffledValues structure was updated to an object like { choice_key: [] }\n // and we need to override shuffledValues if it's not an array\n { shuffledValues: Array.isArray(storedValues) ? storedValues : [] },\n us(key),\n 'value',\n );\n }\n\n if (!isEmpty(shuffledValues)) {\n if (session && updateSession && typeof updateSession === 'function') {\n updateSession(session.id as string, session.element as string, {\n shuffledValues,\n }).catch((e) => {\n // eslint-disable-next-line no-console\n console.error('update session failed', e);\n });\n }\n }\n }\n\n let teacherInstructions: string | null | undefined = null;\n let rationale: string | null | undefined = null;\n\n const choicesWillNullRationales = (Object.keys(choices) || []).reduce<Record<string, DeliveryChoice[]>>((acc, currentValue) => {\n acc[currentValue] = (choices[currentValue] || []).map((choice) => ({\n ...choice,\n rationale: null,\n }));\n\n return acc;\n }, {});\n\n if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {\n rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : null;\n teacherInstructions = normalizedQuestion.teacherInstructionsEnabled ? normalizedQuestion.teacherInstructions : null;\n\n choices = normalizedQuestion.choiceRationaleEnabled ? normalizedQuestion.choices : choicesWillNullRationales;\n } else {\n rationale = null;\n teacherInstructions = null;\n choices = choicesWillNullRationales;\n }\n\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n prompt: normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : null,\n displayType: normalizedQuestion.displayType,\n markup: normalizedQuestion.markup,\n choices,\n feedback,\n\n responseCorrect: env.mode === 'evaluate' ? getScore(normalizedQuestion, session) === 1 : undefined,\n rationale,\n teacherInstructions,\n language: normalizedQuestion.language,\n extraCSSRules: normalizedQuestion.extraCSSRules,\n };\n\n return out;\n}\n\nexport const getScore = (\n config: Partial<Pick<InlineDropdownModel, 'choices' | 'alternateResponse'>>,\n session: InlineDropdownSession | null | undefined,\n) => {\n const { value = {} } = session || {};\n const maxScore = config && config.choices ? Object.keys(config.choices).length : 0;\n const allCorrectResponses = getAllCorrectResponses(config);\n let correctCount = 0;\n\n for (let i = 0; i < maxScore; i++) {\n const result = reduce<string[], number>(\n allCorrectResponses,\n (total, choices, key) => {\n const answer = (value && value[key]) || '';\n const correctChoice = choices[i] || '';\n\n if (correctChoice && answer && correctChoice === answer) {\n return total;\n }\n\n return total - 1;\n },\n maxScore,\n );\n\n if (result > correctCount) {\n correctCount = result;\n }\n\n if (result === maxScore) {\n break;\n }\n }\n\n const str = (correctCount / maxScore).toFixed(2);\n\n return parseFloat(str);\n};\n\n/**\n * Generates detailed trace log for scoring evaluation\n * @param {Object} model - the question model\n * @param {Object} session - the student session\n * @param {Object} env - the environment\n * @returns {Array} traceLog - array of trace messages\n */\nexport const getLogTrace = (\n model: InlineDropdownModel,\n session: InlineDropdownSession | null | undefined,\n env: Partial<PieEnvironment>,\n) => {\n const traceLog: string[] = [];\n const { value = {} } = session || {};\n const allCorrectResponses = getAllCorrectResponses(model);\n const responseAreaKeys = Object.keys(allCorrectResponses);\n const totalAreas = responseAreaKeys.length;\n \n traceLog.push(`${totalAreas} dropdown response area(s) defined in this question.`);\n \n if (value && Object.keys(value).length > 0) {\n const selectedAreas = Object.entries(value).filter(([, val]) => val && val.trim()).length;\n traceLog.push(`Student selected options in ${selectedAreas} out of ${totalAreas} dropdown(s).`);\n \n responseAreaKeys.forEach((areaKey) => {\n const studentSelection = (value && value[areaKey]) || '';\n const correctOptions = allCorrectResponses[areaKey] || [];\n \n if (studentSelection.trim()) {\n traceLog.push(`Dropdown ${parseInt(areaKey) + 1}: student selected '${studentSelection}' (correct options: [${correctOptions.map(opt => `'${opt}'`).join(', ')}]).`);\n } else {\n traceLog.push(`Dropdown ${parseInt(areaKey) + 1}: no selection made (correct options: [${correctOptions.map(opt => `'${opt}'`).join(', ')}]).`);\n }\n });\n } else {\n traceLog.push('Student did not make any selections in the dropdowns.');\n }\n\n const partialScoringEnabled = partialScoring.enabled(model, env);\n traceLog.push(\n `Scoring method: ${\n partialScoringEnabled ? 'partial scoring' : 'all-or-nothing scoring'\n }.`\n );\n\n const score = getScore(model, session);\n traceLog.push(`Final score: ${score}.`);\n\n return traceLog;\n}\n\n/**\n *\n * The score is partial by default for checkbox mode, allOrNothing for radio mode.\n * To disable partial scoring for checkbox mode you either set model.partialScoring = false or env.partialScoring =\n * false. the value in `env` will override the value in `model`.\n * @param {Object} model - the main model\n * @param {boolean} model.partialScoring - is partial scoring enabled (if undefined set to to true)\n * @param {*} session\n * @param {Object} env\n * @param {boolean} env.partialScoring - is partial scoring enabled (if undefined default to true) This overrides\n * `model.partialScoring`.\n */\nexport function outcome(\n model: InlineDropdownModel,\n session: InlineDropdownSession | null | undefined,\n env: Partial<PieEnvironment> = {},\n) {\n return new Promise<{ score: number; empty: boolean; traceLog: string[] }>((resolve) => {\n if (!session || isEmpty(session)) {\n resolve({ \n score: 0, \n empty: true, \n traceLog: ['Student did not make any selections in the dropdowns. Score is 0.'] \n });\n } else {\n const traceLog = getLogTrace(model, session, env);\n const score = getScore(model, session);\n const partialScoringEnabled = partialScoring.enabled(model, env);\n\n resolve({\n score: partialScoringEnabled ? score : Math.floor(score),\n empty: false,\n traceLog\n });\n }\n });\n}\n\nexport const createCorrectResponseSession = (question: InlineDropdownModel, env: PieEnvironment) => {\n return new Promise<InlineDropdownSession | null>((resolve) => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const { choices } = question;\n const value: Record<string, string> = {};\n\n if (choices) {\n Object.keys(choices).forEach((key, i) => {\n const correctChoices = choices[key] && choices[key].filter((c) => c.correct);\n\n value[i] = correctChoices && correctChoices[0].value;\n });\n }\n\n resolve({\n id: '1',\n value,\n });\n } else {\n resolve(null);\n }\n });\n};\n\n// remove all html tags except img, iframe and source tag for audio\nconst getContent = (html: string | undefined) => (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/gi, '');\n\nexport const validate = (\n model: Partial<InlineDropdownModel> = {},\n config: InlineDropdownConfiguration = {},\n) => {\n const { markup, choices } = model;\n const { maxResponseAreas, maxResponseAreaChoices } = config;\n const errors: InlineDropdownValidationErrors = {};\n\n (['teacherInstructions', 'prompt', 'rationale'] as const).forEach((field) => {\n if (config[field]?.required && !getContent(model[field])) {\n errors[field] = 'This field is required.';\n }\n });\n\n const nbOfResponseAreas = ((markup || '').match(/\\{\\{(\\d+)\\}\\}/g) || []).length;\n\n if (maxResponseAreas !== undefined && nbOfResponseAreas > maxResponseAreas) {\n errors.responseAreasError = `No more than ${maxResponseAreas} response areas should be defined.`;\n } else if (nbOfResponseAreas < 1) {\n errors.responseAreasError = 'There should be defined at least 1 response area.';\n }\n\n // `Object.keys` throws when the model has no `choices`.\n const allChoices = choices as Choices;\n\n (Object.keys(allChoices) || []).forEach((choiceKey) => {\n if (\n allChoices[choiceKey] &&\n maxResponseAreaChoices !== undefined &&\n allChoices[choiceKey].length > maxResponseAreaChoices\n ) {\n errors.responseAreaChoicesError = `No more than ${maxResponseAreaChoices} choices per response area should be defined.`;\n }\n });\n\n return errors;\n};\n"],"mappings":"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"}
@@ -1,19 +1,19 @@
1
1
  declare const _default: {
2
2
  alternateResponse: {};
3
- choiceRationaleEnabled: boolean;
3
+ choiceRationaleEnabled: true;
4
4
  choices: {};
5
- disabled: boolean;
5
+ disabled: false;
6
6
  displayType: string;
7
7
  markup: string;
8
- mode: string;
8
+ mode: "gather";
9
9
  prompt: string;
10
- promptEnabled: boolean;
10
+ promptEnabled: true;
11
11
  rationale: string;
12
- rationaleEnabled: boolean;
13
- shuffle: boolean;
14
- studentInstructionsEnabled: boolean;
12
+ rationaleEnabled: true;
13
+ shuffle: true;
14
+ studentInstructionsEnabled: true;
15
15
  teacherInstructions: string;
16
- teacherInstructionsEnabled: boolean;
17
- toolbarEditorPosition: string;
16
+ teacherInstructionsEnabled: true;
17
+ toolbarEditorPosition: "bottom";
18
18
  };
19
19
  export default _default;
@@ -1,4 +1,48 @@
1
- export declare const normalize: (question: any) => any;
1
+ import type { PieEnvironment, PieUpdateSession } from '@pie-element/shared-types';
2
+ import type { Choice, Choices, InlineDropdownConfiguration, InlineDropdownModel, InlineDropdownSession } from '../types.js';
3
+ /** Errors `validate()` reports, keyed by field. */
4
+ export type InlineDropdownValidationErrors = {
5
+ teacherInstructions?: string;
6
+ prompt?: string;
7
+ rationale?: string;
8
+ responseAreasError?: string;
9
+ responseAreaChoicesError?: string;
10
+ };
11
+ /** A choice as the controller hands it to the delivery: rationales are `null` unless the instructor sees them */
12
+ type DeliveryChoice = Omit<Choice, 'rationale'> & {
13
+ rationale?: string | null;
14
+ };
15
+ export declare const normalize: (question: InlineDropdownModel) => {
16
+ choices: Choices;
17
+ alternateResponse: {};
18
+ alternateResponses?: import("../types.js").AlternateResponse;
19
+ markup: string;
20
+ slateMarkup?: string;
21
+ prompt: string;
22
+ promptEnabled: boolean;
23
+ lockChoiceOrder?: boolean;
24
+ partialScoring?: boolean;
25
+ rationale: string;
26
+ scoringType?: "auto" | "rubric";
27
+ studentInstructions?: string;
28
+ teacherInstructions: string;
29
+ rationaleEnabled: boolean;
30
+ spellCheckEnabled?: boolean;
31
+ choiceRationaleEnabled: boolean;
32
+ studentInstructionsEnabled: boolean;
33
+ teacherInstructionsEnabled: boolean;
34
+ displayType: string;
35
+ toolbarEditorPosition: "bottom" | "top";
36
+ rubricEnabled?: boolean;
37
+ language?: string;
38
+ extraCSSRules?: import("@pie-element/shared-types").ExtraCSSRules;
39
+ shuffle: boolean;
40
+ disabled: boolean;
41
+ mode: "gather" | "view" | "evaluate";
42
+ id: string;
43
+ element: string;
44
+ accessibilityCatalogs?: import("@pie-element/shared-types").AccessibilityCatalog[];
45
+ };
2
46
  /**
3
47
  *
4
48
  * @param {*} question
@@ -6,21 +50,21 @@ export declare const normalize: (question: any) => any;
6
50
  * @param {*} env
7
51
  * @param {*} updateSession - optional - a function that will set the properties passed into it on the session.
8
52
  */
9
- export declare function model(question: any, session: any, env: any, updateSession: any): Promise<{
53
+ export declare function model(question: InlineDropdownModel, session: InlineDropdownSession | null | undefined, env: PieEnvironment, updateSession?: PieUpdateSession): Promise<{
10
54
  disabled: boolean;
11
- mode: any;
12
- prompt: any;
13
- displayType: any;
14
- markup: any;
15
- choices: {};
16
- feedback: {};
55
+ mode: "gather" | "view" | "evaluate";
56
+ prompt: string | null;
57
+ displayType: string;
58
+ markup: string;
59
+ choices: Record<string, DeliveryChoice[] | undefined>;
60
+ feedback: Record<string, string>;
17
61
  responseCorrect: boolean | undefined;
18
- rationale: any;
19
- teacherInstructions: any;
20
- language: any;
21
- extraCSSRules: any;
62
+ rationale: string | null;
63
+ teacherInstructions: string | null;
64
+ language: string | undefined;
65
+ extraCSSRules: import("@pie-element/shared-types").ExtraCSSRules | undefined;
22
66
  }>;
23
- export declare const getScore: (config: any, session: any) => number;
67
+ export declare const getScore: (config: Partial<Pick<InlineDropdownModel, "choices" | "alternateResponse">>, session: InlineDropdownSession | null | undefined) => number;
24
68
  /**
25
69
  * Generates detailed trace log for scoring evaluation
26
70
  * @param {Object} model - the question model
@@ -28,7 +72,7 @@ export declare const getScore: (config: any, session: any) => number;
28
72
  * @param {Object} env - the environment
29
73
  * @returns {Array} traceLog - array of trace messages
30
74
  */
31
- export declare const getLogTrace: (model: any, session: any, env: any) => string[];
75
+ export declare const getLogTrace: (model: InlineDropdownModel, session: InlineDropdownSession | null | undefined, env: Partial<PieEnvironment>) => string[];
32
76
  /**
33
77
  *
34
78
  * The score is partial by default for checkbox mode, allOrNothing for radio mode.
@@ -41,6 +85,11 @@ export declare const getLogTrace: (model: any, session: any, env: any) => string
41
85
  * @param {boolean} env.partialScoring - is partial scoring enabled (if undefined default to true) This overrides
42
86
  * `model.partialScoring`.
43
87
  */
44
- export declare function outcome(model: any, session: any, env?: {}): Promise<unknown>;
45
- export declare const createCorrectResponseSession: (question: any, env: any) => Promise<unknown>;
46
- export declare const validate: (model?: {}, config?: {}) => {};
88
+ export declare function outcome(model: InlineDropdownModel, session: InlineDropdownSession | null | undefined, env?: Partial<PieEnvironment>): Promise<{
89
+ score: number;
90
+ empty: boolean;
91
+ traceLog: string[];
92
+ }>;
93
+ export declare const createCorrectResponseSession: (question: InlineDropdownModel, env: PieEnvironment) => Promise<InlineDropdownSession | null>;
94
+ export declare const validate: (model?: Partial<InlineDropdownModel>, config?: InlineDropdownConfiguration) => InlineDropdownValidationErrors;
95
+ export {};
@@ -67,7 +67,7 @@ var d = (e, n) => {
67
67
  }, f = (e, n, r) => {
68
68
  let i = [], { value: a = {} } = n || {}, o = t(e), c = Object.keys(o), l = c.length;
69
69
  if (i.push(`${l} dropdown response area(s) defined in this question.`), a && Object.keys(a).length > 0) {
70
- let e = Object.entries(a).filter(([e, t]) => t && t.trim()).length;
70
+ let e = Object.entries(a).filter(([, e]) => e && e.trim()).length;
71
71
  i.push(`Student selected options in ${e} out of ${l} dropdown(s).`), c.forEach((e) => {
72
72
  let t = a && a[e] || "", n = o[e] || [];
73
73
  t.trim() ? i.push(`Dropdown ${parseInt(e) + 1}: student selected '${t}' (correct options: [${n.map((e) => `'${e}'`).join(", ")}]).`) : i.push(`Dropdown ${parseInt(e) + 1}: no selection made (correct options: [${n.map((e) => `'${e}'`).join(", ")}]).`);
@@ -116,8 +116,10 @@ var m = (e, t) => new Promise((n) => {
116
116
  t[n]?.required && !h(e[n]) && (o[n] = "This field is required.");
117
117
  });
118
118
  let s = ((n || "").match(/\{\{(\d+)\}\}/g) || []).length;
119
- return s > i ? o.responseAreasError = `No more than ${i} response areas should be defined.` : s < 1 && (o.responseAreasError = "There should be defined at least 1 response area."), (Object.keys(r) || []).forEach((e) => {
120
- r[e] && r[e].length > a && (o.responseAreaChoicesError = `No more than ${a} choices per response area should be defined.`);
119
+ i !== void 0 && s > i ? o.responseAreasError = `No more than ${i} response areas should be defined.` : s < 1 && (o.responseAreasError = "There should be defined at least 1 response area.");
120
+ let c = r;
121
+ return (Object.keys(c) || []).forEach((e) => {
122
+ c[e] && a !== void 0 && c[e].length > a && (o.responseAreaChoicesError = `No more than ${a} choices per response area should be defined.`);
121
123
  }), o;
122
124
  };
123
125
  //#endregion
@@ -1,4 +1,2 @@
1
- export declare const getAllCorrectResponses: ({ choices, alternateResponse }: {
2
- choices: any;
3
- alternateResponse: any;
4
- }) => {};
1
+ import type { InlineDropdownModel } from '../types.js';
2
+ export declare const getAllCorrectResponses: ({ choices, alternateResponse, }: Partial<Pick<InlineDropdownModel, "choices" | "alternateResponse">>) => Record<string, string[]>;
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { default } from './delivery/index.js';
2
+ export type * from './types.js';