@pie-element/mc-populated-blank 0.3.0-next.9 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +51 -21
  2. package/author.js +2 -0
  3. package/dist/author/defaults.d.ts +73 -0
  4. package/dist/author/index.d.ts +2 -10
  5. package/dist/author/index.js +139 -165
  6. package/dist/author/index.js.map +1 -1
  7. package/dist/browser/McPopulatedBlank-LqV-pdXv.js +2541 -0
  8. package/dist/browser/McPopulatedBlank-LqV-pdXv.js.map +1 -0
  9. package/dist/browser/author/index.js +11 -32
  10. package/dist/browser/author/index.js.map +1 -1
  11. package/dist/browser/{client-BmZWrsT3.js → client-Dfdyltec.js} +655 -643
  12. package/dist/browser/client-Dfdyltec.js.map +1 -0
  13. package/dist/browser/controller/index.js +2 -220
  14. package/dist/browser/controller-DSkEI2th.js +222 -0
  15. package/dist/browser/controller-DSkEI2th.js.map +1 -0
  16. package/dist/browser/delivery/index.js +72 -1024
  17. package/dist/browser/delivery/index.js.map +1 -1
  18. package/dist/browser/{layoutLimits-Bp17YP2V.js → layoutLimits-C2D60jW0.js} +1 -2
  19. package/dist/browser/layoutLimits-C2D60jW0.js.map +1 -0
  20. package/dist/browser/print/index.js +94 -103
  21. package/dist/browser/print/index.js.map +1 -1
  22. package/dist/controller/defaults.d.ts +8 -30
  23. package/dist/controller/index.d.ts +80 -65
  24. package/dist/controller/index.js +142 -115
  25. package/dist/controller/index.js.map +1 -1
  26. package/dist/delivery/assets/audioButtonSkinAssets.d.ts +4 -0
  27. package/dist/delivery/computeDisplayState.d.ts +12 -7
  28. package/dist/delivery/computeLayoutProfile.d.ts +8 -0
  29. package/dist/delivery/computeLayoutStyle.d.ts +1 -1
  30. package/dist/delivery/i18n.d.ts +8 -0
  31. package/dist/delivery/index.d.ts +8 -23
  32. package/dist/delivery/index.js +3233 -752
  33. package/dist/delivery/index.js.map +1 -1
  34. package/dist/delivery/variant-css-map.d.ts +15 -2
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.iife.d.ts +1 -154
  37. package/dist/index.iife.js +414 -163
  38. package/dist/index.js +2 -6847
  39. package/dist/print/index.d.ts +3 -7
  40. package/dist/print/index.js +4667 -349
  41. package/dist/print/index.js.map +1 -1
  42. package/dist/print/preparePrint.d.ts +15 -0
  43. package/dist/runtime-support.js +5 -5
  44. package/dist/runtime-support.js.map +1 -1
  45. package/dist/shared/layoutLimits.d.ts +0 -1
  46. package/dist/shared/types.d.ts +14 -20
  47. package/module/print.js +3781 -918
  48. package/module/print.js.map +1 -1
  49. package/package.json +14 -4
  50. package/dist/browser/client-BmZWrsT3.js.map +0 -1
  51. package/dist/browser/controller/index.js.map +0 -1
  52. package/dist/browser/layoutLimits-Bp17YP2V.js.map +0 -1
  53. package/dist/index.js.map +0 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Svelte 5 PIE element where the learner picks a **multiple-choice** option and that choice **fills a blank** in a sentence/template.
4
4
 
5
- This element is the PIE counterpart for Star Learnosity CQT "populated blank" interactions. The CQT family had several published `custom_type` flavors, but they are all variants of the same base interaction:
5
+ This element is the PIE counterpart for Star CQT "populated blank" interactions. The CQT family had several published `custom_type` flavors, but they are all variants of the same base interaction:
6
6
 
7
7
  - one selected choice
8
8
  - one correctness key
@@ -11,7 +11,7 @@ This element is the PIE counterpart for Star Learnosity CQT "populated blank" in
11
11
 
12
12
  ## What the original CQT flavors mean
13
13
 
14
- The historical Learnosity CQT names mostly describe layout/stimulus differences, not different scoring logic:
14
+ The historical CQT names mostly describe layout/stimulus differences, not different scoring logic:
15
15
 
