@pie-element/mc-populated-blank 0.1.0 → 0.2.1
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 +116 -2
- package/dist/controller/defaults.d.ts +89 -0
- package/dist/controller/defaults.d.ts.map +1 -1
- package/dist/controller/index.d.ts.map +1 -1
- package/dist/controller/index.js +110 -4
- package/dist/controller/index.js.map +1 -1
- package/dist/delivery/index.js +589 -477
- package/dist/delivery/index.js.map +1 -1
- package/dist/index.iife.d.ts +2 -1
- package/dist/index.iife.d.ts.map +1 -1
- package/dist/index.iife.js +25 -19
- package/dist/index.js +589 -477
- package/dist/index.js.map +1 -1
- package/package.json +1 -4
- package/src/controller/defaults.ts +53 -0
- package/src/controller/index.ts +83 -5
- package/src/delivery/McPopulatedBlank.svelte +464 -457
- package/src/index.iife.ts +2 -8
|
@@ -1,85 +1,114 @@
|
|
|
1
1
|
<svelte:options
|
|
2
2
|
customElement={{
|
|
3
|
+
tag: 'mc-populated-blank',
|
|
3
4
|
shadow: 'none',
|
|
4
5
|
props: {
|
|
5
6
|
model: { type: 'Object' },
|
|
6
7
|
session: { type: 'Object' },
|
|
7
8
|
options: { type: 'Object' },
|
|
8
|
-
onSessionChange: { type: 'Object' },
|
|
9
|
-
onAudioStarted: { type: 'Object' },
|
|
10
|
-
onAudioEnded: { type: 'Object' },
|
|
11
9
|
},
|
|
12
10
|
}}
|
|
13
11
|
/>
|
|
14
12
|
|
|
15
13
|
<script lang="ts">
|
|
16
|
-
import { onDestroy } from 'svelte';
|
|
17
|
-
|
|
18
14
|
/** Must match controller `BLANK_TOKEN` (kept local to avoid pulling controller into delivery). */
|
|
19
15
|
const BLANK_TOKEN = '{{blank}}';
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
16
|
+
const DEFAULT_LAYOUT_LIMITS = {
|
|
17
|
+
blankStandaloneWidthRem: 7,
|
|
18
|
+
blankWideWidthRem: 10,
|
|
19
|
+
blankUnderlineWidthPx: 2,
|
|
20
|
+
blankUnderlineWideWidthPx: 4,
|
|
21
|
+
horizontalChoiceWidthPx: 170,
|
|
22
|
+
horizontalChoiceWidthVw: 30,
|
|
23
|
+
horizontalChoiceTileMinHeightRem: 11,
|
|
24
|
+
horizontalChoiceContentMinHeightRem: 7.5,
|
|
25
|
+
selectedImageMaxHeightRem: 4,
|
|
26
|
+
choiceImageMaxHeightRem: 5,
|
|
27
|
+
listenButtonSizePx: 128,
|
|
28
|
+
stimulusMinColumnPx: 210,
|
|
29
|
+
textMinColumnPx: 260,
|
|
30
|
+
legendMaxChars: 120,
|
|
31
|
+
choiceGroupGapRem: 0.5,
|
|
32
|
+
choiceRowGapRem: 0.5,
|
|
33
|
+
toggleButtonGapRem: 0.5,
|
|
34
|
+
horizontalChoiceRadioTopMarginRem: 0.5,
|
|
35
|
+
audioBlankTemplateMarginTopRem: 0.8,
|
|
36
|
+
audioBlankTemplateMarginBottomRem: 1.8,
|
|
37
|
+
audioInstructionsMaxWidthPx: 875,
|
|
38
|
+
narrowHorizontalChoiceMaxWidthPx: 230,
|
|
39
|
+
stimulusGridColumnGapRem: 2,
|
|
40
|
+
stimulusGridRowGapRem: 0.7,
|
|
41
|
+
stimulusSentenceMarginTopRem: 0.2,
|
|
42
|
+
stimulusChoicesMarginTopRem: 0.9,
|
|
43
|
+
tokenGridColumnGapRem: 1.5,
|
|
44
|
+
tokenGridRowGapRem: 0.8,
|
|
45
|
+
tokenTemplateMarginTopRem: 0.6,
|
|
46
|
+
tokenInlineTokenGapRem: 0.35,
|
|
47
|
+
tokenChoicesMarginTopRem: 0.2,
|
|
48
|
+
inlineGridColumnGapRem: 1.5,
|
|
49
|
+
inlineGridRowGapRem: 0.65,
|
|
50
|
+
inlineTemplateMarginTopRem: 0.45,
|
|
51
|
+
inlineChoicesMarginTopRem: 0.25,
|
|
52
|
+
} as const;
|
|
53
|
+
const DEFAULT_LAYOUT_PROFILE_PRESETS: Record<string, Record<string, number>> = {
|
|
54
|
+
audio_blank_only: {
|
|
55
|
+
blankWideWidthRem: 10,
|
|
56
|
+
blankUnderlineWideWidthPx: 4,
|
|
57
|
+
},
|
|
58
|
+
stimulus_image_blank: {
|
|
59
|
+
blankWideWidthRem: 10,
|
|
60
|
+
blankUnderlineWideWidthPx: 4,
|
|
61
|
+
},
|
|
62
|
+
token_sequence: {
|
|
63
|
+
blankStandaloneWidthRem: 7,
|
|
64
|
+
blankUnderlineWideWidthPx: 4,
|
|
65
|
+
},
|
|
57
66
|
};
|
|
67
|
+
const DEFAULT_AUDIO_BUTTON_SKINS = {
|
|
68
|
+
default: {
|
|
69
|
+
silentUrl:
|
|
70
|
+
'https://assets.learnosity.com/organisations/844/0c9f2aa3-3cd5-4de7-93ef-541c24ca35da.svg',
|
|
71
|
+
playingUrl:
|
|
72
|
+
'https://assets.learnosity.com/organisations/844/231dfdc2-c113-4be5-91fb-e75a0ca5994b.svg',
|
|
73
|
+
},
|
|
74
|
+
es: {
|
|
75
|
+
silentUrl:
|
|
76
|
+
'https://assets.learnosity.com/organisations/844/27a9d5b5-d873-4bd5-b9ba-22748782d8ba.svg',
|
|
77
|
+
playingUrl:
|
|
78
|
+
'https://assets.learnosity.com/organisations/844/120f216d-96b7-4560-94b8-1d90710216b7.svg',
|
|
79
|
+
},
|
|
80
|
+
} as const;
|
|
81
|
+
const DEFAULT_UI_TEXT = {
|
|
82
|
+
answerChoices: 'Answer choices',
|
|
83
|
+
selectedAnswerInSentence: 'Selected answer in sentence',
|
|
84
|
+
showCorrectAnswer: 'Show correct answer',
|
|
85
|
+
hideCorrectAnswer: 'Hide correct answer',
|
|
86
|
+
clickToEnableAutoplay: 'Click to enable audio autoplay',
|
|
87
|
+
audioResourceUnavailable: 'Audio is enabled but no playable audio URL is configured.',
|
|
88
|
+
transcriptLabel: 'Transcript',
|
|
89
|
+
listenLabelEn: 'Listen',
|
|
90
|
+
listenLabelEs: 'Escuchar',
|
|
91
|
+
} as const;
|
|
58
92
|
|
|
59
|
-
let
|
|
60
|
-
model?: McModel;
|
|
61
|
-
session?: McSession;
|
|
62
|
-
options?: Record<string, unknown>;
|
|
63
|
-
onSessionChange?: (session: McSession) => void;
|
|
64
|
-
onAudioStarted?: () => void;
|
|
65
|
-
onAudioEnded?: () => void;
|
|
66
|
-
}>();
|
|
93
|
+
let { model, session, options } = $props<{ model?: any; session?: any; options?: any }>();
|
|
67
94
|
let audioEl = $state<HTMLAudioElement | null>(null);
|
|
68
|
-
let activeUtterance = $state<SpeechSynthesisUtterance | null>(null);
|
|
69
|
-
let isSynthSpeaking = $state(false);
|
|
70
95
|
let isMediaPlaying = $state(false);
|
|
71
96
|
let localChoiceId = $state('');
|
|
72
97
|
let autoPlayPromptOpen = $state(false);
|
|
73
98
|
let autoplayAttempted = $state(false);
|
|
99
|
+
let featureAudioButtonEl = $state<HTMLButtonElement | null>(null);
|
|
100
|
+
let autoplayEnableButtonEl = $state<HTMLButtonElement | null>(null);
|
|
101
|
+
let toggleCorrectAnswerButtonEl = $state<HTMLButtonElement | null>(null);
|
|
102
|
+
let choicesGroupEl = $state<HTMLDivElement | null>(null);
|
|
74
103
|
const instanceId = `mc-populated-blank-${Math.random().toString(36).slice(2, 10)}`;
|
|
75
104
|
|
|
76
|
-
const isEvaluateMode = $derived(
|
|
77
|
-
const correctness = $derived(
|
|
105
|
+
const isEvaluateMode = $derived(model?.env?.mode === 'evaluate');
|
|
106
|
+
const correctness = $derived(model?.correctness);
|
|
78
107
|
const isCorrect = $derived(correctness === 'correct');
|
|
79
108
|
const isIncorrect = $derived(correctness === 'incorrect');
|
|
80
|
-
const isAudioOnlyMode = $derived(
|
|
109
|
+
const isAudioOnlyMode = $derived(model?.interactionMode === 'audio_mc_only');
|
|
81
110
|
const isBlankOnlyTemplate = $derived.by(() => {
|
|
82
|
-
const t =
|
|
111
|
+
const t = model?.template || '';
|
|
83
112
|
if (!t) return false;
|
|
84
113
|
const plain = t
|
|
85
114
|
.replace(/<[^>]+>/g, '')
|
|
@@ -87,25 +116,91 @@ const isBlankOnlyTemplate = $derived.by(() => {
|
|
|
87
116
|
.trim();
|
|
88
117
|
return plain === BLANK_TOKEN;
|
|
89
118
|
});
|
|
90
|
-
const layoutProfile = $derived(
|
|
119
|
+
const layoutProfile = $derived(model?.layoutProfile || '');
|
|
91
120
|
const choiceLayout = $derived(
|
|
92
|
-
|
|
121
|
+
model?.choiceLayout || (isAudioOnlyMode || isBlankOnlyTemplate ? 'horizontal' : 'vertical')
|
|
93
122
|
);
|
|
94
123
|
const isHorizontalChoices = $derived(choiceLayout === 'horizontal');
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
const hasPlayableAudio = $derived(!!props?.model?.hasAudio && !!props?.model?.audioUrl);
|
|
99
|
-
const hasTranscriptOnlyAudio = $derived(
|
|
100
|
-
!!props?.model?.hasAudio && !props?.model?.audioUrl && !!props?.model?.audioTranscript
|
|
101
|
-
);
|
|
124
|
+
const showVisibleTranscript = $derived(!!model?.showVisibleTranscript);
|
|
125
|
+
const hasPlayableAudio = $derived(!!model?.hasAudio && !!model?.audioUrl);
|
|
126
|
+
const hasAudioButMissingResource = $derived(!!model?.hasAudio && !model?.audioUrl);
|
|
102
127
|
const hasInlineSentenceAudioLayout = $derived(
|
|
103
|
-
layoutProfile === 'inline_sentence' && !!
|
|
128
|
+
layoutProfile === 'inline_sentence' && !!model?.hasAudio
|
|
129
|
+
);
|
|
130
|
+
const uiText = $derived.by(() => ({
|
|
131
|
+
...DEFAULT_UI_TEXT,
|
|
132
|
+
...(model?.uiText || {}),
|
|
133
|
+
}));
|
|
134
|
+
const profilePresetLimits = $derived.by(() => {
|
|
135
|
+
const profile = String(layoutProfile || '');
|
|
136
|
+
const defaults = DEFAULT_LAYOUT_PROFILE_PRESETS[profile] || {};
|
|
137
|
+
const customPresets =
|
|
138
|
+
model?.layoutProfilePresets && typeof model.layoutProfilePresets === 'object'
|
|
139
|
+
? model.layoutProfilePresets
|
|
140
|
+
: {};
|
|
141
|
+
const custom =
|
|
142
|
+
customPresets[profile] && typeof customPresets[profile] === 'object'
|
|
143
|
+
? customPresets[profile]
|
|
144
|
+
: {};
|
|
145
|
+
return {
|
|
146
|
+
...defaults,
|
|
147
|
+
...custom,
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
const layoutLimits = $derived.by(() => {
|
|
151
|
+
const configured =
|
|
152
|
+
model?.layoutLimits && typeof model.layoutLimits === 'object' ? model.layoutLimits : {};
|
|
153
|
+
return {
|
|
154
|
+
...DEFAULT_LAYOUT_LIMITS,
|
|
155
|
+
...profilePresetLimits,
|
|
156
|
+
...configured,
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
const rootStyle = $derived.by(() =>
|
|
160
|
+
[
|
|
161
|
+
`--mpb-listen-button-size:${layoutLimits.listenButtonSizePx}px`,
|
|
162
|
+
`--mpb-blank-standalone-width:${layoutLimits.blankStandaloneWidthRem}rem`,
|
|
163
|
+
`--mpb-blank-wide-width:${layoutLimits.blankWideWidthRem}rem`,
|
|
164
|
+
`--mpb-blank-underline-width:${layoutLimits.blankUnderlineWidthPx}px`,
|
|
165
|
+
`--mpb-blank-underline-wide-width:${layoutLimits.blankUnderlineWideWidthPx}px`,
|
|
166
|
+
`--mpb-selected-image-max-height:${layoutLimits.selectedImageMaxHeightRem}rem`,
|
|
167
|
+
`--mpb-choice-image-max-height:${layoutLimits.choiceImageMaxHeightRem}rem`,
|
|
168
|
+
`--mpb-choice-width-px:${layoutLimits.horizontalChoiceWidthPx}px`,
|
|
169
|
+
`--mpb-choice-width-vw:${layoutLimits.horizontalChoiceWidthVw}vw`,
|
|
170
|
+
`--mpb-choice-tile-min-height:${layoutLimits.horizontalChoiceTileMinHeightRem}rem`,
|
|
171
|
+
`--mpb-choice-content-min-height:${layoutLimits.horizontalChoiceContentMinHeightRem}rem`,
|
|
172
|
+
`--mpb-stimulus-min-column:${layoutLimits.stimulusMinColumnPx}px`,
|
|
173
|
+
`--mpb-text-min-column:${layoutLimits.textMinColumnPx}px`,
|
|
174
|
+
`--mpb-choice-group-gap:${layoutLimits.choiceGroupGapRem}rem`,
|
|
175
|
+
`--mpb-choice-row-gap:${layoutLimits.choiceRowGapRem}rem`,
|
|
176
|
+
`--mpb-toggle-button-gap:${layoutLimits.toggleButtonGapRem}rem`,
|
|
177
|
+
`--mpb-horizontal-choice-radio-top-margin:${layoutLimits.horizontalChoiceRadioTopMarginRem}rem`,
|
|
178
|
+
`--mpb-audio-blank-template-margin-top:${layoutLimits.audioBlankTemplateMarginTopRem}rem`,
|
|
179
|
+
`--mpb-audio-blank-template-margin-bottom:${layoutLimits.audioBlankTemplateMarginBottomRem}rem`,
|
|
180
|
+
`--mpb-audio-instructions-max-width:${layoutLimits.audioInstructionsMaxWidthPx}px`,
|
|
181
|
+
`--mpb-narrow-choice-max-width:${layoutLimits.narrowHorizontalChoiceMaxWidthPx}px`,
|
|
182
|
+
`--mpb-stimulus-grid-column-gap:${layoutLimits.stimulusGridColumnGapRem}rem`,
|
|
183
|
+
`--mpb-stimulus-grid-row-gap:${layoutLimits.stimulusGridRowGapRem}rem`,
|
|
184
|
+
`--mpb-stimulus-sentence-margin-top:${layoutLimits.stimulusSentenceMarginTopRem}rem`,
|
|
185
|
+
`--mpb-stimulus-choices-margin-top:${layoutLimits.stimulusChoicesMarginTopRem}rem`,
|
|
186
|
+
`--mpb-token-grid-column-gap:${layoutLimits.tokenGridColumnGapRem}rem`,
|
|
187
|
+
`--mpb-token-grid-row-gap:${layoutLimits.tokenGridRowGapRem}rem`,
|
|
188
|
+
`--mpb-token-template-margin-top:${layoutLimits.tokenTemplateMarginTopRem}rem`,
|
|
189
|
+
`--mpb-token-inline-token-gap:${layoutLimits.tokenInlineTokenGapRem}rem`,
|
|
190
|
+
`--mpb-token-choices-margin-top:${layoutLimits.tokenChoicesMarginTopRem}rem`,
|
|
191
|
+
`--mpb-inline-grid-column-gap:${layoutLimits.inlineGridColumnGapRem}rem`,
|
|
192
|
+
`--mpb-inline-grid-row-gap:${layoutLimits.inlineGridRowGapRem}rem`,
|
|
193
|
+
`--mpb-inline-template-margin-top:${layoutLimits.inlineTemplateMarginTopRem}rem`,
|
|
194
|
+
`--mpb-inline-choices-margin-top:${layoutLimits.inlineChoicesMarginTopRem}rem`,
|
|
195
|
+
].join(';')
|
|
104
196
|
);
|
|
105
197
|
const useFeatureButtonAudio = $derived.by(() => {
|
|
198
|
+
if (typeof model?.useFeatureButtonAudio === 'boolean') {
|
|
199
|
+
return !!model.useFeatureButtonAudio;
|
|
200
|
+
}
|
|
106
201
|
const profile = layoutProfile || '';
|
|
107
202
|
return (
|
|
108
|
-
!!
|
|
203
|
+
!!model?.hasAudio &&
|
|
109
204
|
(profile === 'audio_blank_only' ||
|
|
110
205
|
profile === 'stimulus_image_blank' ||
|
|
111
206
|
profile === 'token_sequence')
|
|
@@ -113,7 +208,7 @@ const useFeatureButtonAudio = $derived.by(() => {
|
|
|
113
208
|
});
|
|
114
209
|
|
|
115
210
|
const templateParts = $derived.by(() => {
|
|
116
|
-
const t =
|
|
211
|
+
const t = model?.template || '';
|
|
117
212
|
const idx = t.indexOf(BLANK_TOKEN);
|
|
118
213
|
if (idx < 0) {
|
|
119
214
|
return { before: t, after: '' };
|
|
@@ -123,93 +218,50 @@ const templateParts = $derived.by(() => {
|
|
|
123
218
|
after: t.slice(idx + BLANK_TOKEN.length),
|
|
124
219
|
};
|
|
125
220
|
});
|
|
126
|
-
|
|
127
|
-
function plainTextFromHtml(value = ''): string {
|
|
128
|
-
return value
|
|
129
|
-
.replace(/<[^>]+>/g, ' ')
|
|
130
|
-
.replace(/ /g, ' ')
|
|
131
|
-
.replace(/\s+/g, ' ')
|
|
132
|
-
.trim();
|
|
133
|
-
}
|
|
134
|
-
|
|
135
221
|
const blankWidth = $derived.by(() => {
|
|
136
222
|
if (layoutProfile === 'audio_blank_only' || layoutProfile === 'stimulus_image_blank') {
|
|
137
|
-
return
|
|
223
|
+
return `${layoutLimits.blankWideWidthRem}rem`;
|
|
138
224
|
}
|
|
139
225
|
if (isBlankOnlyTemplate) {
|
|
140
|
-
return
|
|
141
|
-
}
|
|
142
|
-
if (choiceMode === 'text') {
|
|
143
|
-
const modelChoices = Array.isArray(props?.model?.choices) ? props.model.choices : [];
|
|
144
|
-
const longestChoiceChars = modelChoices.reduce((max: number, choice: McChoice) => {
|
|
145
|
-
const textLength = plainTextFromHtml(choice?.labelHtml || '').length;
|
|
146
|
-
return Math.max(max, textLength);
|
|
147
|
-
}, 0);
|
|
148
|
-
if (longestChoiceChars > 0) {
|
|
149
|
-
const widthInCh = Math.min(24, Math.max(7, longestChoiceChars + 1));
|
|
150
|
-
return `${widthInCh}ch`;
|
|
151
|
-
}
|
|
226
|
+
return `${layoutLimits.blankStandaloneWidthRem}rem`;
|
|
152
227
|
}
|
|
153
228
|
return 'auto';
|
|
154
229
|
});
|
|
155
230
|
const blankBorderWidth = $derived.by(() => {
|
|
156
231
|
if (layoutProfile === 'audio_blank_only' || layoutProfile === 'stimulus_image_blank') {
|
|
157
|
-
return
|
|
232
|
+
return `${layoutLimits.blankUnderlineWideWidthPx}px`;
|
|
158
233
|
}
|
|
159
|
-
return
|
|
234
|
+
return `${layoutLimits.blankUnderlineWidthPx}px`;
|
|
160
235
|
});
|
|
161
236
|
|
|
162
|
-
const choices = $derived(Array.isArray(
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const lockChoiceOrder = !!props?.model?.lockChoiceOrder || !!props?.options?.lockChoiceOrder;
|
|
167
|
-
return (modelShuffle || optionsShuffle) && !lockChoiceOrder;
|
|
168
|
-
});
|
|
169
|
-
const shuffleSeed = $derived.by(
|
|
170
|
-
() =>
|
|
171
|
-
`${props?.session?.id || props?.model?.id || instanceId}:${choices.map((c: McChoice) => c.id).join('|')}`
|
|
172
|
-
);
|
|
173
|
-
function hashString(value: string): number {
|
|
174
|
-
let hash = 2166136261;
|
|
175
|
-
for (let i = 0; i < value.length; i++) {
|
|
176
|
-
hash ^= value.charCodeAt(i);
|
|
177
|
-
hash = Math.imul(hash, 16777619);
|
|
178
|
-
}
|
|
179
|
-
return hash >>> 0;
|
|
180
|
-
}
|
|
181
|
-
function deterministicShuffle<T extends { id?: string }>(items: T[], seed: string): T[] {
|
|
182
|
-
return [...items]
|
|
183
|
-
.map((item, index) => ({
|
|
184
|
-
item,
|
|
185
|
-
key: hashString(`${seed}:${item?.id || index}:${index}`),
|
|
186
|
-
}))
|
|
187
|
-
.sort((a, b) => a.key - b.key)
|
|
188
|
-
.map((entry) => entry.item);
|
|
189
|
-
}
|
|
190
|
-
const renderedChoices = $derived.by(() =>
|
|
191
|
-
shouldShuffleChoices ? deterministicShuffle(choices, shuffleSeed) : choices
|
|
192
|
-
);
|
|
193
|
-
const choiceMode = $derived(props?.model?.choiceMode || 'text');
|
|
194
|
-
const selectedId = $derived(props?.session?.choiceId || localChoiceId || '');
|
|
195
|
-
const radioGroupName = $derived(`${instanceId}-choice-group-${props?.model?.id || '1'}`);
|
|
237
|
+
const choices = $derived(Array.isArray(model?.choices) ? model.choices : []);
|
|
238
|
+
const choiceMode = $derived(model?.choiceMode || 'text');
|
|
239
|
+
const selectedId = $derived(session?.choiceId || localChoiceId || '');
|
|
240
|
+
const radioGroupName = $derived(`${instanceId}-choice-group-${model?.id || '1'}`);
|
|
196
241
|
|
|
197
242
|
let showCorrectAnswer = $state(false);
|
|
198
243
|
|
|
199
244
|
const displayChoiceId = $derived.by(() => {
|
|
200
|
-
if (isEvaluateMode && showCorrectAnswer &&
|
|
201
|
-
return
|
|
245
|
+
if (isEvaluateMode && showCorrectAnswer && model?.correctChoiceId) {
|
|
246
|
+
return model.correctChoiceId;
|
|
202
247
|
}
|
|
203
248
|
return selectedId;
|
|
204
249
|
});
|
|
205
250
|
|
|
206
|
-
const displayChoice = $derived.by(() =>
|
|
207
|
-
renderedChoices.find((c: McChoice) => c.id === displayChoiceId)
|
|
208
|
-
);
|
|
251
|
+
const displayChoice = $derived.by(() => choices.find((c: any) => c.id === displayChoiceId));
|
|
209
252
|
|
|
210
253
|
const legendText = $derived.by(() => {
|
|
211
|
-
const plain =
|
|
212
|
-
|
|
254
|
+
const plain = (model?.prompt || '')
|
|
255
|
+
.replace(/<[^>]+>/g, ' ')
|
|
256
|
+
.replace(/\s+/g, ' ')
|
|
257
|
+
.trim();
|
|
258
|
+
const maxChars = Math.max(
|
|
259
|
+
8,
|
|
260
|
+
Number(layoutLimits.legendMaxChars) || DEFAULT_LAYOUT_LIMITS.legendMaxChars
|
|
261
|
+
);
|
|
262
|
+
return plain.length > maxChars
|
|
263
|
+
? `${plain.slice(0, Math.max(1, maxChars - 1))}…`
|
|
264
|
+
: plain || uiText.answerChoices;
|
|
213
265
|
});
|
|
214
266
|
|
|
215
267
|
const promptId = $derived(`${instanceId}-prompt`);
|
|
@@ -217,62 +269,51 @@ const transcriptId = $derived(`${instanceId}-transcript`);
|
|
|
217
269
|
const legendId = $derived(`${instanceId}-choices-legend`);
|
|
218
270
|
const resultId = $derived(`${instanceId}-result`);
|
|
219
271
|
|
|
220
|
-
const choicesGroupLabelledBy = $derived(
|
|
272
|
+
const choicesGroupLabelledBy = $derived(model?.prompt ? promptId : undefined);
|
|
273
|
+
const choicesGroupAriaLabel = $derived.by(() => {
|
|
274
|
+
if (model?.prompt) return undefined;
|
|
275
|
+
const explicit = String(model?.choiceGroupLabel || '').trim();
|
|
276
|
+
if (explicit) return explicit;
|
|
277
|
+
return legendText;
|
|
278
|
+
});
|
|
221
279
|
|
|
222
280
|
const templateDescribedBy = $derived.by(() => {
|
|
223
281
|
const ids: string[] = [];
|
|
224
|
-
if (
|
|
225
|
-
if (
|
|
282
|
+
if (model?.prompt) ids.push(promptId);
|
|
283
|
+
if (model?.hasAudio && model?.audioTranscript) {
|
|
226
284
|
ids.push(transcriptId);
|
|
227
285
|
}
|
|
228
286
|
return ids.length ? ids.join(' ') : undefined;
|
|
229
287
|
});
|
|
230
288
|
|
|
231
289
|
const lang = $derived.by(() => {
|
|
232
|
-
const locale =
|
|
290
|
+
const locale = model?.locale || '';
|
|
233
291
|
return locale ? locale.slice(0, 2) : 'en';
|
|
234
292
|
});
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
answerChoices: 'Answer choices',
|
|
239
|
-
correctSelected: 'Correct answer selected',
|
|
240
|
-
incorrectSelected: 'Incorrect answer selected',
|
|
241
|
-
selectedAnswerInSentence: 'Selected answer in sentence',
|
|
242
|
-
selectedAnswerImage: 'Selected answer image',
|
|
243
|
-
showCorrect: 'Show correct answer',
|
|
244
|
-
hideCorrect: 'Hide correct answer',
|
|
245
|
-
enableAutoplay: 'Click to enable audio autoplay',
|
|
246
|
-
listen: 'Listen',
|
|
247
|
-
teacherInstructions: 'Teacher instructions',
|
|
248
|
-
},
|
|
249
|
-
es: {
|
|
250
|
-
answerChoices: 'Opciones de respuesta',
|
|
251
|
-
correctSelected: 'Respuesta correcta seleccionada',
|
|
252
|
-
incorrectSelected: 'Respuesta incorrecta seleccionada',
|
|
253
|
-
selectedAnswerInSentence: 'Respuesta seleccionada en la oración',
|
|
254
|
-
selectedAnswerImage: 'Imagen de la respuesta seleccionada',
|
|
255
|
-
showCorrect: 'Mostrar respuesta correcta',
|
|
256
|
-
hideCorrect: 'Ocultar respuesta correcta',
|
|
257
|
-
enableAutoplay: 'Haga clic para habilitar la reproducción automática de audio',
|
|
258
|
-
listen: 'Escuchar',
|
|
259
|
-
teacherInstructions: 'Instrucciones para el docente',
|
|
260
|
-
},
|
|
261
|
-
} as const;
|
|
262
|
-
type UiKey = keyof (typeof uiStrings)['en'];
|
|
263
|
-
function t(key: UiKey): string {
|
|
264
|
-
return (lang === 'es' ? uiStrings.es[key] : uiStrings.en[key]) || uiStrings.en[key];
|
|
265
|
-
}
|
|
293
|
+
const audioErrorMessage = $derived.by(() =>
|
|
294
|
+
hasAudioButMissingResource ? uiText.audioResourceUnavailable : ''
|
|
295
|
+
);
|
|
266
296
|
|
|
267
297
|
const resultText = $derived.by(() => {
|
|
268
298
|
if (!isEvaluateMode || showCorrectAnswer) return '';
|
|
269
|
-
if (isCorrect) return
|
|
270
|
-
if (isIncorrect && selectedId) return
|
|
299
|
+
if (isCorrect) return 'Correct answer selected';
|
|
300
|
+
if (isIncorrect && selectedId) return 'Incorrect answer selected';
|
|
271
301
|
return '';
|
|
272
302
|
});
|
|
273
303
|
|
|
274
|
-
function emitSession(updatedSession:
|
|
275
|
-
|
|
304
|
+
function emitSession(updatedSession: any, sourceEl?: HTMLElement | null) {
|
|
305
|
+
const host = getHostElement(sourceEl);
|
|
306
|
+
if (host?.onSessionChange) {
|
|
307
|
+
host.onSessionChange(updatedSession);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
host?.dispatchEvent(
|
|
311
|
+
new CustomEvent('session-changed', {
|
|
312
|
+
bubbles: true,
|
|
313
|
+
composed: true,
|
|
314
|
+
detail: { complete: !!updatedSession?.choiceId, component: 'mc-populated-blank' },
|
|
315
|
+
})
|
|
316
|
+
);
|
|
276
317
|
}
|
|
277
318
|
|
|
278
319
|
function onRadioChange(e: Event) {
|
|
@@ -281,12 +322,12 @@ function onRadioChange(e: Event) {
|
|
|
281
322
|
const choiceId = input.value;
|
|
282
323
|
localChoiceId = choiceId;
|
|
283
324
|
const updatedSession = {
|
|
284
|
-
...
|
|
285
|
-
id:
|
|
325
|
+
...session,
|
|
326
|
+
id: session?.id || model?.id || '1',
|
|
286
327
|
element: 'mc-populated-blank',
|
|
287
328
|
choiceId,
|
|
288
329
|
};
|
|
289
|
-
emitSession(updatedSession);
|
|
330
|
+
emitSession(updatedSession, input);
|
|
290
331
|
}
|
|
291
332
|
|
|
292
333
|
function toggleCorrectAnswer() {
|
|
@@ -294,7 +335,7 @@ function toggleCorrectAnswer() {
|
|
|
294
335
|
}
|
|
295
336
|
|
|
296
337
|
function onRadioGroupKeydown(e: KeyboardEvent) {
|
|
297
|
-
if (
|
|
338
|
+
if (model?.disabled) return;
|
|
298
339
|
const key = e.key;
|
|
299
340
|
if (!['ArrowDown', 'ArrowRight', 'ArrowUp', 'ArrowLeft'].includes(key)) return;
|
|
300
341
|
e.preventDefault();
|
|
@@ -320,45 +361,57 @@ function handleEnableAutoplayClick() {
|
|
|
320
361
|
audioEl.play().finally(() => {
|
|
321
362
|
autoPlayPromptOpen = false;
|
|
322
363
|
});
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
if (hasTranscriptOnlyAudio) {
|
|
326
|
-
speakTranscript();
|
|
327
|
-
autoPlayPromptOpen = false;
|
|
328
364
|
}
|
|
329
365
|
}
|
|
330
366
|
|
|
331
|
-
function onAudioPlaying() {
|
|
367
|
+
function onAudioPlaying(e: Event) {
|
|
368
|
+
const host = getHostElement(e.currentTarget as HTMLElement);
|
|
332
369
|
isMediaPlaying = true;
|
|
333
|
-
|
|
370
|
+
host?.onAudioStarted?.();
|
|
334
371
|
autoPlayPromptOpen = false;
|
|
335
372
|
}
|
|
336
373
|
|
|
337
|
-
function onAudioEnded() {
|
|
374
|
+
function onAudioEnded(e: Event) {
|
|
375
|
+
const host = getHostElement(e.currentTarget as HTMLElement);
|
|
338
376
|
isMediaPlaying = false;
|
|
339
|
-
|
|
377
|
+
host?.onAudioEnded?.();
|
|
340
378
|
}
|
|
341
379
|
|
|
342
|
-
function
|
|
343
|
-
|
|
380
|
+
function getHostElement(sourceEl?: HTMLElement | null) {
|
|
381
|
+
let cursor: HTMLElement | null | undefined = sourceEl;
|
|
382
|
+
while (cursor) {
|
|
383
|
+
const maybeHost = cursor as any;
|
|
384
|
+
if (
|
|
385
|
+
typeof maybeHost?.onSessionChange === 'function' ||
|
|
386
|
+
typeof maybeHost?.onAudioStarted === 'function' ||
|
|
387
|
+
typeof maybeHost?.onAudioEnded === 'function'
|
|
388
|
+
) {
|
|
389
|
+
return maybeHost;
|
|
390
|
+
}
|
|
391
|
+
cursor = cursor.parentElement;
|
|
392
|
+
}
|
|
393
|
+
return (document.querySelector('mc-populated-blank') as any) || null;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function speechButtonLabel(locale = '') {
|
|
397
|
+
return locale.toLowerCase().startsWith('es') ? uiText.listenLabelEs : uiText.listenLabelEn;
|
|
344
398
|
}
|
|
345
399
|
|
|
346
400
|
const featureAudioSkin = $derived.by(() => {
|
|
347
|
-
const locale = String(
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
};
|
|
401
|
+
const locale = String(model?.locale || '').toLowerCase();
|
|
402
|
+
const lang = locale.slice(0, 2);
|
|
403
|
+
const byLocale =
|
|
404
|
+
model?.audioButtonSkinsByLocale && typeof model.audioButtonSkinsByLocale === 'object'
|
|
405
|
+
? model.audioButtonSkinsByLocale
|
|
406
|
+
: {};
|
|
407
|
+
const customSingle =
|
|
408
|
+
model?.audioButtonSkin && typeof model.audioButtonSkin === 'object'
|
|
409
|
+
? model.audioButtonSkin
|
|
410
|
+
: null;
|
|
411
|
+
const defaultSkin = locale.startsWith('es')
|
|
412
|
+
? DEFAULT_AUDIO_BUTTON_SKINS.es
|
|
413
|
+
: DEFAULT_AUDIO_BUTTON_SKINS.default;
|
|
414
|
+
return byLocale[locale] || byLocale[lang] || byLocale.default || customSingle || defaultSkin;
|
|
362
415
|
});
|
|
363
416
|
|
|
364
417
|
function playFeatureAudio() {
|
|
@@ -366,105 +419,123 @@ function playFeatureAudio() {
|
|
|
366
419
|
audioEl.play().catch(() => {
|
|
367
420
|
// Keep behavior resilient: if playback is blocked, user can retry.
|
|
368
421
|
});
|
|
369
|
-
return;
|
|
370
422
|
}
|
|
371
|
-
speakTranscript();
|
|
372
423
|
}
|
|
373
424
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
const utterance = new SpeechSynthesisUtterance(transcript);
|
|
380
|
-
utterance.lang = props?.model?.locale || 'en-US';
|
|
425
|
+
$effect(() => {
|
|
426
|
+
if (session?.choiceId) {
|
|
427
|
+
localChoiceId = session.choiceId;
|
|
428
|
+
}
|
|
429
|
+
});
|
|
381
430
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
431
|
+
$effect(() => {
|
|
432
|
+
const el = audioEl;
|
|
433
|
+
if (!el) return;
|
|
434
|
+
const handlePlaying = (e: Event) => onAudioPlaying(e);
|
|
435
|
+
const handleEnded = (e: Event) => onAudioEnded(e);
|
|
436
|
+
el.addEventListener('playing', handlePlaying);
|
|
437
|
+
el.addEventListener('ended', handleEnded);
|
|
438
|
+
return () => {
|
|
439
|
+
el.removeEventListener('playing', handlePlaying);
|
|
440
|
+
el.removeEventListener('ended', handleEnded);
|
|
385
441
|
};
|
|
442
|
+
});
|
|
386
443
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
444
|
+
$effect(() => {
|
|
445
|
+
const btn = featureAudioButtonEl;
|
|
446
|
+
if (!btn) return;
|
|
447
|
+
const handleClick = () => playFeatureAudio();
|
|
448
|
+
btn.addEventListener('click', handleClick);
|
|
449
|
+
return () => {
|
|
450
|
+
btn.removeEventListener('click', handleClick);
|
|
391
451
|
};
|
|
452
|
+
});
|
|
392
453
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
454
|
+
$effect(() => {
|
|
455
|
+
const btn = autoplayEnableButtonEl;
|
|
456
|
+
if (!btn) return;
|
|
457
|
+
const handleClick = () => handleEnableAutoplayClick();
|
|
458
|
+
btn.addEventListener('click', handleClick);
|
|
459
|
+
return () => {
|
|
460
|
+
btn.removeEventListener('click', handleClick);
|
|
396
461
|
};
|
|
462
|
+
});
|
|
397
463
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
464
|
+
$effect(() => {
|
|
465
|
+
const btn = toggleCorrectAnswerButtonEl;
|
|
466
|
+
if (!btn) return;
|
|
467
|
+
const handleClick = () => toggleCorrectAnswer();
|
|
468
|
+
btn.addEventListener('click', handleClick);
|
|
469
|
+
return () => {
|
|
470
|
+
btn.removeEventListener('click', handleClick);
|
|
471
|
+
};
|
|
406
472
|
});
|
|
407
473
|
|
|
408
474
|
$effect(() => {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
475
|
+
const group = choicesGroupEl;
|
|
476
|
+
if (!group) return;
|
|
477
|
+
const handleChange = (e: Event) => {
|
|
478
|
+
const target = e.target as HTMLInputElement | null;
|
|
479
|
+
if (!target || target.type !== 'radio') return;
|
|
480
|
+
onRadioChange(e);
|
|
481
|
+
};
|
|
482
|
+
const handleKeydown = (e: KeyboardEvent) => onRadioGroupKeydown(e);
|
|
483
|
+
group.addEventListener('change', handleChange);
|
|
484
|
+
group.addEventListener('keydown', handleKeydown);
|
|
485
|
+
return () => {
|
|
486
|
+
group.removeEventListener('change', handleChange);
|
|
487
|
+
group.removeEventListener('keydown', handleKeydown);
|
|
488
|
+
};
|
|
412
489
|
});
|
|
413
490
|
|
|
414
491
|
$effect(() => {
|
|
415
|
-
if (!
|
|
492
|
+
if (!model?.hasAudio || !model?.autoplayAudioEnabled) return;
|
|
416
493
|
if (autoplayAttempted) return;
|
|
417
494
|
|
|
418
495
|
autoplayAttempted = true;
|
|
419
|
-
if (audioEl &&
|
|
496
|
+
if (audioEl && model?.audioUrl) {
|
|
420
497
|
// Browser autoplay restrictions vary. Try immediate play; if blocked show click-to-enable affordance.
|
|
421
498
|
audioEl.play().catch(() => {
|
|
422
499
|
autoPlayPromptOpen = true;
|
|
423
500
|
});
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
if (props?.model?.audioTranscript) {
|
|
428
|
-
autoPlayPromptOpen = true;
|
|
429
501
|
}
|
|
430
502
|
});
|
|
431
503
|
</script>
|
|
432
504
|
|
|
433
505
|
<div
|
|
434
|
-
class={`p-4 mc-populated-blank-root layout-${layoutProfile} ${hasInlineSentenceAudioLayout ? 'has-inline-audio' : ''}
|
|
506
|
+
class={`p-4 mc-populated-blank-root pie-element pie-element-mc-populated-blank pie-delivery-root layout-${layoutProfile} ${hasInlineSentenceAudioLayout ? 'has-inline-audio' : ''}`}
|
|
435
507
|
lang={lang}
|
|
508
|
+
style={rootStyle}
|
|
436
509
|
>
|
|
437
|
-
{#if
|
|
438
|
-
<div class="mb-4 prose" id={promptId}>{@html
|
|
510
|
+
{#if model?.prompt}
|
|
511
|
+
<div class="mb-4 prose pie-prompt" id={promptId}>{@html model.prompt}</div>
|
|
439
512
|
{/if}
|
|
440
513
|
|
|
441
|
-
{#if
|
|
442
|
-
<div class="mb-4 audio-container">
|
|
514
|
+
{#if model?.hasAudio}
|
|
515
|
+
<div class="mb-4 audio-container pie-audio-container">
|
|
443
516
|
{#if hasPlayableAudio && useFeatureButtonAudio}
|
|
444
517
|
<audio
|
|
445
518
|
bind:this={audioEl}
|
|
446
|
-
class="sr-only"
|
|
519
|
+
class="sr-only pie-audio-player"
|
|
447
520
|
preload="metadata"
|
|
448
|
-
src={
|
|
521
|
+
src={model.audioUrl}
|
|
449
522
|
aria-hidden="true"
|
|
450
523
|
tabindex="-1"
|
|
451
|
-
onplaying={onAudioPlaying}
|
|
452
|
-
onended={onAudioEnded}
|
|
453
524
|
></audio>
|
|
454
525
|
<button
|
|
455
|
-
|
|
526
|
+
bind:this={featureAudioButtonEl}
|
|
527
|
+
class="listen-button pie-listen-button rli-feature-audio"
|
|
456
528
|
type="button"
|
|
457
|
-
aria-label={speechButtonLabel()}
|
|
458
|
-
onclick={playFeatureAudio}
|
|
529
|
+
aria-label={speechButtonLabel(model?.locale)}
|
|
459
530
|
>
|
|
460
531
|
<img
|
|
461
|
-
class={`listen-feature-icon rli-feature-listen ${isMediaPlaying
|
|
532
|
+
class={`listen-feature-icon pie-listen-icon rli-feature-listen ${isMediaPlaying ? '' : 'listen-active'}`}
|
|
462
533
|
src={featureAudioSkin.silentUrl}
|
|
463
534
|
alt=""
|
|
464
535
|
aria-hidden="true"
|
|
465
536
|
/>
|
|
466
537
|
<img
|
|
467
|
-
class={`listen-feature-icon rli-feature-listen ${isMediaPlaying
|
|
538
|
+
class={`listen-feature-icon pie-listen-icon rli-feature-listen ${isMediaPlaying ? 'listen-active' : ''}`}
|
|
468
539
|
src={featureAudioSkin.playingUrl}
|
|
469
540
|
alt=""
|
|
470
541
|
aria-hidden="true"
|
|
@@ -474,84 +545,62 @@ $effect(() => {
|
|
|
474
545
|
<audio
|
|
475
546
|
bind:this={audioEl}
|
|
476
547
|
controls
|
|
477
|
-
class="w-full max-w-md"
|
|
548
|
+
class="w-full max-w-md pie-audio-player"
|
|
478
549
|
preload="metadata"
|
|
479
|
-
src={
|
|
480
|
-
aria-describedby={
|
|
481
|
-
onplaying={onAudioPlaying}
|
|
482
|
-
onended={onAudioEnded}
|
|
550
|
+
src={model.audioUrl}
|
|
551
|
+
aria-describedby={model?.audioTranscript ? transcriptId : undefined}
|
|
483
552
|
>
|
|
484
553
|
<track kind="captions" />
|
|
485
554
|
</audio>
|
|
486
555
|
{#if autoPlayPromptOpen}
|
|
487
|
-
<button
|
|
488
|
-
{
|
|
556
|
+
<button
|
|
557
|
+
bind:this={autoplayEnableButtonEl}
|
|
558
|
+
class="mt-2 text-sm underline pie-audio-autoplay-enable"
|
|
559
|
+
type="button"
|
|
560
|
+
>
|
|
561
|
+
{uiText.clickToEnableAutoplay}
|
|
489
562
|
</button>
|
|
490
563
|
{/if}
|
|
491
|
-
{:else if
|
|
492
|
-
<
|
|
493
|
-
class="listen-button rli-feature-audio"
|
|
494
|
-
type="button"
|
|
495
|
-
aria-label={speechButtonLabel()}
|
|
496
|
-
onclick={playFeatureAudio}
|
|
497
|
-
>
|
|
498
|
-
<img
|
|
499
|
-
class={`listen-feature-icon rli-feature-listen ${isMediaPlaying || isSynthSpeaking ? '' : 'listen-active'}`}
|
|
500
|
-
src={featureAudioSkin.silentUrl}
|
|
501
|
-
alt=""
|
|
502
|
-
aria-hidden="true"
|
|
503
|
-
/>
|
|
504
|
-
<img
|
|
505
|
-
class={`listen-feature-icon rli-feature-listen ${isMediaPlaying || isSynthSpeaking ? 'listen-active' : ''}`}
|
|
506
|
-
src={featureAudioSkin.playingUrl}
|
|
507
|
-
alt=""
|
|
508
|
-
aria-hidden="true"
|
|
509
|
-
/>
|
|
510
|
-
</button>
|
|
564
|
+
{:else if hasAudioButMissingResource}
|
|
565
|
+
<p class="text-sm text-red-700 pie-audio-error" role="alert">{audioErrorMessage}</p>
|
|
511
566
|
{/if}
|
|
512
|
-
{#if
|
|
567
|
+
{#if model?.audioTranscript}
|
|
513
568
|
<p
|
|
514
|
-
class={`text-sm mt-2 text-gray-700 ${showVisibleTranscript ? '' : 'sr-only'}`}
|
|
569
|
+
class={`text-sm mt-2 text-gray-700 pie-audio-transcript ${showVisibleTranscript ? '' : 'sr-only'}`}
|
|
515
570
|
id={transcriptId}
|
|
516
571
|
>
|
|
517
|
-
{
|
|
572
|
+
<strong>{uiText.transcriptLabel}:</strong> {model.audioTranscript}
|
|
518
573
|
</p>
|
|
519
574
|
{/if}
|
|
520
575
|
</div>
|
|
521
576
|
{/if}
|
|
522
577
|
|
|
523
|
-
{#if
|
|
524
|
-
<div class="mb-
|
|
525
|
-
|
|
526
|
-
<div class="prose teacher-instructions-content">{@html props.model.teacherInstructions}</div>
|
|
527
|
-
</div>
|
|
528
|
-
{/if}
|
|
529
|
-
|
|
530
|
-
{#if props?.model?.sentenceHtml}
|
|
531
|
-
<div class="mb-3 prose prose-p:my-1 sentence-line" aria-describedby={templateDescribedBy}>
|
|
532
|
-
{@html props.model.sentenceHtml}
|
|
578
|
+
{#if model?.sentenceHtml}
|
|
579
|
+
<div class="mb-3 prose prose-p:my-1 sentence-line pie-sentence-line" aria-describedby={templateDescribedBy}>
|
|
580
|
+
{@html model.sentenceHtml}
|
|
533
581
|
</div>
|
|
534
582
|
{/if}
|
|
535
583
|
|
|
536
584
|
{#if !isAudioOnlyMode}
|
|
537
|
-
<div class="mb-4 template-line" aria-describedby={templateDescribedBy}>
|
|
585
|
+
<div class="mb-4 template-line pie-template-line" aria-describedby={templateDescribedBy}>
|
|
538
586
|
{@html templateParts.before}
|
|
539
587
|
<span
|
|
540
|
-
class={`inline-flex items-center min-h-[1.5em] px-2 mx-1 border-b-2 border-gray-500 align-baseline blank-slot ${isBlankOnlyTemplate ? 'blank-slot-standalone' : ''}`}
|
|
588
|
+
class={`inline-flex items-center min-h-[1.5em] px-2 mx-1 border-b-2 border-gray-500 align-baseline blank-slot pie-blank-slot ${isBlankOnlyTemplate ? 'blank-slot-standalone pie-blank-slot-standalone' : ''}`}
|
|
541
589
|
style={`width:${blankWidth};border-bottom-width:${blankBorderWidth};`}
|
|
542
590
|
role="status"
|
|
543
591
|
aria-live="polite"
|
|
544
592
|
aria-atomic="true"
|
|
545
|
-
aria-label={
|
|
593
|
+
aria-label={uiText.selectedAnswerInSentence}
|
|
546
594
|
>
|
|
547
595
|
{#if choiceMode === 'image' && displayChoice?.imageUrl}
|
|
548
596
|
<img
|
|
549
597
|
src={displayChoice.imageUrl}
|
|
550
|
-
alt={displayChoice.imageAlt ||
|
|
551
|
-
class="
|
|
598
|
+
alt={displayChoice.imageAlt || 'Selected answer image'}
|
|
599
|
+
class="w-auto object-contain pie-blank-image"
|
|
600
|
+
style="max-height:var(--mpb-selected-image-max-height, 4rem);"
|
|
552
601
|
/>
|
|
553
602
|
{:else if displayChoice?.labelHtml}
|
|
554
|
-
<span class="blank-inner choice-label">{@html displayChoice.labelHtml}</span>
|
|
603
|
+
<span class="blank-inner choice-label pie-blank-value">{@html displayChoice.labelHtml}</span>
|
|
555
604
|
{:else}
|
|
556
605
|
<span class="blank-inner-empty" aria-hidden="true"> </span>
|
|
557
606
|
{/if}
|
|
@@ -562,45 +611,53 @@ $effect(() => {
|
|
|
562
611
|
|
|
563
612
|
{#if isEvaluateMode && isIncorrect}
|
|
564
613
|
<button
|
|
614
|
+
bind:this={toggleCorrectAnswerButtonEl}
|
|
565
615
|
type="button"
|
|
566
|
-
class="mb-3 flex items-center
|
|
567
|
-
|
|
616
|
+
class="mb-3 flex items-center cursor-pointer select-none pie-toggle-correct-answer"
|
|
617
|
+
style="gap:var(--mpb-toggle-button-gap, 0.5rem);"
|
|
568
618
|
aria-pressed={showCorrectAnswer}
|
|
569
619
|
>
|
|
570
620
|
<span class="text-sm hover:underline">
|
|
571
|
-
{showCorrectAnswer ?
|
|
621
|
+
{showCorrectAnswer ? uiText.hideCorrectAnswer : uiText.showCorrectAnswer}
|
|
572
622
|
</span>
|
|
573
623
|
</button>
|
|
574
624
|
{/if}
|
|
575
625
|
{#if resultText}
|
|
576
|
-
<p id={resultId} class="sr-only" role="status" aria-live="polite">{resultText}</p>
|
|
626
|
+
<p id={resultId} class="sr-only pie-result-feedback" role="status" aria-live="polite">{resultText}</p>
|
|
577
627
|
{/if}
|
|
578
628
|
|
|
579
|
-
<fieldset class="border-0 p-0 m-0" disabled={
|
|
580
|
-
<legend class="sr-only" id={legendId}>{legendText}</legend>
|
|
629
|
+
<fieldset class="border-0 p-0 m-0 pie-choices-fieldset" disabled={model?.disabled}>
|
|
630
|
+
<legend class="sr-only pie-choices-legend" id={legendId}>{legendText}</legend>
|
|
581
631
|
<div
|
|
582
|
-
|
|
632
|
+
bind:this={choicesGroupEl}
|
|
633
|
+
class={`pie-choices ${isHorizontalChoices ? 'flex flex-row flex-wrap items-start justify-center' : 'flex flex-col'}`}
|
|
634
|
+
style="gap:var(--mpb-choice-group-gap, 0.5rem);"
|
|
583
635
|
role="radiogroup"
|
|
584
636
|
tabindex="-1"
|
|
585
637
|
aria-labelledby={choicesGroupLabelledBy}
|
|
638
|
+
aria-label={choicesGroupAriaLabel}
|
|
586
639
|
aria-describedby={resultText ? resultId : undefined}
|
|
587
|
-
onkeydown={onRadioGroupKeydown}
|
|
588
640
|
>
|
|
589
|
-
{#each
|
|
641
|
+
{#each choices as c (c.id)}
|
|
590
642
|
<div
|
|
591
|
-
class={`flex items-start
|
|
643
|
+
class={`flex items-start choice-row pie-choice ${isHorizontalChoices ? 'choice-row-horizontal pie-choice-horizontal' : ''} ${((showCorrectAnswer && isEvaluateMode ? model?.correctChoiceId : selectedId) === c.id) ? 'is-selected pie-choice-selected' : ''}`}
|
|
644
|
+
style="gap:var(--mpb-choice-row-gap, 0.5rem);"
|
|
592
645
|
>
|
|
593
646
|
{#if isHorizontalChoices}
|
|
594
|
-
<label
|
|
595
|
-
|
|
647
|
+
<label
|
|
648
|
+
for={`${instanceId}-opt-${c.id}`}
|
|
649
|
+
class="cursor-pointer choice-tile text-center pie-choice-tile"
|
|
650
|
+
>
|
|
651
|
+
<span class="choice-tile-content pie-choice-tile-content">
|
|
596
652
|
{#if choiceMode === 'image' && c.imageUrl}
|
|
597
653
|
<img
|
|
598
654
|
src={c.imageUrl}
|
|
599
655
|
alt={c.imageAlt || `Choice ${c.id}`}
|
|
600
|
-
class="
|
|
656
|
+
class="object-contain mx-auto pie-choice-image"
|
|
657
|
+
style="max-height:var(--mpb-choice-image-max-height, 5rem);"
|
|
601
658
|
/>
|
|
602
659
|
{:else}
|
|
603
|
-
<span class="choice-label">{@html c.labelHtml || ''}</span>
|
|
660
|
+
<span class="choice-label pie-choice-label">{@html c.labelHtml || ''}</span>
|
|
604
661
|
{/if}
|
|
605
662
|
</span>
|
|
606
663
|
<input
|
|
@@ -609,11 +666,10 @@ $effect(() => {
|
|
|
609
666
|
id={`${instanceId}-opt-${c.id}`}
|
|
610
667
|
value={c.id}
|
|
611
668
|
checked={
|
|
612
|
-
(showCorrectAnswer && isEvaluateMode ?
|
|
669
|
+
(showCorrectAnswer && isEvaluateMode ? model?.correctChoiceId : selectedId) === c.id
|
|
613
670
|
}
|
|
614
|
-
disabled={
|
|
615
|
-
|
|
616
|
-
class="choice-radio-bottom"
|
|
671
|
+
disabled={model?.disabled}
|
|
672
|
+
class="choice-radio-bottom pie-choice-radio pie-choice-radio-bottom"
|
|
617
673
|
/>
|
|
618
674
|
</label>
|
|
619
675
|
{:else}
|
|
@@ -623,25 +679,33 @@ $effect(() => {
|
|
|
623
679
|
id={`${instanceId}-opt-${c.id}`}
|
|
624
680
|
value={c.id}
|
|
625
681
|
checked={
|
|
626
|
-
(showCorrectAnswer && isEvaluateMode ?
|
|
682
|
+
(showCorrectAnswer && isEvaluateMode ? model?.correctChoiceId : selectedId) === c.id
|
|
627
683
|
}
|
|
628
|
-
disabled={
|
|
629
|
-
|
|
630
|
-
class="mt-1"
|
|
684
|
+
disabled={model?.disabled}
|
|
685
|
+
class="choice-radio-inline pie-choice-radio pie-choice-radio-inline"
|
|
631
686
|
/>
|
|
632
|
-
<label for={`${instanceId}-opt-${c.id}`} class="cursor-pointer flex-1">
|
|
687
|
+
<label for={`${instanceId}-opt-${c.id}`} class="cursor-pointer flex-1 pie-choice-label-wrap">
|
|
633
688
|
{#if choiceMode === 'image' && c.imageUrl}
|
|
634
|
-
<img
|
|
689
|
+
<img
|
|
690
|
+
src={c.imageUrl}
|
|
691
|
+
alt={c.imageAlt || `Choice ${c.id}`}
|
|
692
|
+
class="object-contain pie-choice-image"
|
|
693
|
+
style="max-height:var(--mpb-choice-image-max-height, 5rem);"
|
|
694
|
+
/>
|
|
635
695
|
{:else}
|
|
636
|
-
<span class="choice-label">{@html c.labelHtml || ''}</span>
|
|
696
|
+
<span class="choice-label pie-choice-label">{@html c.labelHtml || ''}</span>
|
|
637
697
|
{/if}
|
|
638
698
|
</label>
|
|
639
699
|
{/if}
|
|
640
700
|
{#if isEvaluateMode && !showCorrectAnswer}
|
|
641
701
|
{#if selectedId === c.id && isCorrect}
|
|
642
|
-
<span class="text-green-600 text-sm font-medium" aria-hidden="true"
|
|
702
|
+
<span class="text-green-600 text-sm font-medium pie-choice-feedback-correct" aria-hidden="true">
|
|
703
|
+
✓
|
|
704
|
+
</span>
|
|
643
705
|
{:else if selectedId === c.id && isIncorrect}
|
|
644
|
-
<span class="text-red-600 text-sm font-medium" aria-hidden="true"
|
|
706
|
+
<span class="text-red-600 text-sm font-medium pie-choice-feedback-incorrect" aria-hidden="true">
|
|
707
|
+
✗
|
|
708
|
+
</span>
|
|
645
709
|
{/if}
|
|
646
710
|
{/if}
|
|
647
711
|
</div>
|
|
@@ -694,12 +758,12 @@ $effect(() => {
|
|
|
694
758
|
}
|
|
695
759
|
|
|
696
760
|
.blank-slot-standalone {
|
|
697
|
-
width: 7rem;
|
|
761
|
+
width: var(--mpb-blank-standalone-width, 7rem);
|
|
698
762
|
}
|
|
699
763
|
|
|
700
764
|
.listen-button {
|
|
701
|
-
width: 128px;
|
|
702
|
-
height: 128px;
|
|
765
|
+
width: var(--mpb-listen-button-size, 128px);
|
|
766
|
+
height: var(--mpb-listen-button-size, 128px);
|
|
703
767
|
border: 0;
|
|
704
768
|
padding: 0;
|
|
705
769
|
background-color: transparent;
|
|
@@ -712,8 +776,8 @@ $effect(() => {
|
|
|
712
776
|
}
|
|
713
777
|
|
|
714
778
|
.listen-feature-icon {
|
|
715
|
-
width: 128px;
|
|
716
|
-
height: 128px;
|
|
779
|
+
width: var(--mpb-listen-button-size, 128px);
|
|
780
|
+
height: var(--mpb-listen-button-size, 128px);
|
|
717
781
|
object-fit: contain;
|
|
718
782
|
display: none;
|
|
719
783
|
}
|
|
@@ -725,7 +789,7 @@ $effect(() => {
|
|
|
725
789
|
.choice-row-horizontal {
|
|
726
790
|
flex-direction: column;
|
|
727
791
|
align-items: center;
|
|
728
|
-
width: min(170px, 30vw);
|
|
792
|
+
width: min(var(--mpb-choice-width-px, 170px), var(--mpb-choice-width-vw, 30vw));
|
|
729
793
|
gap: 0;
|
|
730
794
|
}
|
|
731
795
|
|
|
@@ -735,7 +799,7 @@ $effect(() => {
|
|
|
735
799
|
justify-content: space-between;
|
|
736
800
|
align-items: center;
|
|
737
801
|
width: 100%;
|
|
738
|
-
min-height: 11rem;
|
|
802
|
+
min-height: var(--mpb-choice-tile-min-height, 11rem);
|
|
739
803
|
padding: 0.8rem 0.65rem 0.5rem;
|
|
740
804
|
border-radius: 8px;
|
|
741
805
|
background: transparent;
|
|
@@ -747,88 +811,19 @@ $effect(() => {
|
|
|
747
811
|
display: flex;
|
|
748
812
|
align-items: center;
|
|
749
813
|
justify-content: center;
|
|
750
|
-
min-height: 7.5rem;
|
|
814
|
+
min-height: var(--mpb-choice-content-min-height, 7.5rem);
|
|
751
815
|
}
|
|
752
816
|
|
|
753
817
|
.choice-row-horizontal:hover .choice-tile {
|
|
754
|
-
background: #
|
|
818
|
+
background: #ececec;
|
|
755
819
|
}
|
|
756
820
|
|
|
757
821
|
.choice-row-horizontal.is-selected .choice-tile {
|
|
758
|
-
background: #
|
|
822
|
+
background: #eceabf;
|
|
759
823
|
}
|
|
760
824
|
|
|
761
825
|
.choice-row-horizontal.is-selected:hover .choice-tile {
|
|
762
|
-
background: #
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
.choice-row:not(.choice-row-horizontal):hover {
|
|
766
|
-
background: #f2f2f2;
|
|
767
|
-
border-radius: 6px;
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
.choice-row.is-selected:not(.choice-row-horizontal) {
|
|
771
|
-
background: #fcfcd3;
|
|
772
|
-
border-radius: 6px;
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
:global(.access-contrast-3) .choice-row-horizontal,
|
|
776
|
-
:global(.access-contrast-6) .choice-row-horizontal {
|
|
777
|
-
border-bottom-width: 4px;
|
|
778
|
-
border-bottom-style: solid;
|
|
779
|
-
padding-bottom: 10px;
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
:global(.access-contrast-3) .choice-row:not(.choice-row-horizontal),
|
|
783
|
-
:global(.access-contrast-6) .choice-row:not(.choice-row-horizontal) {
|
|
784
|
-
border-left-width: 4px;
|
|
785
|
-
border-left-style: solid;
|
|
786
|
-
padding-left: 0.35rem;
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
:global(.access-contrast-3) .choice-row-horizontal,
|
|
790
|
-
:global(.access-contrast-3) .choice-row:not(.choice-row-horizontal) {
|
|
791
|
-
border-color: #2d4e84;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
:global(.access-contrast-6) .choice-row-horizontal,
|
|
795
|
-
:global(.access-contrast-6) .choice-row:not(.choice-row-horizontal) {
|
|
796
|
-
border-color: #000;
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
:global(.access-contrast-3) .choice-row:hover,
|
|
800
|
-
:global(.access-contrast-6) .choice-row:hover {
|
|
801
|
-
border-radius: 0;
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
:global(.access-contrast-3) .choice-row:hover {
|
|
805
|
-
border-color: #fff25d;
|
|
806
|
-
color: #fff25d;
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
:global(.access-contrast-6) .choice-row:hover {
|
|
810
|
-
border-color: #fff;
|
|
811
|
-
color: #fff;
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
:global(.access-contrast-3) .choice-row:hover:not(.is-selected):not(.choice-row-horizontal),
|
|
815
|
-
:global(.access-contrast-6) .choice-row:hover:not(.is-selected):not(.choice-row-horizontal) {
|
|
816
|
-
background: inherit;
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
:global(.access-contrast-3) .choice-row-horizontal:hover:not(.is-selected) .choice-tile,
|
|
820
|
-
:global(.access-contrast-6) .choice-row-horizontal:hover:not(.is-selected) .choice-tile {
|
|
821
|
-
background: inherit;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
:global(.access-contrast-3) .choice-row.is-selected:hover,
|
|
825
|
-
:global(.access-contrast-6) .choice-row.is-selected:hover {
|
|
826
|
-
color: #000;
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
:global(.access-contrast-3) .choice-row-horizontal.is-selected:hover .choice-tile,
|
|
830
|
-
:global(.access-contrast-6) .choice-row-horizontal.is-selected:hover .choice-tile {
|
|
831
|
-
background: #fcfcd3;
|
|
826
|
+
background: #eceabf;
|
|
832
827
|
}
|
|
833
828
|
|
|
834
829
|
.choice-row-horizontal :global(p) {
|
|
@@ -841,34 +836,6 @@ $effect(() => {
|
|
|
841
836
|
margin: 0;
|
|
842
837
|
}
|
|
843
838
|
|
|
844
|
-
.teacher-instructions {
|
|
845
|
-
border-left: 4px solid #60a5fa;
|
|
846
|
-
background: #eff6ff;
|
|
847
|
-
padding: 0.5rem 0.75rem;
|
|
848
|
-
border-radius: 4px;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
.teacher-instructions-title {
|
|
852
|
-
margin: 0 0 0.3rem;
|
|
853
|
-
font-size: 0.9rem;
|
|
854
|
-
font-weight: 600;
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
.vic-family-layout {
|
|
858
|
-
margin-left: auto;
|
|
859
|
-
margin-right: auto;
|
|
860
|
-
max-width: 800px;
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
.vic-family-layout .choice-row {
|
|
864
|
-
user-select: none;
|
|
865
|
-
margin-right: 10px;
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
.sel-vic-family-layout {
|
|
869
|
-
font-size: 1.5em;
|
|
870
|
-
}
|
|
871
|
-
|
|
872
839
|
.blank-inner {
|
|
873
840
|
width: 100%;
|
|
874
841
|
display: inline-flex;
|
|
@@ -878,36 +845,44 @@ $effect(() => {
|
|
|
878
845
|
}
|
|
879
846
|
|
|
880
847
|
.choice-radio-bottom {
|
|
881
|
-
margin-top: 0.5rem;
|
|
848
|
+
margin-top: var(--mpb-horizontal-choice-radio-top-margin, 0.5rem);
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
.choice-radio-inline {
|
|
852
|
+
margin-top: var(--mpb-horizontal-choice-radio-top-margin, 0.5rem);
|
|
882
853
|
}
|
|
883
854
|
|
|
884
855
|
.layout-audio_blank_only .audio-container,
|
|
885
856
|
.layout-stimulus_image_blank .audio-container {
|
|
886
857
|
display: flex;
|
|
858
|
+
width: min(100%, var(--mpb-audio-instructions-max-width, 875px));
|
|
859
|
+
margin-left: auto;
|
|
860
|
+
margin-right: auto;
|
|
887
861
|
justify-content: flex-end;
|
|
888
862
|
}
|
|
889
863
|
|
|
890
864
|
.layout-audio_blank_only .template-line,
|
|
891
865
|
.layout-stimulus_image_blank .template-line {
|
|
892
866
|
text-align: center;
|
|
893
|
-
margin: 0.8rem 0
|
|
867
|
+
margin: var(--mpb-audio-blank-template-margin-top, 0.8rem) 0
|
|
868
|
+
var(--mpb-audio-blank-template-margin-bottom, 1.8rem);
|
|
894
869
|
}
|
|
895
870
|
|
|
896
871
|
.layout-audio_blank_only .blank-slot,
|
|
897
872
|
.layout-stimulus_image_blank .blank-slot {
|
|
898
|
-
width: 10rem;
|
|
899
|
-
border-bottom-width: 4px;
|
|
873
|
+
width: var(--mpb-blank-wide-width, 10rem);
|
|
874
|
+
border-bottom-width: var(--mpb-blank-underline-wide-width, 4px);
|
|
900
875
|
}
|
|
901
876
|
|
|
902
877
|
.layout-stimulus_image_blank {
|
|
903
878
|
display: grid;
|
|
904
|
-
grid-template-columns: minmax(210px, 1fr) auto;
|
|
879
|
+
grid-template-columns: minmax(var(--mpb-stimulus-min-column, 210px), 1fr) auto;
|
|
905
880
|
grid-template-areas:
|
|
906
881
|
'sentence audio'
|
|
907
882
|
'. template'
|
|
908
883
|
'choices choices';
|
|
909
|
-
column-gap: 2rem;
|
|
910
|
-
row-gap: 0.7rem;
|
|
884
|
+
column-gap: var(--mpb-stimulus-grid-column-gap, 2rem);
|
|
885
|
+
row-gap: var(--mpb-stimulus-grid-row-gap, 0.7rem);
|
|
911
886
|
align-items: start;
|
|
912
887
|
}
|
|
913
888
|
|
|
@@ -918,7 +893,7 @@ $effect(() => {
|
|
|
918
893
|
|
|
919
894
|
.layout-stimulus_image_blank .sentence-line {
|
|
920
895
|
grid-area: sentence;
|
|
921
|
-
margin: 0.2rem 0 0;
|
|
896
|
+
margin: var(--mpb-stimulus-sentence-margin-top, 0.2rem) 0 0;
|
|
922
897
|
}
|
|
923
898
|
|
|
924
899
|
.layout-stimulus_image_blank .template-line {
|
|
@@ -930,17 +905,17 @@ $effect(() => {
|
|
|
930
905
|
|
|
931
906
|
.layout-stimulus_image_blank fieldset {
|
|
932
907
|
grid-area: choices;
|
|
933
|
-
margin-top: 0.9rem;
|
|
908
|
+
margin-top: var(--mpb-stimulus-choices-margin-top, 0.9rem);
|
|
934
909
|
}
|
|
935
910
|
|
|
936
911
|
.layout-token_sequence {
|
|
937
912
|
display: grid;
|
|
938
|
-
grid-template-columns: minmax(260px, 1fr) auto;
|
|
913
|
+
grid-template-columns: minmax(var(--mpb-text-min-column, 260px), 1fr) auto;
|
|
939
914
|
grid-template-areas:
|
|
940
915
|
'template audio'
|
|
941
916
|
'choices choices';
|
|
942
|
-
column-gap: 1.5rem;
|
|
943
|
-
row-gap: 0.8rem;
|
|
917
|
+
column-gap: var(--mpb-token-grid-column-gap, 1.5rem);
|
|
918
|
+
row-gap: var(--mpb-token-grid-row-gap, 0.8rem);
|
|
944
919
|
align-items: start;
|
|
945
920
|
}
|
|
946
921
|
|
|
@@ -952,34 +927,34 @@ $effect(() => {
|
|
|
952
927
|
|
|
953
928
|
.layout-token_sequence .template-line {
|
|
954
929
|
grid-area: template;
|
|
955
|
-
margin: 0.6rem 0 0;
|
|
930
|
+
margin: var(--mpb-token-template-margin-top, 0.6rem) 0 0;
|
|
956
931
|
justify-self: center;
|
|
957
932
|
text-align: center;
|
|
958
933
|
}
|
|
959
934
|
|
|
960
935
|
.layout-token_sequence .template-line :global(span + span) {
|
|
961
|
-
margin-left: 0.35rem;
|
|
936
|
+
margin-left: var(--mpb-token-inline-token-gap, 0.35rem);
|
|
962
937
|
}
|
|
963
938
|
|
|
964
939
|
.layout-token_sequence .blank-slot {
|
|
965
|
-
width: 7rem;
|
|
966
|
-
border-bottom-width: 4px;
|
|
967
|
-
margin-left: 0.35rem;
|
|
940
|
+
width: var(--mpb-blank-standalone-width, 7rem);
|
|
941
|
+
border-bottom-width: var(--mpb-blank-underline-wide-width, 4px);
|
|
942
|
+
margin-left: var(--mpb-token-inline-token-gap, 0.35rem);
|
|
968
943
|
}
|
|
969
944
|
|
|
970
945
|
.layout-token_sequence fieldset {
|
|
971
946
|
grid-area: choices;
|
|
972
|
-
margin-top: 0.2rem;
|
|
947
|
+
margin-top: var(--mpb-token-choices-margin-top, 0.2rem);
|
|
973
948
|
}
|
|
974
949
|
|
|
975
950
|
.layout-inline_sentence.has-inline-audio {
|
|
976
951
|
display: grid;
|
|
977
|
-
grid-template-columns: minmax(260px, 1fr) auto;
|
|
952
|
+
grid-template-columns: minmax(var(--mpb-text-min-column, 260px), 1fr) auto;
|
|
978
953
|
grid-template-areas:
|
|
979
954
|
'template audio'
|
|
980
955
|
'choices choices';
|
|
981
|
-
column-gap: 1.5rem;
|
|
982
|
-
row-gap: 0.65rem;
|
|
956
|
+
column-gap: var(--mpb-inline-grid-column-gap, 1.5rem);
|
|
957
|
+
row-gap: var(--mpb-inline-grid-row-gap, 0.65rem);
|
|
983
958
|
align-items: start;
|
|
984
959
|
}
|
|
985
960
|
|
|
@@ -991,13 +966,45 @@ $effect(() => {
|
|
|
991
966
|
|
|
992
967
|
.layout-inline_sentence.has-inline-audio .template-line {
|
|
993
968
|
grid-area: template;
|
|
994
|
-
margin: 0.45rem 0 0;
|
|
969
|
+
margin: var(--mpb-inline-template-margin-top, 0.45rem) 0 0;
|
|
995
970
|
text-align: center;
|
|
996
971
|
justify-self: center;
|
|
997
972
|
}
|
|
998
973
|
|
|
999
974
|
.layout-inline_sentence.has-inline-audio fieldset {
|
|
1000
975
|
grid-area: choices;
|
|
1001
|
-
margin-top: 0.25rem;
|
|
976
|
+
margin-top: var(--mpb-inline-choices-margin-top, 0.25rem);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
/* Match Learnosity responsive behavior for CQT audio-blank layouts:
|
|
980
|
+
at smaller widths, audio control shifts left and answer tiles stack. */
|
|
981
|
+
@media (max-width: 760px) {
|
|
982
|
+
.layout-audio_blank_only .audio-container,
|
|
983
|
+
.layout-stimulus_image_blank .audio-container,
|
|
984
|
+
.layout-token_sequence .audio-container,
|
|
985
|
+
.layout-inline_sentence.has-inline-audio .audio-container {
|
|
986
|
+
width: 100%;
|
|
987
|
+
margin-left: 0;
|
|
988
|
+
margin-right: 0;
|
|
989
|
+
justify-content: flex-start;
|
|
990
|
+
justify-self: start;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
.layout-audio_blank_only .pie-choices,
|
|
994
|
+
.layout-token_sequence .pie-choices,
|
|
995
|
+
.layout-stimulus_image_blank .pie-choices,
|
|
996
|
+
.layout-inline_sentence.has-inline-audio .pie-choices {
|
|
997
|
+
flex-direction: column;
|
|
998
|
+
align-items: flex-start;
|
|
999
|
+
justify-content: flex-start;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
.layout-audio_blank_only .choice-row-horizontal,
|
|
1003
|
+
.layout-token_sequence .choice-row-horizontal,
|
|
1004
|
+
.layout-stimulus_image_blank .choice-row-horizontal,
|
|
1005
|
+
.layout-inline_sentence.has-inline-audio .choice-row-horizontal {
|
|
1006
|
+
width: min(100%, var(--mpb-narrow-choice-max-width, 230px));
|
|
1007
|
+
align-items: flex-start;
|
|
1008
|
+
}
|
|
1002
1009
|
}
|
|
1003
1010
|
</style>
|