@pocketprep/ui-kit 3.7.0 → 3.7.2
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/dist/@pocketprep/ui-kit.css +1 -1
- package/dist/@pocketprep/ui-kit.js +6531 -6491
- package/dist/@pocketprep/ui-kit.js.map +1 -1
- package/dist/@pocketprep/ui-kit.umd.cjs +10 -10
- package/dist/@pocketprep/ui-kit.umd.cjs.map +1 -1
- package/lib/components/Quiz/Question/BuildListChoicesContainer.vue +126 -54
- package/lib/components/Quiz/Question/MPMCChoicesContainer.vue +4 -5
- package/lib/components/Quiz/Question/MPMCRadioGroup.vue +16 -0
- package/lib/components/Quiz/Question/QuestionContext.vue +27 -2
- package/lib/components/Quiz/Question/Summary.vue +6 -6
- package/lib/components/Quiz/Question.vue +44 -13
- package/package.json +1 -1
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
{{ announcementMessage }}
|
|
13
13
|
</div>
|
|
14
14
|
<div
|
|
15
|
-
v-breakpoint="breakpointsWithEl"
|
|
16
15
|
class="uikit-question-build-list-choices-container-wrapper"
|
|
17
16
|
>
|
|
18
17
|
<TransitionGroup
|
|
18
|
+
v-dark="isDarkMode"
|
|
19
19
|
v-breakpoint="breakpointsWithEl"
|
|
20
20
|
name="list"
|
|
21
21
|
tag="ol"
|
|
@@ -27,9 +27,10 @@
|
|
|
27
27
|
(showBuildListOrder || reviewMode) && !isBuildListOrderCorrect,
|
|
28
28
|
'uikit-question-build-list-choices-container--teach-group-review':
|
|
29
29
|
(showBuildListOrder || reviewMode) && isTeachGroupReview,
|
|
30
|
+
'uikit-question-build-list-choices-container--review-mode': reviewMode,
|
|
30
31
|
}"
|
|
31
32
|
role="list"
|
|
32
|
-
:aria-label="`
|
|
33
|
+
:aria-label="`List with ${orderedChoices.length} items`"
|
|
33
34
|
>
|
|
34
35
|
<li
|
|
35
36
|
v-for="(choice, index) in orderedChoices"
|
|
@@ -46,6 +47,9 @@
|
|
|
46
47
|
v-dark="isDarkMode"
|
|
47
48
|
v-breakpoint="breakpointsWithEl"
|
|
48
49
|
class="uikit-question-build-list-choices-container__choice-number"
|
|
50
|
+
:class="{
|
|
51
|
+
'uikit-question-build-list-choices-container__choice-number--review-mode': reviewMode
|
|
52
|
+
}"
|
|
49
53
|
>
|
|
50
54
|
{{ index + 1 }}
|
|
51
55
|
</div>
|
|
@@ -54,14 +58,13 @@
|
|
|
54
58
|
v-breakpoint="breakpointsWithEl"
|
|
55
59
|
class="uikit-question-build-list-choices-container__choice"
|
|
56
60
|
:class="{
|
|
57
|
-
'uikit-question-build-list-choices-container__choice--
|
|
58
|
-
reviewMode || showBuildListOrder
|
|
61
|
+
'uikit-question-build-list-choices-container__choice--review-mode': reviewMode
|
|
59
62
|
}"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
@
|
|
64
|
-
@
|
|
63
|
+
:tabindex="-1"
|
|
64
|
+
@keydown.enter.stop="handleCardKeydown($event, index)"
|
|
65
|
+
@keydown.space.stop="handleCardKeydown($event, index)"
|
|
66
|
+
@click.prevent
|
|
67
|
+
@mousedown.prevent
|
|
65
68
|
:ref="(el) => setCardRef(el, choice.key)"
|
|
66
69
|
>
|
|
67
70
|
<div
|
|
@@ -72,7 +75,9 @@
|
|
|
72
75
|
'uikit-question-build-list-choices-container__mobile-choice-number--correct':
|
|
73
76
|
(reviewMode || showBuildListOrder) && isChoiceInCorrectPosition(choice, index),
|
|
74
77
|
'uikit-question-build-list-choices-container__mobile-choice-number--incorrect':
|
|
75
|
-
(reviewMode || showBuildListOrder) && !isChoiceInCorrectPosition(choice, index)
|
|
78
|
+
(reviewMode || showBuildListOrder) && !isChoiceInCorrectPosition(choice, index),
|
|
79
|
+
'uikit-question-build-list-choices-container__mobile-choice-number--review-mode':
|
|
80
|
+
reviewMode,
|
|
76
81
|
}"
|
|
77
82
|
>
|
|
78
83
|
{{ index + 1 }}
|
|
@@ -92,7 +97,7 @@
|
|
|
92
97
|
{{ getCorrectPositionOrderNumber(choice) }}
|
|
93
98
|
</div>
|
|
94
99
|
<Icon
|
|
95
|
-
v-if="isChoiceInCorrectPosition(choice, index)"
|
|
100
|
+
v-if="isChoiceInCorrectPosition(choice, index) && !reviewMode"
|
|
96
101
|
v-dark="isDarkMode"
|
|
97
102
|
v-breakpoint="breakpointsWithEl"
|
|
98
103
|
class="uikit-question-build-list-choices-container__answer-correct-icon"
|
|
@@ -100,7 +105,7 @@
|
|
|
100
105
|
|
|
101
106
|
/>
|
|
102
107
|
<Icon
|
|
103
|
-
v-else
|
|
108
|
+
v-else-if="!isChoiceInCorrectPosition(choice, index) && !reviewMode"
|
|
104
109
|
v-dark="isDarkMode"
|
|
105
110
|
v-breakpoint="breakpointsWithEl"
|
|
106
111
|
class="uikit-question-build-list-choices-container__answer-incorrect-icon"
|
|
@@ -119,7 +124,8 @@
|
|
|
119
124
|
index === 0
|
|
120
125
|
}"
|
|
121
126
|
:disabled="index === 0"
|
|
122
|
-
|
|
127
|
+
:tabindex="buttonsAreFocusable && index !== 0 ? 0 : -1"
|
|
128
|
+
@click.prevent.stop="moveChoiceUp(index)"
|
|
123
129
|
:aria-label="`Move '${stripHtmlTags(choice.text || '')}' up`"
|
|
124
130
|
:title="'Move up'"
|
|
125
131
|
>
|
|
@@ -138,7 +144,8 @@
|
|
|
138
144
|
index === orderedChoices.length - 1
|
|
139
145
|
}"
|
|
140
146
|
:disabled="index === orderedChoices.length - 1"
|
|
141
|
-
|
|
147
|
+
:tabindex="buttonsAreFocusable && index !== orderedChoices.length - 1 ? 0 : -1"
|
|
148
|
+
@click.prevent.stop="moveChoiceDown(index)"
|
|
142
149
|
:aria-label="`Move '${stripHtmlTags(choice.text || '')}' down`"
|
|
143
150
|
:title="'Move down'"
|
|
144
151
|
>
|
|
@@ -158,7 +165,7 @@
|
|
|
158
165
|
</template>
|
|
159
166
|
|
|
160
167
|
<script setup lang="ts">
|
|
161
|
-
import { ref, watch, onMounted, type ComponentPublicInstance } from 'vue'
|
|
168
|
+
import { ref, watch, onMounted, computed, type ComponentPublicInstance } from 'vue'
|
|
162
169
|
import Icon from '../../Icons/Icon.vue'
|
|
163
170
|
import { dark as vDark, breakpoint as vBreakpoint } from '../../../directives'
|
|
164
171
|
import { useQuestionContext } from './composables'
|
|
@@ -187,6 +194,11 @@ const orderedChoices = ref<TBuildListChoice[]>([])
|
|
|
187
194
|
const floatingChoiceKey = ref<string | null>(null)
|
|
188
195
|
const choiceRefs = ref<Map<string, HTMLDivElement>>(new Map())
|
|
189
196
|
const announcementMessage = ref<string>('')
|
|
197
|
+
const isMoveTriggeredByArrowKey = ref<boolean>(false)
|
|
198
|
+
|
|
199
|
+
const buttonsAreFocusable = computed(() => {
|
|
200
|
+
return !showBuildListOrder.value && !reviewMode.value
|
|
201
|
+
})
|
|
190
202
|
|
|
191
203
|
onMounted(() => {
|
|
192
204
|
updateOrderedChoices()
|
|
@@ -230,11 +242,37 @@ const restoreFocusAfterMove = (movedChoiceKey: string) => {
|
|
|
230
242
|
setTimeout(() => {
|
|
231
243
|
const choiceEl = choiceRefs.value.get(movedChoiceKey)
|
|
232
244
|
if (choiceEl) {
|
|
245
|
+
// Temporarily make the choice focusable for animation
|
|
246
|
+
choiceEl.setAttribute('tabindex', '0')
|
|
233
247
|
choiceEl.focus()
|
|
248
|
+
|
|
249
|
+
// Remove tabindex after animation completes
|
|
250
|
+
const animationDelay = prefersReducedMotion() ? 0 : 350
|
|
251
|
+
setTimeout(() => {
|
|
252
|
+
choiceEl.setAttribute('tabindex', '-1')
|
|
253
|
+
}, animationDelay)
|
|
234
254
|
}
|
|
235
255
|
}, delay)
|
|
236
256
|
}
|
|
237
257
|
|
|
258
|
+
const removeFocusAfterAnimation = (movedChoiceKey: string) => {
|
|
259
|
+
// Don't remove focus if we're in review mode or showing the build list order
|
|
260
|
+
if (showBuildListOrder.value || reviewMode.value) {
|
|
261
|
+
return
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Only remove focus if the move was NOT triggered by arrow keys
|
|
265
|
+
if (!isMoveTriggeredByArrowKey.value) {
|
|
266
|
+
const animationDelay = prefersReducedMotion() ? 0 : 350 // Slightly after animation completes
|
|
267
|
+
setTimeout(() => {
|
|
268
|
+
const choiceEl = choiceRefs.value.get(movedChoiceKey)
|
|
269
|
+
if (choiceEl) {
|
|
270
|
+
choiceEl.blur()
|
|
271
|
+
}
|
|
272
|
+
}, animationDelay)
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
238
276
|
// For accessibility, we want to announce to the user where they moved the choice
|
|
239
277
|
// to in the ordered list. ie: “Moved Photosynthesis to position 2 of 6.”
|
|
240
278
|
const announceMove = (choiceText: string, newPosition: number, totalItems: number) => {
|
|
@@ -268,6 +306,9 @@ const moveChoiceUp = (index: number) => {
|
|
|
268
306
|
// Restore focus to the moved card
|
|
269
307
|
restoreFocusAfterMove(currentItem.key)
|
|
270
308
|
|
|
309
|
+
// Remove focus after animation if not triggered by arrow key
|
|
310
|
+
removeFocusAfterAnimation(currentItem.key)
|
|
311
|
+
|
|
271
312
|
// Clear floating state after animation completes
|
|
272
313
|
const animationDelay = prefersReducedMotion() ? 0 : 300
|
|
273
314
|
setTimeout(() => {
|
|
@@ -298,6 +339,9 @@ const moveChoiceDown = (index: number) => {
|
|
|
298
339
|
// Restore focus to the moved card
|
|
299
340
|
restoreFocusAfterMove(currentItem.key)
|
|
300
341
|
|
|
342
|
+
// Remove focus after animation
|
|
343
|
+
removeFocusAfterAnimation(currentItem.key)
|
|
344
|
+
|
|
301
345
|
// Clear floating state after animation completes
|
|
302
346
|
const animationDelay = prefersReducedMotion() ? 0 : 300
|
|
303
347
|
setTimeout(() => {
|
|
@@ -321,32 +365,39 @@ const isChoiceInCorrectPosition = (choice: TBuildListChoice, currentIndex: numbe
|
|
|
321
365
|
return correctOrderPosition === currentOrderPosition
|
|
322
366
|
}
|
|
323
367
|
|
|
324
|
-
const handleCardClick = (event: MouseEvent) => {
|
|
325
|
-
if (showBuildListOrder.value || reviewMode.value) {
|
|
326
|
-
event.preventDefault()
|
|
327
|
-
event.stopPropagation()
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
368
|
const handleCardKeydown = (event: KeyboardEvent, index: number) => {
|
|
332
369
|
// Handle Alt+Arrow shortcuts for moving cards
|
|
333
370
|
if (event.altKey) {
|
|
334
371
|
if (event.key === 'ArrowUp' || event.key === 'Up') {
|
|
335
372
|
event.preventDefault()
|
|
373
|
+
isMoveTriggeredByArrowKey.value = true
|
|
336
374
|
moveChoiceUp(index)
|
|
375
|
+
// Reset flag after a short delay
|
|
376
|
+
setTimeout(() => {
|
|
377
|
+
isMoveTriggeredByArrowKey.value = false
|
|
378
|
+
}, 100)
|
|
337
379
|
} else if (event.key === 'ArrowDown' || event.key === 'Down') {
|
|
338
380
|
event.preventDefault()
|
|
381
|
+
isMoveTriggeredByArrowKey.value = true
|
|
339
382
|
moveChoiceDown(index)
|
|
383
|
+
// Reset flag after a short delay
|
|
384
|
+
setTimeout(() => {
|
|
385
|
+
isMoveTriggeredByArrowKey.value = false
|
|
386
|
+
}, 100)
|
|
340
387
|
}
|
|
341
388
|
}
|
|
342
389
|
}
|
|
343
390
|
|
|
344
|
-
|
|
345
391
|
watch(orderedChoices, () => {
|
|
346
392
|
const newChoices = orderedChoices.value
|
|
347
393
|
emit('reorderBuildList', newChoices)
|
|
348
394
|
}, { deep: true })
|
|
349
395
|
|
|
396
|
+
watch(selectedBuildListChoiceOrder, () => {
|
|
397
|
+
if ((reviewMode.value || showBuildListOrder.value)) {
|
|
398
|
+
updateOrderedChoices()
|
|
399
|
+
}
|
|
400
|
+
})
|
|
350
401
|
</script>
|
|
351
402
|
|
|
352
403
|
<style lang="scss">
|
|
@@ -378,22 +429,23 @@ watch(orderedChoices, () => {
|
|
|
378
429
|
flex-direction: column;
|
|
379
430
|
gap: 12px;
|
|
380
431
|
list-style: none;
|
|
381
|
-
margin: 0;
|
|
432
|
+
margin: 0 0 0 -46px;
|
|
382
433
|
padding: 0;
|
|
383
434
|
|
|
384
435
|
&::after {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
436
|
+
content: '';
|
|
437
|
+
position: absolute;
|
|
438
|
+
top: -8px;
|
|
439
|
+
bottom: -8px;
|
|
440
|
+
left: 8px;
|
|
441
|
+
right: 10px;
|
|
442
|
+
border-radius: 11px;
|
|
443
|
+
pointer-events: none;
|
|
393
444
|
|
|
394
|
-
|
|
445
|
+
}
|
|
395
446
|
|
|
396
447
|
&--mobile {
|
|
448
|
+
margin: 0;
|
|
397
449
|
&::after {
|
|
398
450
|
content: '';
|
|
399
451
|
position: absolute;
|
|
@@ -407,6 +459,17 @@ watch(orderedChoices, () => {
|
|
|
407
459
|
}
|
|
408
460
|
}
|
|
409
461
|
|
|
462
|
+
&--review-mode:not(&--mobile) {
|
|
463
|
+
margin: 0;
|
|
464
|
+
max-width: 492px;
|
|
465
|
+
width: 100%;
|
|
466
|
+
|
|
467
|
+
&::after {
|
|
468
|
+
left: -8px;
|
|
469
|
+
right: -8px;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
410
473
|
&--correct {
|
|
411
474
|
&::after {
|
|
412
475
|
display: block;
|
|
@@ -450,8 +513,12 @@ watch(orderedChoices, () => {
|
|
|
450
513
|
z-index: 10;
|
|
451
514
|
|
|
452
515
|
.uikit-question-build-list-choices-container__choice {
|
|
453
|
-
|
|
454
|
-
|
|
516
|
+
outline: 2px solid $brand-blue;
|
|
517
|
+
outline-offset: 2px;
|
|
518
|
+
|
|
519
|
+
&--dark {
|
|
520
|
+
outline-color: $banana-bread;
|
|
521
|
+
}
|
|
455
522
|
}
|
|
456
523
|
}
|
|
457
524
|
}
|
|
@@ -459,7 +526,7 @@ watch(orderedChoices, () => {
|
|
|
459
526
|
&__choice-number,
|
|
460
527
|
&__mobile-choice-number {
|
|
461
528
|
display: flex;
|
|
462
|
-
align-items:
|
|
529
|
+
align-items: flex-end;
|
|
463
530
|
justify-content: center;
|
|
464
531
|
width: 24px;
|
|
465
532
|
height: 24px;
|
|
@@ -477,13 +544,14 @@ watch(orderedChoices, () => {
|
|
|
477
544
|
}
|
|
478
545
|
|
|
479
546
|
&__choice-number {
|
|
547
|
+
&--review-mode,
|
|
480
548
|
&--mobile {
|
|
481
549
|
display: none;
|
|
482
550
|
}
|
|
483
551
|
}
|
|
484
552
|
|
|
485
553
|
&__mobile-choice-number {
|
|
486
|
-
&:not(&--mobile) {
|
|
554
|
+
&:not(&--mobile, &--review-mode) {
|
|
487
555
|
display: none;
|
|
488
556
|
}
|
|
489
557
|
|
|
@@ -524,28 +592,15 @@ watch(orderedChoices, () => {
|
|
|
524
592
|
box-shadow: 0 1px 4px 0 rgba(71, 89, 103, 0.30);
|
|
525
593
|
outline: none;
|
|
526
594
|
|
|
527
|
-
&:focus:not(&--showing-answer) {
|
|
528
|
-
outline: 2px solid $brand-blue;
|
|
529
|
-
outline-offset: 2px;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
595
|
&--dark {
|
|
533
596
|
border: 1px solid $slate;
|
|
534
597
|
background-color: $brand-black;
|
|
535
598
|
box-shadow: 0 1px 4px 0 rgba(71, 89, 103, 0.30);
|
|
536
|
-
|
|
537
|
-
&:focus:not(&--showing-answer) {
|
|
538
|
-
outline-color: $banana-bread;
|
|
539
|
-
}
|
|
540
599
|
}
|
|
541
600
|
|
|
542
601
|
&--mobile {
|
|
543
602
|
width: 100%;
|
|
544
603
|
}
|
|
545
|
-
|
|
546
|
-
&--showing-answer {
|
|
547
|
-
gap: 27px;
|
|
548
|
-
}
|
|
549
604
|
}
|
|
550
605
|
|
|
551
606
|
&__choice-text {
|
|
@@ -589,9 +644,30 @@ watch(orderedChoices, () => {
|
|
|
589
644
|
cursor: pointer;
|
|
590
645
|
transition: all 0.2s ease;
|
|
591
646
|
|
|
647
|
+
&:focus {
|
|
648
|
+
outline: none;
|
|
649
|
+
border: 2px solid $white;
|
|
650
|
+
box-shadow: 0 0 0 2px $brand-blue-hover;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
&:hover,
|
|
654
|
+
&:focus {
|
|
655
|
+
background-color: $brand-blue-hover;
|
|
656
|
+
}
|
|
657
|
+
|
|
592
658
|
&--dark {
|
|
593
659
|
background-color: $banana-bread;
|
|
594
660
|
color: $brand-black;
|
|
661
|
+
|
|
662
|
+
&:focus {
|
|
663
|
+
border: 2px solid $brand-black;
|
|
664
|
+
box-shadow: 0 0 0 2px $butterscotch;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
&:hover,
|
|
668
|
+
&:focus {
|
|
669
|
+
background-color: $butterscotch;
|
|
670
|
+
}
|
|
595
671
|
}
|
|
596
672
|
|
|
597
673
|
&--disabled {
|
|
@@ -663,12 +739,10 @@ watch(orderedChoices, () => {
|
|
|
663
739
|
|
|
664
740
|
// TransitionGroup animations
|
|
665
741
|
.list-move,
|
|
666
|
-
.list-enter-active,
|
|
667
742
|
.list-leave-active {
|
|
668
743
|
transition: all 0.2s ease;
|
|
669
744
|
}
|
|
670
745
|
|
|
671
|
-
.list-enter-from,
|
|
672
746
|
.list-leave-to {
|
|
673
747
|
opacity: 0;
|
|
674
748
|
transform: translateX(30px);
|
|
@@ -682,12 +756,10 @@ watch(orderedChoices, () => {
|
|
|
682
756
|
// Respect prefers-reduced-motion
|
|
683
757
|
@media (prefers-reduced-motion: reduce) {
|
|
684
758
|
.list-move,
|
|
685
|
-
.list-enter-active,
|
|
686
759
|
.list-leave-active {
|
|
687
760
|
transition: none;
|
|
688
761
|
}
|
|
689
762
|
|
|
690
|
-
.list-enter-from,
|
|
691
763
|
.list-leave-to {
|
|
692
764
|
opacity: 1;
|
|
693
765
|
transform: none;
|
|
@@ -38,9 +38,7 @@ const mpmcLabels = computed(() => {
|
|
|
38
38
|
|
|
39
39
|
const questionChoices = computed(() => {
|
|
40
40
|
const choices = question.value.choices
|
|
41
|
-
|
|
42
|
-
// Shuffle mpmc choices
|
|
43
|
-
return [ ...choices ].sort(() => Math.random() - 0.5)
|
|
41
|
+
return choices
|
|
44
42
|
})
|
|
45
43
|
|
|
46
44
|
const choiceKeysByLabelIndexObj = computed(() => {
|
|
@@ -235,8 +233,9 @@ watch(selectedMPMCChoices, () => {
|
|
|
235
233
|
:aria-label="
|
|
236
234
|
`${stripHtmlTags(label)}. ${expandedPartNumbers.includes(labelIndex) ? 'Expanded' : 'Collapsed'}.`
|
|
237
235
|
"
|
|
238
|
-
@keydown.enter="openChoiceDropdown(labelIndex)"
|
|
239
|
-
@keydown.space.
|
|
236
|
+
@keydown.enter.stop="openChoiceDropdown(labelIndex)"
|
|
237
|
+
@keydown.space.stop="openChoiceDropdown(labelIndex)"
|
|
238
|
+
@mousedown.prevent
|
|
240
239
|
>
|
|
241
240
|
<div
|
|
242
241
|
class="uikit-question-mpmc-choices-container__part"
|
|
@@ -25,6 +25,10 @@ const selectedChoice = defineModel<TChoiceKey | null>({ default: null })
|
|
|
25
25
|
|
|
26
26
|
const selectChoice = (choiceKey: TChoiceKey) => {
|
|
27
27
|
selectedChoice.value = choiceKey
|
|
28
|
+
// Remove focus from the choice after selecting a choice
|
|
29
|
+
if (document.activeElement instanceof HTMLElement) {
|
|
30
|
+
document.activeElement.blur()
|
|
31
|
+
}
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
const radioButtonColor = (choice: TChoiceKey) => {
|
|
@@ -130,16 +134,28 @@ const radioButtonColor = (choice: TChoiceKey) => {
|
|
|
130
134
|
outline: none;
|
|
131
135
|
transition: background-color 0.2s ease;
|
|
132
136
|
|
|
137
|
+
&:last-child {
|
|
138
|
+
border-radius: 0 0 5px 5px;
|
|
139
|
+
}
|
|
140
|
+
|
|
133
141
|
&:not(&--show-answer) {
|
|
134
142
|
&:focus {
|
|
135
143
|
border: 0.5px solid $brand-blue;
|
|
136
144
|
}
|
|
145
|
+
|
|
146
|
+
&:hover {
|
|
147
|
+
background: $fog;
|
|
148
|
+
}
|
|
137
149
|
}
|
|
138
150
|
|
|
139
151
|
&--dark {
|
|
140
152
|
&:focus:not(.uikit-mpmc-radio-group__option--show-answer) {
|
|
141
153
|
border: 0.5px solid $banana-bread;
|
|
142
154
|
}
|
|
155
|
+
|
|
156
|
+
&:hover:not(.uikit-mpmc-radio-group__option--show-answer) {
|
|
157
|
+
background-color: $moonlit-ocean;
|
|
158
|
+
}
|
|
143
159
|
}
|
|
144
160
|
}
|
|
145
161
|
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
? ` of ${quizLength}`
|
|
31
31
|
: ''
|
|
32
32
|
}${
|
|
33
|
-
(showAnswers || showMatrixAnswers)
|
|
34
|
-
?
|
|
33
|
+
(showAnswers || showMatrixAnswers || showBuildListOrder || showMPMCAnswers)
|
|
34
|
+
? isCorrectlyAnswered
|
|
35
35
|
? ', Answered Correctly'
|
|
36
36
|
: ', Answered Incorrectly'
|
|
37
37
|
: ''
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
import Icon from '../../Icons/Icon.vue'
|
|
63
63
|
import { dark as vDark, breakpoint as vBreakpoint } from '../../../directives'
|
|
64
64
|
import { useQuestionContext } from './composables'
|
|
65
|
+
import { computed } from 'vue'
|
|
65
66
|
|
|
66
67
|
const {
|
|
67
68
|
// questionEl is used by the breakpoint directive
|
|
@@ -72,15 +73,39 @@ const {
|
|
|
72
73
|
questionNumber,
|
|
73
74
|
isDarkMode,
|
|
74
75
|
isCorrect,
|
|
76
|
+
isBuildListQuestion,
|
|
77
|
+
isMatrixQuestion,
|
|
78
|
+
isMPMCQuestion,
|
|
79
|
+
isBuildListOrderCorrect,
|
|
80
|
+
isMatrixQuestionCorrect,
|
|
81
|
+
isMPMCQuestionCorrect,
|
|
75
82
|
contextIconType,
|
|
76
83
|
showAnswers,
|
|
84
|
+
showBuildListOrder,
|
|
77
85
|
showMatrixAnswers,
|
|
86
|
+
showMPMCAnswers,
|
|
78
87
|
} = useQuestionContext()
|
|
79
88
|
|
|
80
89
|
defineExpose({
|
|
81
90
|
questionEl,
|
|
82
91
|
})
|
|
83
92
|
|
|
93
|
+
const isCorrectlyAnswered = computed(() => {
|
|
94
|
+
if (isMatrixQuestion.value) {
|
|
95
|
+
return isMatrixQuestionCorrect.value
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (isBuildListQuestion) {
|
|
99
|
+
return isBuildListOrderCorrect.value
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (isMPMCQuestion.value) {
|
|
103
|
+
return isMPMCQuestionCorrect.value
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return isCorrect.value
|
|
107
|
+
})
|
|
108
|
+
|
|
84
109
|
</script>
|
|
85
110
|
|
|
86
111
|
<style lang="scss">
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
'uikit-question-summary--matrix-question-review-mode': isMatrixQuestion && reviewMode,
|
|
10
10
|
'uikit-question-summary--mpmc-question': isMPMCQuestion,
|
|
11
11
|
'uikit-question-summary--mpmc-question-review-mode': isMPMCQuestion && reviewMode,
|
|
12
|
-
'uikit-question-summary--build-list-question':
|
|
13
|
-
|
|
12
|
+
'uikit-question-summary--build-list-question-not-review-mode':
|
|
13
|
+
isBuildListQuestion && !reviewMode,
|
|
14
14
|
}"
|
|
15
15
|
>
|
|
16
16
|
<div class="uikit-question-summary__summary-title">
|
|
@@ -218,10 +218,9 @@ const toggleSummaryExplanationImageLongAlt = () => {
|
|
|
218
218
|
max-width: 518px;
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
&--build-list-question {
|
|
222
|
-
max-width:
|
|
223
|
-
margin-left:
|
|
224
|
-
display: inline-block;
|
|
221
|
+
&--build-list-question-not-review-mode {
|
|
222
|
+
max-width: 450px;
|
|
223
|
+
margin-left: -4px
|
|
225
224
|
}
|
|
226
225
|
|
|
227
226
|
&--matrix-question-review-mode#{&}--tablet-landscape,
|
|
@@ -231,6 +230,7 @@ const toggleSummaryExplanationImageLongAlt = () => {
|
|
|
231
230
|
|
|
232
231
|
&--mpmc-question {
|
|
233
232
|
max-width: 492px;
|
|
233
|
+
margin-left: 4px;
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
&--tablet-portrait {
|
|
@@ -374,7 +374,6 @@
|
|
|
374
374
|
>
|
|
375
375
|
Check Answer
|
|
376
376
|
</PocketButton>
|
|
377
|
-
|
|
378
377
|
<PocketButton
|
|
379
378
|
v-else-if="(
|
|
380
379
|
showAnswers
|
|
@@ -988,37 +987,61 @@ const prompt = computed(() => {
|
|
|
988
987
|
})
|
|
989
988
|
})
|
|
990
989
|
|
|
990
|
+
const isTEIsQuestionType = computed(() => {
|
|
991
|
+
return isMPMCQuestion.value || isMatrixQuestion.value || isBuildListQuestion.value
|
|
992
|
+
})
|
|
993
|
+
|
|
991
994
|
const keydownListener = (e: KeyboardEvent) => {
|
|
992
995
|
switch (e.code) {
|
|
993
996
|
case 'KeyA':
|
|
994
|
-
|
|
997
|
+
if (!isTEIsQuestionType.value) {
|
|
998
|
+
choices.value[0] && selectChoice(choices.value[0].key, true)
|
|
999
|
+
}
|
|
995
1000
|
break
|
|
996
1001
|
case 'KeyB':
|
|
997
|
-
|
|
1002
|
+
if (!isTEIsQuestionType.value) {
|
|
1003
|
+
choices.value[1] && selectChoice(choices.value[1].key, true)
|
|
1004
|
+
}
|
|
998
1005
|
break
|
|
999
1006
|
case 'KeyC':
|
|
1000
|
-
|
|
1007
|
+
if (!isTEIsQuestionType.value) {
|
|
1008
|
+
choices.value[2] && selectChoice(choices.value[2].key, true)
|
|
1009
|
+
}
|
|
1001
1010
|
break
|
|
1002
1011
|
case 'KeyD':
|
|
1003
|
-
|
|
1012
|
+
if (!isTEIsQuestionType.value) {
|
|
1013
|
+
choices.value[3] && selectChoice(choices.value[3].key, true)
|
|
1014
|
+
}
|
|
1004
1015
|
break
|
|
1005
1016
|
case 'KeyE':
|
|
1006
|
-
|
|
1017
|
+
if (!isTEIsQuestionType.value) {
|
|
1018
|
+
choices.value[4] && selectChoice(choices.value[4].key, true)
|
|
1019
|
+
}
|
|
1007
1020
|
break
|
|
1008
1021
|
case 'KeyF':
|
|
1009
|
-
|
|
1022
|
+
if (!isTEIsQuestionType.value) {
|
|
1023
|
+
choices.value[5] && selectChoice(choices.value[5].key, true)
|
|
1024
|
+
}
|
|
1010
1025
|
break
|
|
1011
1026
|
case 'KeyG':
|
|
1012
|
-
|
|
1027
|
+
if (!isTEIsQuestionType.value) {
|
|
1028
|
+
choices.value[6] && selectChoice(choices.value[6].key, true)
|
|
1029
|
+
}
|
|
1013
1030
|
break
|
|
1014
1031
|
case 'KeyH':
|
|
1015
|
-
|
|
1032
|
+
if (!isTEIsQuestionType.value) {
|
|
1033
|
+
choices.value[7] && selectChoice(choices.value[7].key, true)
|
|
1034
|
+
}
|
|
1016
1035
|
break
|
|
1017
1036
|
case 'KeyI':
|
|
1018
|
-
|
|
1037
|
+
if (!isTEIsQuestionType.value) {
|
|
1038
|
+
choices.value[8] && selectChoice(choices.value[8].key, true)
|
|
1039
|
+
}
|
|
1019
1040
|
break
|
|
1020
1041
|
case 'KeyJ':
|
|
1021
|
-
|
|
1042
|
+
if (!isTEIsQuestionType.value) {
|
|
1043
|
+
choices.value[9] && selectChoice(choices.value[9].key, true)
|
|
1044
|
+
}
|
|
1022
1045
|
break
|
|
1023
1046
|
case 'KeyX':
|
|
1024
1047
|
showAnswers.value && toggleExplanation()
|
|
@@ -1028,7 +1051,12 @@ const keydownListener = (e: KeyboardEvent) => {
|
|
|
1028
1051
|
e.preventDefault()
|
|
1029
1052
|
break
|
|
1030
1053
|
case 'Enter':
|
|
1031
|
-
if (
|
|
1054
|
+
if (
|
|
1055
|
+
!showAnswers.value
|
|
1056
|
+
&& selectedChoices.value.length
|
|
1057
|
+
&& focusChoiceKey.value === null
|
|
1058
|
+
&& !isTEIsQuestionType.value
|
|
1059
|
+
) {
|
|
1032
1060
|
clickCheckAnswer()
|
|
1033
1061
|
e.preventDefault()
|
|
1034
1062
|
}
|
|
@@ -1596,7 +1624,10 @@ onMounted(() => {
|
|
|
1596
1624
|
showBuildListOrder.value = props.initialShowAnswers
|
|
1597
1625
|
}
|
|
1598
1626
|
|
|
1599
|
-
if (
|
|
1627
|
+
if (
|
|
1628
|
+
props.allowKeyboardShortcuts
|
|
1629
|
+
&& !isMPMCQuestion.value
|
|
1630
|
+
) {
|
|
1600
1631
|
window.addEventListener('keydown', keydownListener)
|
|
1601
1632
|
}
|
|
1602
1633
|
|