16
16
  - `sel_vic`: sentence-style vocabulary in context, with audio/transcript support
17
17
  - `sr-vic`: sentence-style vocabulary in context, typically no audio button
@@ -26,9 +26,9 @@ The shared behavior across these flavors is now represented by one element with
26
26
 
27
27
  ## Flavor to model mapping (quick defaults)
28
28
 
29
- Use this as a practical starting point when mapping Learnosity CQT payloads into `mc-populated-blank` models.
29
+ Use this as a practical starting point when mapping CQT payloads into `mc-populated-blank` models.
30
30
 
31
- | Learnosity `custom_type` | Typical layout meaning | Suggested `interactionMode` | Suggested `choiceMode` | Template hint |
31
+ | CQT `custom_type` | Typical layout meaning | Suggested `interactionMode` | Suggested `choiceMode` | Template hint |
32
32
  | --- | --- | --- | --- | --- |
33
33
  | `sel_vic` | sentence cloze with audio/transcript | `populate_blank` | `text` | `<p>{before} {{blank}} {after}</p>` |
34
34
  | `sr-vic` | sentence cloze without listen button | `populate_blank` | `text` | `<p>{before} {{blank}} {after}</p>` |
@@ -43,9 +43,39 @@ Notes:
43
43
 
44
44
  - `choiceMode` should be `image` only when distractors are image choices; otherwise use `text`.
45
45
  - Current model contract is single-blank for `populate_blank`; dual-cloze source shapes are normalized to one `{{blank}}`.
46
- - `correctChoiceId` should always map from Learnosity `valid_response.name` to canonical `distractor_n`.
46
+ - `correctChoiceId` should always map from the CQT's `valid_response.name` to canonical `distractor_n`.
47
47
  - Layout defaults are tuned from original CQT visual baselines, but they are not fixed: override through `model.layoutLimits` when host/theme requirements differ.
48
48
 
