@pie-element/mc-populated-blank 0.3.0-next.15 → 0.3.0-next.17
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.
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ Notes:
|
|
|
55
55
|
- **`choices`**: `{ id, labelHtml? }` or `{ id, imageUrl, imageAlt }` per mode
|
|
56
56
|
- **`correctChoiceId`**
|
|
57
57
|
- **`hasAudio`**, **`audioUrl`**, **`audioTranscript`** (`audioUrl` required when `hasAudio=true`)
|
|
58
|
-
- **`autoplayAudioEnabled`**, **`completeAudioEnabled`** (optional integration flags)
|
|
58
|
+
- **`autoplayAudioEnabled`**, **`completeAudioEnabled`** (optional integration flags). `completeAudioEnabled` keeps the item incomplete until the audio has played to the end, whether or not autoplay is on.
|
|
59
59
|
- **`layoutLimits`** (optional): numeric visual constraints; defaults are based on current CQT parity behavior and can be overridden per item
|
|
60
60
|
- **`layoutProfilePresets`** (optional): named preset map by `layoutProfile`; use profile as a template and override with `layoutLimits`
|
|
61
61
|
- **`audioButtonSkin`** / **`audioButtonSkinsByLocale`** (optional): override listen-button skin URLs
|
|
@@ -89,7 +89,7 @@ function a(e, t) {
|
|
|
89
89
|
//#region src/delivery/index.ts
|
|
90
90
|
var o = a(e, { isComplete: (e, t) => !!t?.choiceId });
|
|
91
91
|
function s(e) {
|
|
92
|
-
return !!e?.
|
|
92
|
+
return !!e?.completeAudioEnabled && !!e?.hasAudio;
|
|
93
93
|
}
|
|
94
94
|
var c = class extends o {
|
|
95
95
|
audioComplete = !1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["#e","t","#t","e","n","#writeAudioTiming"],"sources":["../../../../../lib-svelte/delivery-events/dist/index2.js","../../../../../shared/player-events/dist/index.js","../../../../../lib-svelte/delivery-events/dist/index3.js","../../../src/delivery/index.ts"],"sourcesContent":["//#region src/write-session-in-place.ts\nfunction e(e) {\n\treturn !!e && typeof e == \"object\" && !Array.isArray(e);\n}\nfunction t(t, n) {\n\tif (t === n) return t;\n\tif (!e(t) || !e(n) || Object.isFrozen(t) || !Object.isExtensible(t)) return n;\n\ttry {\n\t\tfor (let e of Object.keys(t)) e in n || delete t[e];\n\t\tObject.assign(t, n);\n\t} catch {\n\t\treturn n;\n\t}\n\treturn t;\n}\n//#endregion\nexport { t as writeSessionInPlace };\n","//#region src/session-notifier.ts\nvar e = \"commitPendingSession\", t = /* @__PURE__ */ new WeakMap();\nfunction n(e, n) {\n\tlet r = t.get(e);\n\tr || (r = /* @__PURE__ */ new Set(), t.set(e, r)), r.add(n);\n}\nfunction r(t) {\n\treturn Object.getOwnPropertyDescriptor(t, e) !== void 0;\n}\nfunction i(t) {\n\tif (r(t)) return;\n\tlet n = t[e];\n\tObject.defineProperty(t, e, {\n\t\tvalue: () => {\n\t\t\tif (typeof n == \"function\") try {\n\t\t\t\tn.call(t);\n\t\t\t} catch {}\n\t\t\to(t);\n\t\t},\n\t\tconfigurable: !0,\n\t\tenumerable: !1,\n\t\twritable: !0\n\t});\n}\nfunction a(e, t, r = {}) {\n\tlet a = r.delayMs, o = typeof a == \"function\" ? a : () => a ?? 0, s = r.maxWaitMs, c = null, l = null, u = !1, d = () => {\n\t\tc !== null && (clearTimeout(c), c = null), l !== null && (clearTimeout(l), l = null);\n\t}, f = () => {\n\t\td(), u && (u = !1, t());\n\t}, p = {\n\t\tnotify() {\n\t\t\tu = !0, c !== null && clearTimeout(c), c = setTimeout(f, Math.max(0, o())), s !== void 0 && l === null && (l = setTimeout(f, Math.max(0, s)));\n\t\t},\n\t\tflush() {\n\t\t\tif (!u) {\n\t\t\t\td();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tf();\n\t\t\t} catch (e) {\n\t\t\t\tconsole.warn(\"[session-notifier] a committed session-changed dispatch threw\", e);\n\t\t\t}\n\t\t}\n\t};\n\treturn n(e, p), i(e), p;\n}\nfunction o(e) {\n\tlet n = t.get(e);\n\tif (n) for (let e of [...n]) e.flush();\n}\n//#endregion\n//#region src/index.ts\nvar s = class e extends CustomEvent {\n\tstatic {\n\t\tthis.TYPE = \"model-set\";\n\t}\n\tconstructor(t, n, r) {\n\t\tsuper(e.TYPE, {\n\t\t\tbubbles: !0,\n\t\t\tcomposed: !0,\n\t\t\tdetail: {\n\t\t\t\tcomplete: n,\n\t\t\t\tcomponent: t,\n\t\t\t\thasModel: r\n\t\t\t}\n\t\t}), this.component = t, this.complete = n;\n\t}\n}, c = class e extends CustomEvent {\n\tstatic {\n\t\tthis.TYPE = \"session-changed\";\n\t}\n\tconstructor(t, n) {\n\t\tsuper(e.TYPE, {\n\t\t\tbubbles: !0,\n\t\t\tcomposed: !0,\n\t\t\tdetail: {\n\t\t\t\tcomplete: n,\n\t\t\t\tcomponent: t\n\t\t\t}\n\t\t}), this.component = t, this.complete = n;\n\t}\n};\n//#endregion\nexport { s as ModelSetEvent, e as SESSION_COMMIT_METHOD, c as SessionChangedEvent, a as createSessionNotifier, o as flushSessionNotifiers };\n","import { writeSessionInPlace as e } from \"./index2.js\";\nimport { ModelSetEvent as t, SessionChangedEvent as n } from \"@pie-element/shared-player-events\";\n//#region src/delivery-element.ts\nfunction r(r, i) {\n\tlet a = r.element;\n\tif (!a) throw TypeError(\"defineDeliveryElement: the component was not compiled with `customElement`\");\n\tclass o extends a {\n\t\t#e;\n\t\t#t;\n\t\tconstructor() {\n\t\t\tsuper(), this.onSessionChange = (e) => {\n\t\t\t\tthis.writeSession(e), this.dispatchSessionChanged();\n\t\t\t};\n\t\t}\n\t\tset model(e) {\n\t\t\tthis.#e = e, super.model = e, queueMicrotask(() => {\n\t\t\t\tthis.dispatchEvent(new t(this.tagName.toLowerCase(), this.isComplete(), this.#e !== void 0));\n\t\t\t});\n\t\t}\n\t\tget model() {\n\t\t\treturn this.#e;\n\t\t}\n\t\tset session(e) {\n\t\t\tthis.#t = e, super.session = e, this.dispatchSessionChanged();\n\t\t}\n\t\tget session() {\n\t\t\treturn this.#t;\n\t\t}\n\t\tisComplete() {\n\t\t\treturn i.isComplete(this.#e, this.#t);\n\t\t}\n\t\twriteSession(t) {\n\t\t\tthis.#t = e(this.#t, t), super.session = t;\n\t\t}\n\t\tdispatchSessionChanged() {\n\t\t\tthis.dispatchEvent(new n(this.tagName.toLowerCase(), this.isComplete()));\n\t\t}\n\t}\n\treturn o;\n}\n//#endregion\nexport { r as defineDeliveryElement };\n","import McPopulatedBlankComponent from './McPopulatedBlank.svelte';\nimport { defineDeliveryElement } from '@pie-lib/delivery-events-svelte';\nimport type { McpbQuestion, McpbSession } from '../shared/types.js';\n\nconst DeliveryElement = defineDeliveryElement<McpbQuestion, McpbSession>(\n McPopulatedBlankComponent,\n { isComplete: (_model, session) => !!session?.choiceId }\n);\n\n
|
|
1
|
+
{"version":3,"file":"index.js","names":["#e","t","#t","e","n","#writeAudioTiming"],"sources":["../../../../../lib-svelte/delivery-events/dist/index2.js","../../../../../shared/player-events/dist/index.js","../../../../../lib-svelte/delivery-events/dist/index3.js","../../../src/delivery/index.ts"],"sourcesContent":["//#region src/write-session-in-place.ts\nfunction e(e) {\n\treturn !!e && typeof e == \"object\" && !Array.isArray(e);\n}\nfunction t(t, n) {\n\tif (t === n) return t;\n\tif (!e(t) || !e(n) || Object.isFrozen(t) || !Object.isExtensible(t)) return n;\n\ttry {\n\t\tfor (let e of Object.keys(t)) e in n || delete t[e];\n\t\tObject.assign(t, n);\n\t} catch {\n\t\treturn n;\n\t}\n\treturn t;\n}\n//#endregion\nexport { t as writeSessionInPlace };\n","//#region src/session-notifier.ts\nvar e = \"commitPendingSession\", t = /* @__PURE__ */ new WeakMap();\nfunction n(e, n) {\n\tlet r = t.get(e);\n\tr || (r = /* @__PURE__ */ new Set(), t.set(e, r)), r.add(n);\n}\nfunction r(t) {\n\treturn Object.getOwnPropertyDescriptor(t, e) !== void 0;\n}\nfunction i(t) {\n\tif (r(t)) return;\n\tlet n = t[e];\n\tObject.defineProperty(t, e, {\n\t\tvalue: () => {\n\t\t\tif (typeof n == \"function\") try {\n\t\t\t\tn.call(t);\n\t\t\t} catch {}\n\t\t\to(t);\n\t\t},\n\t\tconfigurable: !0,\n\t\tenumerable: !1,\n\t\twritable: !0\n\t});\n}\nfunction a(e, t, r = {}) {\n\tlet a = r.delayMs, o = typeof a == \"function\" ? a : () => a ?? 0, s = r.maxWaitMs, c = null, l = null, u = !1, d = () => {\n\t\tc !== null && (clearTimeout(c), c = null), l !== null && (clearTimeout(l), l = null);\n\t}, f = () => {\n\t\td(), u && (u = !1, t());\n\t}, p = {\n\t\tnotify() {\n\t\t\tu = !0, c !== null && clearTimeout(c), c = setTimeout(f, Math.max(0, o())), s !== void 0 && l === null && (l = setTimeout(f, Math.max(0, s)));\n\t\t},\n\t\tflush() {\n\t\t\tif (!u) {\n\t\t\t\td();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tf();\n\t\t\t} catch (e) {\n\t\t\t\tconsole.warn(\"[session-notifier] a committed session-changed dispatch threw\", e);\n\t\t\t}\n\t\t}\n\t};\n\treturn n(e, p), i(e), p;\n}\nfunction o(e) {\n\tlet n = t.get(e);\n\tif (n) for (let e of [...n]) e.flush();\n}\n//#endregion\n//#region src/index.ts\nvar s = class e extends CustomEvent {\n\tstatic {\n\t\tthis.TYPE = \"model-set\";\n\t}\n\tconstructor(t, n, r) {\n\t\tsuper(e.TYPE, {\n\t\t\tbubbles: !0,\n\t\t\tcomposed: !0,\n\t\t\tdetail: {\n\t\t\t\tcomplete: n,\n\t\t\t\tcomponent: t,\n\t\t\t\thasModel: r\n\t\t\t}\n\t\t}), this.component = t, this.complete = n;\n\t}\n}, c = class e extends CustomEvent {\n\tstatic {\n\t\tthis.TYPE = \"session-changed\";\n\t}\n\tconstructor(t, n) {\n\t\tsuper(e.TYPE, {\n\t\t\tbubbles: !0,\n\t\t\tcomposed: !0,\n\t\t\tdetail: {\n\t\t\t\tcomplete: n,\n\t\t\t\tcomponent: t\n\t\t\t}\n\t\t}), this.component = t, this.complete = n;\n\t}\n};\n//#endregion\nexport { s as ModelSetEvent, e as SESSION_COMMIT_METHOD, c as SessionChangedEvent, a as createSessionNotifier, o as flushSessionNotifiers };\n","import { writeSessionInPlace as e } from \"./index2.js\";\nimport { ModelSetEvent as t, SessionChangedEvent as n } from \"@pie-element/shared-player-events\";\n//#region src/delivery-element.ts\nfunction r(r, i) {\n\tlet a = r.element;\n\tif (!a) throw TypeError(\"defineDeliveryElement: the component was not compiled with `customElement`\");\n\tclass o extends a {\n\t\t#e;\n\t\t#t;\n\t\tconstructor() {\n\t\t\tsuper(), this.onSessionChange = (e) => {\n\t\t\t\tthis.writeSession(e), this.dispatchSessionChanged();\n\t\t\t};\n\t\t}\n\t\tset model(e) {\n\t\t\tthis.#e = e, super.model = e, queueMicrotask(() => {\n\t\t\t\tthis.dispatchEvent(new t(this.tagName.toLowerCase(), this.isComplete(), this.#e !== void 0));\n\t\t\t});\n\t\t}\n\t\tget model() {\n\t\t\treturn this.#e;\n\t\t}\n\t\tset session(e) {\n\t\t\tthis.#t = e, super.session = e, this.dispatchSessionChanged();\n\t\t}\n\t\tget session() {\n\t\t\treturn this.#t;\n\t\t}\n\t\tisComplete() {\n\t\t\treturn i.isComplete(this.#e, this.#t);\n\t\t}\n\t\twriteSession(t) {\n\t\t\tthis.#t = e(this.#t, t), super.session = t;\n\t\t}\n\t\tdispatchSessionChanged() {\n\t\t\tthis.dispatchEvent(new n(this.tagName.toLowerCase(), this.isComplete()));\n\t\t}\n\t}\n\treturn o;\n}\n//#endregion\nexport { r as defineDeliveryElement };\n","import McPopulatedBlankComponent from './McPopulatedBlank.svelte';\nimport { defineDeliveryElement } from '@pie-lib/delivery-events-svelte';\nimport type { McpbQuestion, McpbSession } from '../shared/types.js';\n\nconst DeliveryElement = defineDeliveryElement<McpbQuestion, McpbSession>(\n McPopulatedBlankComponent,\n { isComplete: (_model, session) => !!session?.choiceId }\n);\n\n/**\n * Audio the learner must hear to the end before a pick counts as complete,\n * whether autoplay or the learner started it.\n */\nfunction requiresAudioCompletion(model: McpbQuestion | undefined): boolean {\n return !!model?.completeAudioEnabled && !!model?.hasAudio;\n}\n\nclass McPopulatedBlankElement extends DeliveryElement {\n audioComplete = false;\n declare onAudioStarted: () => void;\n declare onAudioEnded: () => void;\n\n constructor() {\n super();\n this.onAudioStarted = () => {\n this.#writeAudioTiming({ audioStartTime: Date.now() });\n };\n this.onAudioEnded = () => {\n this.audioComplete = true;\n this.#writeAudioTiming({ audioEndTime: Date.now() });\n this.dispatchSessionChanged();\n };\n }\n\n set model(m: McpbQuestion | undefined) {\n // Autoplay re-fires only for a new `audioUrl`, so a re-set of the same\n // model must keep a finished playback counted.\n if (m?.audioUrl !== this.model?.audioUrl) this.audioComplete = false;\n super.model = m;\n }\n\n get model(): McpbQuestion | undefined {\n return super.model;\n }\n\n isComplete(): boolean {\n return super.isComplete() && (this.audioComplete || !requiresAudioCompletion(this.model));\n }\n\n /**\n * The first playback's timing, as multiple-choice's `updateSessionMetadata`\n * records it: a replay does not move either timestamp, and `waitTime` is set\n * once both exist. It reaches the component too, which builds the learner's\n * next pick from the session it renders.\n */\n #writeAudioTiming(timing: { audioStartTime?: number; audioEndTime?: number }) {\n const session: McpbSession = this.session || {};\n const audioStartTime = session.audioStartTime || timing.audioStartTime;\n const audioEndTime = session.audioEndTime || timing.audioEndTime;\n const next: McpbSession = {\n ...session,\n ...(audioStartTime ? { audioStartTime } : {}),\n ...(audioEndTime ? { audioEndTime } : {}),\n };\n if (!next.waitTime && audioStartTime && audioEndTime) {\n next.waitTime = audioEndTime - audioStartTime;\n }\n this.writeSession(next);\n }\n}\n\nexport default McPopulatedBlankElement;\n"],"mappings":"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"}
|
package/dist/delivery/index.js
CHANGED
|
@@ -9228,9 +9228,12 @@ function r(r, i) {
|
|
|
9228
9228
|
//#endregion
|
|
9229
9229
|
//#region src/delivery/index.ts
|
|
9230
9230
|
var DeliveryElement = r(McPopulatedBlank, { isComplete: (_model, session) => !!session?.choiceId });
|
|
9231
|
-
/**
|
|
9231
|
+
/**
|
|
9232
|
+
* Audio the learner must hear to the end before a pick counts as complete,
|
|
9233
|
+
* whether autoplay or the learner started it.
|
|
9234
|
+
*/
|
|
9232
9235
|
function requiresAudioCompletion(model) {
|
|
9233
|
-
return !!model?.
|
|
9236
|
+
return !!model?.completeAudioEnabled && !!model?.hasAudio;
|
|
9234
9237
|
}
|
|
9235
9238
|
var _McPopulatedBlankElement_brand = /* @__PURE__ */ new WeakSet();
|
|
9236
9239
|
var McPopulatedBlankElement = class extends DeliveryElement {
|