49
+ ## Layouts
50
+
51
+ `layoutProfile` selects the arrangement and lands on the root as `layout-<layoutProfile>`; the variant sheet for `customType` tunes sizes on top of it (see [Bundled CQT variant CSS](#bundled-cqt-variant-css)). `choiceLayout` sets the choice direction; unset, choices are horizontal when the template is only `{{blank}}` or `interactionMode` is `audio_mc_only`, and vertical otherwise. `audio_blank_only`, `stimulus_image_blank` and `token_sequence` replace the native audio controls with the listen button; `useFeatureButtonAudio` overrides that either way.
52
+
53
+ | `layoutProfile` | Arrangement | `customType` in the samples |
54
+ | --- | --- | --- |
55
+ | unset | block flow in DOM order | — |
56
+ | `inline_sentence` | block flow; a two-column grid when `hasAudio` | `sr-vic`, `sel_vic` |
57
+ | `audio_blank_only` | centred block flow around a large blank | `sel_r1-_plusggg`, `sel_r1-_gplusggg` |
58
+ | `token_sequence` | grid: listen row, then a row of token boxes | `sel_r1-g_plusggg`, `sel_r1-gg_plusggg`, `sel_r1-_ggplusggg` |
59
+ | `stimulus_image_blank` | grid: stimulus, blank and listen button in one row | `sel_r1-s3_plusggg` |
60
+
61
+ The figures are wireframes: colour marks a region, a dashed region renders only when its content is present, and a labelled size is what renders without a `layoutLimits` override.
62
+
63
+ ![Default block flow: header, audio, sentence, template and choices stacked in DOM order](docs/layouts/layout-default-flow.png)
64
+
65
+ ![inline_sentence with audio: the template and the listen button share a grid row above the choices](docs/layouts/layout-inline-sentence-audio.png)
66
+
67
+ ![audio_blank_only: listen button at the end of its row, a centred 10rem blank, then a centred row of choice tiles](docs/layouts/layout-audio-blank-only.png)
68
+
69
+ ![token_sequence: listen button on its own row, a centred row of 150px token boxes including the blank, then choice tiles](docs/layouts/layout-token-sequence.png)
70
+
71
+ ![stimulus_image_blank with the sel_r1-s3 sheet: stimulus, blank and listen button in one row above centred choice tiles](docs/layouts/layout-stimulus-image-blank.png)
72
+
73
+ ![audio_mc_only: header, audio and horizontal choices, with no template line](docs/layouts/layout-audio-mc-only.png)
74
+
75
+ ![Choice rows: the inline row used by vertical choices and the tile used by horizontal choices, with their evaluate states](docs/layouts/choice-rows.png)
76
+
77
+ ![Below 760px: the listen button moves to the start and the choice tiles stack in a column](docs/layouts/layout-narrow.png)
78
+
49
79
  ## Authoring model
50
80
 
51
81
  - **`prompt`** (optional) and **`promptEnabled`**
@@ -55,12 +85,15 @@ Notes:
55
85
  - **`choices`**: `{ id, labelHtml? }` or `{ id, imageUrl, imageAlt }` per mode
56
86
  - **`correctChoiceId`**
57
87
  - **`hasAudio`**, **`audioUrl`**, **`audioTranscript`** (`audioUrl` required when `hasAudio=true`)
58
- - **`autoplayAudioEnabled`**, **`completeAudioEnabled`** (optional integration flags)
88
+ - **`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
89
  - **`layoutLimits`** (optional): numeric visual constraints; defaults are based on current CQT parity behavior and can be overridden per item
60
90
  - **`layoutProfilePresets`** (optional): named preset map by `layoutProfile`; use profile as a template and override with `layoutLimits`
61
91
  - **`audioButtonSkin`** / **`audioButtonSkinsByLocale`** (optional): override listen-button skin URLs
62
- - **`uiText`** (optional): override labels/messages (show/hide correct, answer choices, autoplay prompt, transcript label, missing-audio message)
92
+ - **`language`** (optional): the language of the learner-facing strings (`en_US`, `es_ES`, …), which come from `@pie-lib/translator` as in the React elements; `locale` stands in when it is unset
63
93
  - **`choiceGroupLabel`** (optional): accessibility label used when no visible prompt is present
94
+ - **`lockChoiceOrder`** (optional): `false` shuffles the choices, as in multiple-choice, and an instructor sees the order the student saw; `shuffle: true` is the older spelling and counts only when `lockChoiceOrder` is unset
95
+ - **`teacherInstructions`** and **`teacherInstructionsEnabled`** (optional): shown to instructors in view and evaluate mode, and in an instructor's printout; unset `teacherInstructionsEnabled` shows them
96
+ - **`printAnswerKey`** (optional): `false` leaves the answer key out of an instructor's printout; a student's printout never has it
64
97
 
65
98
  ### `layoutLimits` keys (all optional, positive numbers)
66
99
 
@@ -85,7 +118,6 @@ Notes:
85
118
  - `audioBlankTemplateMarginTopRem`
86
119
  - `audioBlankTemplateMarginBottomRem`
87
120
  - `audioInstructionsMaxWidthPx`
88
- - `narrowHorizontalChoiceMaxWidthPx`
89
121
  - `stimulusGridColumnGapRem`
90
122
  - `stimulusGridRowGapRem`
91
123
  - `stimulusSentenceMarginTopRem`
@@ -110,19 +142,20 @@ Notes:
110
142
  - **Choice normalization:** choices are polymorphic by `choiceMode` (text via `labelHtml`, image via `imageUrl`/`imageAlt`).
111
143
  - **Delivery rendering:** template is split around `{{blank}}`; selected choice content is rendered into the blank slot.
112
144
  - **Layout limits are model-driven:** delivery reads `model.layoutLimits` (blank widths/underline widths, choice tile sizing, image max heights, listen button size, layout column minimums); defaults are CQT-informed but overrideable.
113
- - **Responsive parity controls:** `audioInstructionsMaxWidthPx` and `narrowHorizontalChoiceMaxWidthPx` are explicitly configurable to tune desktop vs narrow-width CQT behavior.
145
+ - **Responsive parity control:** `audioInstructionsMaxWidthPx` is configurable to tune desktop vs narrow-width CQT behavior.
114
146
  - **Evaluate mode behavior:** when evaluate/correct-answer mode is enabled, delivery can render `correctChoiceId` in the blank/choice state.
115
- - **Audio error behavior:** no TTS fallback is used; when `hasAudio=true` and no playable `audioUrl` is provided, delivery shows an explicit error message (configurable via `uiText.audioResourceUnavailable`).
147
+ - **Audio error behavior:** no TTS fallback is used; when `hasAudio=true` and no playable `audioUrl` is provided, delivery shows an explicit error message.
116
148
  - **Prompt-off accessibility:** when `prompt` is empty, delivery uses `choiceGroupLabel` (or fallback UI text) as the radiogroup accessible name.
117
- - **Print parity:** print view mirrors prompt/template/choice presentation with the same blank-token contract.
118
- - **Delivery renders no transcript:** it is an accessibility-catalog alternate, so on `pie-section-player` the assessment toolkit resolves the `transcript` card against the learner's personal needs profile and renders it in a labelled region above this element (PIE-902) — the same path signing takes. `model.audioTranscript` stays on the model for the print view, which has no toolkit, and as the source the Learnosity import writes the card from. A host that wants a transcript delivers the toolkit; there is no element-specific CSS class to apply.
149
+ - **Print parity:** print renders the delivery component as a player shows the printout's `role` in `view` mode, with the choices in authored order; an instructor's key is the correct-response session, filling the blank and checking the key's choice. Teacher instructions print expanded, and audio prints as its URL and transcript in place of a player.
150
+ - **Delivery renders no transcript:** it is an accessibility-catalog alternate, so on `pie-section-player` the assessment toolkit resolves the `transcript` card against the learner's personal needs profile and renders it in a labelled region above this element (PIE-902) — the same path signing takes. `model.audioTranscript` stays on the model for the print view, which has no toolkit, and as the source the pie-api-aws import writes the card from. A host that wants a transcript delivers the toolkit; there is no element-specific CSS class to apply.
119
151
 
120
152
  ## Theming hooks (`pie-*` classes)
121
153
 
122
154
  Delivery now exposes stable `pie-*` classes so hosts can theme this element with the same class-oriented approach used by other PIE elements.
123
155
 
124
156
  - Root/container: `pie-element`, `pie-element-mc-populated-blank`, `pie-delivery-root`
125
- - Prompt/audio/template: `pie-prompt`, `pie-audio-container`, `pie-audio-player`, `pie-audio-transcript`, `pie-template-line`, `pie-sentence-line`
157
+ - Header, holding teacher instructions, the prompt and the show-correct-answer toggle ahead of the stem: `pie-header`
158
+ - Prompt/audio/template: `pie-prompt`, `pie-audio-container`, `pie-audio-player`, `pie-template-line`, `pie-sentence-line`
126
159
  - Blank display: `pie-blank-slot`, `pie-blank-slot-standalone`, `pie-blank-value`, `pie-blank-image`
127
160
  - Choice group: `pie-choices-fieldset`, `pie-choices-legend`, `pie-choices`
128
161
  - Choice rows/items: `pie-choice`, `pie-choice-horizontal`, `pie-choice-selected`, `pie-choice-label`, `pie-choice-image`
@@ -131,25 +164,22 @@ Delivery now exposes stable `pie-*` classes so hosts can theme this element with
131
164
 
132
165
  ## Bundled CQT variant CSS
133
166
 
134
- To avoid runtime dependency on cross-origin Learnosity stylesheet loading, this element bundles variant-specific CSS in delivery:
167
+ This element bundles variant-specific CSS in delivery, so it loads no stylesheet at runtime:
135
168
 
136
169
  - Variant CSS files: `src/delivery/cqt-css/*.css`
137
170
  - Variant mapping: `src/delivery/variant-css-map.ts`
138
171
  - Applied by `model.customType` (for example `sel_r1-_plusggg`)
139
172
 
140
- Each variant CSS file is intentionally scoped with `.mc-populated-blank-root.variant-*` selectors so styles only apply to this element instance and do not leak into other PIE elements.
173
+ Every selector in a variant CSS file starts at `.mc-populated-blank-root` (`variant-css-scope.test.ts` enforces it), so the styles cannot leak into other PIE elements. At injection each root selector is narrowed to roots whose `data-mpb-css` carries a hash of this build's sheets, so two versions of the element on one page style only their own instances. The sheets go into the document head, or into the shadow root the element renders in.
141
174
 
142
175
  ### Maintenance workflow
143
176
 
144
- 1. Fetch the latest Learnosity `question.css` for each supported CQT variant.
145
- 2. Update the matching file under `src/delivery/cqt-css/`.
146
- 3. Keep the source URL comment at the top of each CSS file current.
147
- 4. If a new `custom_type` is introduced, add it in `src/delivery/variant-css-map.ts` with:
177
+ 1. Edit the variant's file under `src/delivery/cqt-css/`.
178
+ 2. If a new `custom_type` is introduced, add it in `src/delivery/variant-css-map.ts` with:
148
179
  - `variantId`
149
180
  - `variantClass`
150
- - `sourceUrl`
151
181
  - imported `cssText`
152
- 5. Run `bun run build` in this package and validate the demo variants.
182
+ 3. Run `bun run build` in this package and validate the demo variants.
153
183
 
154
184
  ## Builds
155
185
 
package/author.js ADDED
@@ -0,0 +1,2 @@
1
+ export { default } from './dist/author/index.js';
2
+ export * from './dist/author/index.js';
@@ -0,0 +1,73 @@
1
+ /** The model a new item starts from: a valid question an author edits in place. */
2
+ declare const _default: {
3
+ model: {
4
+ prompt: string;
5
+ template: string;
6
+ choices: {
7
+ id: string;
8
+ labelHtml: string;
9
+ }[];
10
+ correctChoiceId: string;
11
+ promptEnabled: boolean;
12
+ interactionMode: "populate_blank";
13
+ layoutProfile: string;
14
+ choiceLayout: string;
15
+ layoutProfilePresets: {};
16
+ layoutLimits: {
17
+ blankStandaloneWidthRem: number;
18
+ blankWideWidthRem: number;
19
+ blankUnderlineWidthPx: number;
20
+ blankUnderlineWideWidthPx: number;
21
+ horizontalChoiceWidthPx: number;
22
+ horizontalChoiceWidthVw: number;
23
+ horizontalChoiceTileMinHeightRem: number;
24
+ horizontalChoiceContentMinHeightRem: number;
25
+ choiceImageMaxHeightRem: number;
26
+ choiceImageMaxWidthRem: number;
27
+ listenButtonSizePx: number;
28
+ stimulusMinColumnPx: number;
29
+ textMinColumnPx: number;
30
+ legendMaxChars: number;
31
+ choiceGroupGapRem: number;
32
+ choiceRowGapRem: number;
33
+ toggleButtonGapRem: number;
34
+ horizontalChoiceRadioTopMarginRem: number;
35
+ audioBlankTemplateMarginTopRem: number;
36
+ audioBlankTemplateMarginBottomRem: number;
37
+ audioInstructionsMaxWidthPx: number;
38
+ stimulusGridColumnGapRem: number;
39
+ stimulusGridRowGapRem: number;
40
+ stimulusSentenceMarginTopRem: number;
41
+ stimulusChoicesMarginTopRem: number;
42
+ tokenGridColumnGapRem: number;
43
+ tokenGridRowGapRem: number;
44
+ tokenTemplateMarginTopRem: number;
45
+ tokenInlineTokenGapRem: number;
46
+ tokenChoicesMarginTopRem: number;
47
+ inlineGridColumnGapRem: number;
48
+ inlineGridRowGapRem: number;
49
+ inlineTemplateMarginTopRem: number;
50
+ inlineChoicesMarginTopRem: number;
51
+ };
52
+ audioButtonSkin: null;
53
+ audioButtonSkinsByLocale: {};
54
+ sentenceHtml: string;
55
+ choiceMode: "text";
56
+ choiceGroupLabel: string;
57
+ hasAudio: boolean;
58
+ autoplayAudioEnabled: boolean;
59
+ completeAudioEnabled: boolean;
60
+ audioUrl: string;
61
+ audioTranscript: string;
62
+ locale: string;
63
+ teacherInstructions: string;
64
+ teacherInstructionsEnabled: boolean;
65
+ };
66
+ configuration: {
67
+ prompt: {
68
+ label: string;
69
+ settings: boolean;
70
+ };
71
+ };
72
+ };
73
+ export default _default;
@@ -1,10 +1,2 @@
1
- declare const SvelteElementClass: any;
2
- declare class McPopulatedBlankAuthor extends SvelteElementClass {
3
- private _model;
4
- private _onChange;
5
- set model(m: any);
6
- get model(): any;
7
- set onChange(fn: (model: any) => void);
8
- get onChange(): (model: any) => void;
9
- }
10
- export default McPopulatedBlankAuthor;
1
+ declare const _default: any;
2
+ export default _default;