@pocketprep/ui-kit 3.4.89 → 3.5.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 (28) hide show
  1. package/dist/@pocketprep/ui-kit.js +14834 -16036
  2. package/dist/@pocketprep/ui-kit.js.map +1 -1
  3. package/dist/@pocketprep/ui-kit.umd.cjs +12 -12
  4. package/dist/@pocketprep/ui-kit.umd.cjs.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/lib/components/Bundles/BundleSearch.vue +41 -11
  7. package/lib/components/Pagination/QuestionReviewPagination.vue +21 -19
  8. package/lib/components/Quiz/Question/ChoicesContainer.vue +95 -129
  9. package/lib/components/Quiz/Question/DropdownExplanation.vue +39 -53
  10. package/lib/components/Quiz/Question/Explanation.vue +47 -57
  11. package/lib/components/Quiz/Question/MatrixChoicesContainer.vue +211 -224
  12. package/lib/components/Quiz/Question/MatrixRadioGroup.vue +5 -4
  13. package/lib/components/Quiz/Question/MobileMatrixChoicesContainer.vue +321 -319
  14. package/lib/components/Quiz/Question/MobileMatrixRadioGroup.vue +7 -6
  15. package/lib/components/Quiz/Question/PassageAndImage.vue +32 -43
  16. package/lib/components/Quiz/Question/PassageAndImageDropdown.vue +32 -43
  17. package/lib/components/Quiz/Question/Paywall.vue +28 -39
  18. package/lib/components/Quiz/Question/QuestionContext.vue +23 -31
  19. package/lib/components/Quiz/Question/StatsSummary.vue +10 -20
  20. package/lib/components/Quiz/Question/Summary.vue +54 -64
  21. package/lib/components/Quiz/Question/composables.ts +71 -0
  22. package/lib/components/Quiz/Question/injectionSymbols.ts +69 -0
  23. package/lib/components/Quiz/Question.vue +788 -988
  24. package/lib/components/Quiz/QuizContainer.vue +36 -34
  25. package/lib/components/Quiz/question.d.ts +4 -4
  26. package/lib/directives.ts +27 -22
  27. package/lib/styles/_breakpoints.scss +6 -12
  28. package/package.json +4 -4
@@ -1,13 +1,16 @@
1
1
  <template>
2
2
  <div
3
3
  ref="uikit-exam-search"
4
- v-breakpoint="{ small: smallBreakpoint }"
4
+ v-breakpoint="{ breakpoints: { small: smallBreakpoint } }"
5
5
  class="uikit-exam-search"
6
6
  :class="{ 'uikit-exam-search--bundle-selected': selectedBundle }"
7
7
  >
8
8
  <Search
9
9
  v-model="examSearchString"
10
- v-breakpoint:examSearchContainer="{ small: smallBreakpoint }"
10
+ v-breakpoint="{
11
+ breakpoints: { small: smallBreakpoint },
12
+ containerEl: examSearchContainer
13
+ }"
11
14
  class="uikit-exam-search__search"
12
15
  placeholder="Search exams"
13
16
  type="white"
@@ -15,7 +18,10 @@
15
18
  />
16
19
  <div
17
20
  v-if="examSearchString"
18
- v-breakpoint:examSearchContainer="{ small: smallBreakpoint }"
21
+ v-breakpoint="{
22
+ breakpoints: { small: smallBreakpoint },
23
+ containerEl: examSearchContainer
24
+ }"
19
25
  class="uikit-exam-search__search-results"
20
26
  >
21
27
  <div class="uikit-exam-search__search-results-header">
@@ -40,7 +46,10 @@
40
46
  <ExamCard
41
47
  v-for="exam in filteredExams"
42
48
  :key="exam.objectId"
43
- v-breakpoint:examSearchContainer="{ small: smallBreakpoint }"
49
+ v-breakpoint="{
50
+ breakpoints: { small: smallBreakpoint },
51
+ containerEl: examSearchContainer
52
+ }"
44
53
  :is-premium="premiumExamIds.includes(exam.objectId)"
45
54
  :exam="exam"
46
55
  :bundle="exam.bundle"
@@ -58,7 +67,10 @@
58
67
  :class="{ 'uikit-exam-search__bundle-search--bundle-selected': selectedBundle }"
59
68
  >
60
69
  <div
61
- v-breakpoint:examSearchContainer="{ small: smallBreakpoint }"
70
+ v-breakpoint="{
71
+ breakpoints: { small: smallBreakpoint },
72
+ containerEl: examSearchContainer
73
+ }"
62
74
  class="uikit-exam-search__bundle-list"
63
75
  >
64
76
  <div class="uikit-exam-search__browse-industry-text">
@@ -73,15 +85,24 @@
73
85
  </div>
74
86
  <div
75
87
  v-if="selectedBundle"
76
- v-breakpoint:examSearchContainer="{ small: smallBreakpoint }"
88
+ v-breakpoint="{
89
+ breakpoints: { small: smallBreakpoint },
90
+ containerEl: examSearchContainer
91
+ }"
77
92
  class="uikit-exam-search__bundle-exam-container"
78
93
  >
79
94
  <div
80
- v-breakpoint:examSearchContainer="{ small: smallBreakpoint }"
95
+ v-breakpoint="{
96
+ breakpoints: { small: smallBreakpoint },
97
+ containerEl: examSearchContainer
98
+ }"
81
99
  class="uikit-exam-search__bundle-exam-container-top"
82
100
  >
83
101
  <PocketButton
84
- v-breakpoint:examSearchContainer="{ small: smallBreakpoint }"
102
+ v-breakpoint="{
103
+ breakpoints: { small: smallBreakpoint },
104
+ containerEl: examSearchContainer
105
+ }"
85
106
  class="uikit-exam-search__bundle-exam-back"
86
107
  :is-dark-mode="isDarkMode"
87
108
  type="tertiary"
@@ -90,7 +111,10 @@
90
111
  <Icon type="arrow" /> Back to Browse
91
112
  </PocketButton>
92
113
  <span
93
- v-breakpoint:examSearchContainer="{ small: smallBreakpoint }"
114
+ v-breakpoint="{
115
+ breakpoints: { small: smallBreakpoint },
116
+ containerEl: examSearchContainer
117
+ }"
94
118
  class="uikit-exam-search__bundle-exam-count"
95
119
  tabindex="-1"
96
120
  >
@@ -110,7 +134,10 @@
110
134
  <ExamCard
111
135
  v-for="exam in selectedBundleExams"
112
136
  :key="exam.objectId"
113
- v-breakpoint:examSearchContainer="{ small: smallBreakpoint }"
137
+ v-breakpoint="{
138
+ breakpoints: { small: smallBreakpoint },
139
+ containerEl: examSearchContainer
140
+ }"
114
141
  :exam="exam"
115
142
  :is-dark-mode="isDarkMode"
116
143
  :bundle="exam.bundle"
@@ -120,7 +147,10 @@
120
147
  @select="selectExam(exam)"
121
148
  />
122
149
  <div
123
- v-breakpoint:examSearchContainer="{ small: smallBreakpoint }"
150
+ v-breakpoint="{
151
+ breakpoints: { small: smallBreakpoint },
152
+ containerEl: examSearchContainer
153
+ }"
124
154
  class="uikit-exam-search__exam-list-padding"
125
155
  />
126
156
  </div>
@@ -40,30 +40,32 @@
40
40
  </div>
41
41
  </template>
42
42
 
43
- <script lang="ts">
44
- import { Vue, Component, Prop, Emit } from 'vue-facing-decorator'
43
+ <script setup lang="ts">
44
+ import { computed } from 'vue'
45
45
  import Icon from '../Icons/Icon.vue'
46
46
 
47
- @Component({
48
- components: {
49
- Icon,
50
- },
47
+ const props = withDefaults(defineProps<{
48
+ currentPage: number
49
+ total: number
50
+ }>(), {
51
+ currentPage: 0,
52
+ total: 0,
51
53
  })
52
- export default class QuestionReviewPagination extends Vue {
53
- @Prop({ default: 0 }) currentPage!: number
54
- @Prop() total!: number
55
54
 
56
- get nextPageDisabled () {
57
- return this.currentPage >= Math.floor(this.total - 1)
58
- }
55
+ const emit = defineEmits<{
56
+ changePage: [ pageNum: number ]
57
+ }>()
59
58
 
60
- @Emit('changePage')
61
- changePage (direction: 'next' | 'previous') {
62
- if (direction === 'next') {
63
- return this.nextPageDisabled ? this.currentPage : this.currentPage + 1
64
- } else {
65
- return Math.max(0, this.currentPage - 1)
66
- }
59
+ const nextPageDisabled = computed(() => {
60
+ return props.currentPage >= Math.floor(props.total - 1)
61
+ })
62
+
63
+ const changePage = (direction: 'next' | 'previous') => {
64
+ if (direction === 'next') {
65
+ const pageNum = nextPageDisabled.value ? props.currentPage : props.currentPage + 1
66
+ emit('changePage', pageNum)
67
+ } else {
68
+ emit('changePage', Math.max(0, props.currentPage - 1))
67
69
  }
68
70
  }
69
71
  </script>
@@ -6,7 +6,7 @@
6
6
  ref="uikit-question-choices-container"
7
7
  >
8
8
  <div
9
- ref="choices"
9
+ ref="choicesRef"
10
10
  v-dark="isDarkMode"
11
11
  class="uikit-question-choices-container__choice-container"
12
12
  :class="{
@@ -40,7 +40,7 @@
40
40
  >
41
41
  <div
42
42
  v-if="!reviewMode"
43
- v-breakpoint:questionEl="breakpoints"
43
+ v-breakpoint="breakpointsWithEl"
44
44
  v-dark="isDarkMode"
45
45
  class="uikit-question-choices-container__choice-letter"
46
46
  :class="!isMCR && {
@@ -60,7 +60,7 @@
60
60
  <div
61
61
  :ref="`choice-${choice.key}`"
62
62
  v-dark="isDarkMode"
63
- v-breakpoint:questionEl="breakpoints"
63
+ v-breakpoint="breakpointsWithEl"
64
64
  class="uikit-question-choices-container__choice"
65
65
  :class="{
66
66
  'uikit-question-choices-container__choice--strike': showAnswers
@@ -111,7 +111,7 @@
111
111
  'uikit-question-choices-container__choice-text--review-mode':
112
112
  reviewMode,
113
113
  }"
114
- v-breakpoint:questionEl="breakpoints"
114
+ v-breakpoint="breakpointsWithEl"
115
115
  :tabindex="showAnswers ? -1 : 0"
116
116
  :role="isMCR
117
117
  ? 'checkbox'
@@ -129,7 +129,7 @@
129
129
  />
130
130
  <PocketButton
131
131
  v-if="!isMCR && showAnswers && answerKeys.includes(choice.key)"
132
- v-breakpoint:questionEl="breakpoints"
132
+ v-breakpoint="breakpointsWithEl"
133
133
  type="tertiary-small"
134
134
  class="uikit-question-choices-container__toggle-explanation"
135
135
  :class="{ 'uikit-question-choices-container__toggle-explanation--review-mode': reviewMode }"
@@ -144,7 +144,7 @@
144
144
  tabindex="-1"
145
145
  >{{ showExplanation ? 'Hide' : 'Show' }} Explanation</span>
146
146
  <Icon
147
- v-breakpoint:questionEl="breakpoints"
147
+ v-breakpoint="breakpointsWithEl"
148
148
  class="uikit-question-choices-container__toggle-explanation-icon"
149
149
  :class="{
150
150
  'uikit-question-choices-container__toggle-explanation-icon--up': showExplanation,
@@ -156,22 +156,6 @@
156
156
  v-if="!isMCR && showAnswers && answerKeys.includes(choice.key) && showExplanation"
157
157
  ref="uikit-question-choices-container__dropdown-explanation"
158
158
  class="uikit-question-choices-container__dropdown-explanation"
159
- :question="question"
160
- :answer-keys="answerKeys"
161
- :choice="choice"
162
- :global-metrics="globalMetrics"
163
- :show-answers="showAnswers"
164
- :is-MCR="isMCR"
165
- :show-explanation-image-long-alt="showExplanationImageLongAlt"
166
- :explanation-image-url="explanationImageUrl"
167
- :explanation-image-alt="explanationImageAlt"
168
- :explanation-image-long-alt="explanationImageLongAlt"
169
- :reference="reference"
170
- :hide-references="hideReferences"
171
- :is-dark-mode="isDarkMode"
172
- :question-el="questionEl"
173
- :breakpoints="breakpoints"
174
- :keyword-definitions="keywordDefinitions"
175
159
  @toggleDropdownExplanationImageLongAlt="toggleDropdownExplanationImageLongAlt"
176
160
  @click="handleClick"
177
161
  >
@@ -186,7 +170,7 @@
186
170
  <template v-if="!globalMetrics">
187
171
  <div
188
172
  v-if="!showAnswers"
189
- v-breakpoint:questionEl="breakpoints"
173
+ v-breakpoint="breakpointsWithEl"
190
174
  v-dark="isDarkMode"
191
175
  :tabindex="showAnswers ? -1 : 0"
192
176
  class="uikit-question-choices-container__strikethrough"
@@ -261,7 +245,7 @@
261
245
  </div>
262
246
  </template>
263
247
  <div
264
- v-breakpoint:questionEl="breakpoints"
248
+ v-breakpoint="breakpointsWithEl"
265
249
  class="uikit-question-choices-container__motivational-moment"
266
250
  :class="{
267
251
  'uikit-question-choices-container__motivational-moment--mcr': isMCR,
@@ -286,127 +270,109 @@
286
270
  </div>
287
271
  </template>
288
272
 
289
- <script lang="ts">
290
- import { Component, Vue, Prop, Emit } from 'vue-facing-decorator'
291
- import type { Study } from '@pocketprep/types'
273
+ <script setup lang="ts">
292
274
  import DropdownExplanation from './DropdownExplanation.vue'
293
275
  import Icon from '../../Icons/Icon.vue'
294
276
  import PocketButton from '../../Buttons/Button.vue'
295
- import { dark, breakpoint } from '../../../directives'
296
- import type { TBreakPointsObject, TChoice, TChoiceKey, TChoiceScores } from './../question'
297
-
298
- @Component({
299
- components: {
300
- Icon,
301
- PocketButton,
302
- DropdownExplanation,
303
- },
304
- directives: {
305
- dark,
306
- breakpoint,
307
- },
308
- })
309
- export default class ChoicesContainer extends Vue {
310
- @Prop() question!: Study.Class.QuestionJSON
311
- @Prop({ default: [] }) choices!: TChoice[]
312
- @Prop({ default: false }) showAnswers!: boolean
313
- @Prop({ default: false }) showExplanation!: boolean
314
- @Prop({ default: false }) isMCR!: boolean
315
- @Prop({ default: false }) isUnanswered!: boolean
316
- @Prop({ default: [] }) answerKeys!: TChoiceKey[]
317
- @Prop({ default: null }) hoverChoiceKey!: TChoiceKey | null
318
- @Prop({ default: null }) focusChoiceKey!: TChoiceKey | null
319
- @Prop({ default: [] }) selectedChoices!: TChoiceKey[]
320
- @Prop({ default: [] }) distractorKeys!: TChoiceKey[]
321
- @Prop({ default: [] }) choiceStrikes!: TChoiceKey[]
322
- @Prop() choiceScores!: TChoiceScores
323
- @Prop({ default: null }) passageImageUrl!: string | null
324
- @Prop({ default: false }) isCorrect!: boolean
325
- @Prop({ default: null }) globalMetrics!: Study.Class.GlobalQuestionMetricJSON | null
326
- @Prop({ default: false }) reviewMode!: boolean
327
- @Prop({ default: false }) showExplanationImageLongAlt!: boolean
328
- @Prop({ default: null }) explanationImageUrl!: string | null
329
- @Prop({ default: undefined }) explanationImageAlt!: string | undefined
330
- @Prop({ default: undefined }) explanationImageLongAlt!: string | undefined
331
- @Prop({ default: undefined }) reference!: string | undefined
332
- @Prop({ default: false }) hideReferences!: boolean
333
- @Prop({ default: false }) isDarkMode!: boolean
334
- @Prop({ default: null }) questionEl!: Element | null
335
- @Prop({ default: {
336
- 'mobile': 767,
337
- 'tablet-portrait': 1023,
338
- 'tablet-landscape': 1439,
339
- } }) breakpoints!: TBreakPointsObject
340
- @Prop({ default: [] }) keywordDefinitions!: { keyword: string; definition: string }[]
341
-
342
- stripHtmlTags (string?: string) {
343
- if (string) {
344
- const div = document.createElement('div')
345
- div.innerHTML = string
346
- return div.textContent || ''
347
- }
348
- return ''
277
+ import { dark as vDark, breakpoint as vBreakpoint } from '../../../directives'
278
+ import { useQuestionContext } from './composables'
279
+ import type { TChoiceKey } from '../question'
280
+
281
+ const emit = defineEmits<{
282
+ 'emitChoiceFocusIn': [ choiceKey: TChoiceKey ]
283
+ 'emitChoiceFocusOut': [ focusEvent: FocusEvent]
284
+ 'emitChoiceMouseOver': [ choiceKey: TChoiceKey ]
285
+ 'emitChoiceMouseLeave': []
286
+ 'emitHandleTouchStart': [ touchEvent: TouchEvent ]
287
+ 'emitHandleTouchMove': [ touchEvent: TouchEvent ]
288
+ 'emitHandleTouchEnd': [ touchEndPayload: { choiceKey: TChoiceKey; event: TouchEvent } ]
289
+ 'emitSelectedChoice': [ choiceKey: TChoiceKey ]
290
+ 'emitClickChoiceStrike': [ choiceKey: TChoiceKey ]
291
+ 'toggleChoiceExplanation': []
292
+ 'toggleDropdownExplanationImageLongAlt': []
293
+ 'click': [ event: MouseEvent ]
294
+ }>()
295
+
296
+ const {
297
+ // questionEl is used by the breakpoint directive
298
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
299
+ questionEl,
300
+ question,
301
+ choices,
302
+ showAnswers,
303
+ showExplanation,
304
+ isMCR,
305
+ isUnanswered,
306
+ answerKeys,
307
+ hoverChoiceKey,
308
+ focusChoiceKey,
309
+ selectedChoices,
310
+ distractorKeys,
311
+ choiceStrikes,
312
+ choiceScores,
313
+ globalMetrics,
314
+ reviewMode,
315
+ isDarkMode,
316
+ passageImageUrl,
317
+ isCorrect,
318
+ breakpointsWithEl,
319
+ } = useQuestionContext()
320
+
321
+ const stripHtmlTags = (string?: string) => {
322
+ if (string) {
323
+ const div = document.createElement('div')
324
+ div.innerHTML = string
325
+ return div.textContent || ''
349
326
  }
327
+ return ''
328
+ }
350
329
 
351
- @Emit('emitChoiceFocusIn')
352
- emitChoiceFocusIn (choiceKey: TChoiceKey) {
353
- return choiceKey
354
- }
330
+ const emitChoiceFocusIn = (choiceKey: TChoiceKey) => {
331
+ emit('emitChoiceFocusIn', choiceKey)
332
+ }
355
333
 
356
- @Emit('emitChoiceFocusOut')
357
- emitChoiceFocusOut (event: FocusEvent) {
358
- return event
359
- }
334
+ const emitChoiceFocusOut = (focusEvent: FocusEvent) => {
335
+ emit('emitChoiceFocusOut', focusEvent)
336
+ }
360
337
 
361
- @Emit('emitChoiceMouseOver')
362
- emitChoiceMouseOver (choiceKey: TChoiceKey) {
363
- return choiceKey
364
- }
338
+ const emitChoiceMouseOver = (choiceKey: TChoiceKey) => {
339
+ emit('emitChoiceMouseOver', choiceKey)
340
+ }
365
341
 
366
- @Emit('emitChoiceMouseLeave')
367
- emitChoiceMouseLeave () {
368
- return
369
- }
342
+ const emitChoiceMouseLeave = () => {
343
+ emit('emitChoiceMouseLeave')
344
+ }
370
345
 
371
- @Emit('emitHandleTouchStart')
372
- emitHandleTouchStart (event: TouchEvent) {
373
- return event
374
- }
346
+ const emitHandleTouchStart = (event: TouchEvent) => {
347
+ emit('emitHandleTouchStart', event)
348
+ }
375
349
 
376
- @Emit('emitHandleTouchMove')
377
- emitHandleTouchMove (event: TouchEvent) {
378
- return event
379
- }
350
+ const emitHandleTouchMove = (event: TouchEvent) => {
351
+ emit('emitHandleTouchMove', event)
352
+ }
380
353
 
381
- @Emit('emitHandleTouchEnd')
382
- emitHandleTouchEnd (choiceKey: TChoiceKey, event: TouchEvent) {
383
- return { choiceKey, event }
384
- }
354
+ const emitHandleTouchEnd = (choiceKey: TChoiceKey, event: TouchEvent) => {
355
+ emit('emitHandleTouchEnd', { choiceKey, event })
356
+ }
385
357
 
386
- @Emit('emitSelectedChoice')
387
- emitSelectedChoice (choiceKey: TChoiceKey) {
388
- return choiceKey
389
- }
358
+ const emitSelectedChoice = (choiceKey: TChoiceKey) => {
359
+ emit('emitSelectedChoice', choiceKey)
360
+ }
390
361
 
391
- @Emit('emitClickChoiceStrike')
392
- emitClickChoiceStrike (choiceKey: TChoiceKey) {
393
- return choiceKey
394
- }
362
+ const emitClickChoiceStrike = (choiceKey: TChoiceKey) => {
363
+ emit('emitClickChoiceStrike', choiceKey)
364
+ }
395
365
 
396
- @Emit('toggleChoiceExplanation')
397
- toggleChoiceExplanation () {
398
- return
399
- }
366
+ const toggleChoiceExplanation = () => {
367
+ emit('toggleChoiceExplanation')
368
+ }
400
369
 
401
- @Emit('toggleDropdownExplanationImageLongAlt')
402
- toggleDropdownExplanationImageLongAlt () {
403
- return
404
- }
370
+ const toggleDropdownExplanationImageLongAlt = () => {
371
+ emit('toggleDropdownExplanationImageLongAlt')
372
+ }
405
373
 
406
- @Emit('click')
407
- handleClick (event: MouseEvent) {
408
- return event
409
- }
374
+ const handleClick = (event: MouseEvent) => {
375
+ emit('click', event)
410
376
  }
411
377
  </script>
412
378
 
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div
3
- v-breakpoint:questionEl="breakpoints"
3
+ v-breakpoint="breakpointsWithEl"
4
4
  ref="uikit-question-dropdown-explanation"
5
5
  class="uikit-question-dropdown-explanation__dropdown-explanation"
6
6
  :class="{
@@ -22,7 +22,7 @@
22
22
  >
23
23
  <PocketButton
24
24
  v-if="explanationImageLongAlt"
25
- v-breakpoint:questionEl="breakpoints"
25
+ v-breakpoint="breakpointsWithEl"
26
26
  type="tertiary-small"
27
27
  class="uikit-question-dropdown-explanation__toggle-dropdown-explanation-img-description"
28
28
  :class="{
@@ -52,7 +52,7 @@
52
52
  v-if="showExplanationImageLongAlt"
53
53
  ref="uikit-question-dropdown-explanation__dropdown-explanation-img-description"
54
54
  v-dark="isDarkMode"
55
- v-breakpoint:questionEl="breakpoints"
55
+ v-breakpoint="breakpointsWithEl"
56
56
  class="uikit-question-dropdown-explanation__dropdown-explanation-img-description"
57
57
  tabindex="-1"
58
58
  v-html="explanationImageLongAlt"
@@ -69,60 +69,46 @@
69
69
  </div>
70
70
  </template>
71
71
 
72
- <script lang="ts">
73
- import { Component, Emit, Prop, Vue } from 'vue-facing-decorator'
74
- import type { Study } from '@pocketprep/types'
72
+ <script setup lang="ts">
73
+ import { computed } from 'vue'
75
74
  import Icon from '../../Icons/Icon.vue'
76
75
  import PocketButton from '../../Buttons/Button.vue'
77
- import { breakpoint, dark } from '../../../directives'
78
- import type { TBreakPointsObject, TChoice, TChoiceKey } from './../question'
76
+ import { dark as vDark, breakpoint as vBreakpoint } from '../../../directives'
79
77
  import { highlightKeywordsInText } from '../../../utils'
80
-
81
- @Component({
82
- components: {
83
- Icon,
84
- PocketButton,
85
- },
86
- directives: {
87
- dark,
88
- breakpoint,
89
- },
78
+ import { useQuestionContext } from './composables'
79
+
80
+ const emit = defineEmits<{
81
+ 'toggleDropdownExplanationImageLongAlt': []
82
+ }>()
83
+
84
+ const {
85
+ // questionEl is used by the breakpoint directive
86
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
87
+ questionEl,
88
+ question,
89
+ globalMetrics,
90
+ showExplanationImageLongAlt,
91
+ explanationImageUrl,
92
+ explanationImageAlt,
93
+ explanationImageLongAlt,
94
+ reference,
95
+ hideReferences,
96
+ isDarkMode,
97
+ breakpointsWithEl,
98
+ keywordDefinitions,
99
+ } = useQuestionContext()
100
+
101
+ const explanation = computed(() => {
102
+ return highlightKeywordsInText({
103
+ text: question.value.explanation || '',
104
+ keywordDefinitions: keywordDefinitions.value,
105
+ isDarkMode: isDarkMode.value,
106
+ location: 'explanation',
107
+ })
90
108
  })
91
- export default class DropdownExplanation extends Vue {
92
- @Prop() question!: Study.Class.QuestionJSON
93
- @Prop({ default: [] }) answerKeys!: TChoiceKey[]
94
- @Prop() choice!: TChoice
95
- @Prop({ default: null }) globalMetrics!: Study.Class.GlobalQuestionMetricJSON | null
96
- @Prop({ default: false }) showAnswers!: boolean
97
- @Prop({ default: false }) isMCR!: boolean
98
- @Prop({ default: false }) showExplanationImageLongAlt!: boolean
99
- @Prop({ default: null }) explanationImageUrl!: string | null
100
- @Prop({ default: undefined }) explanationImageAlt!: string | undefined
101
- @Prop({ default: undefined }) explanationImageLongAlt!: string | undefined
102
- @Prop({ default: undefined }) reference!: string | undefined
103
- @Prop({ default: false }) hideReferences!: boolean
104
- @Prop({ default: false }) isDarkMode!: boolean
105
- @Prop({ default: null }) questionEl!: Element | null
106
- @Prop({ default: {
107
- 'mobile': 767,
108
- 'tablet-portrait': 1023,
109
- 'tablet-landscape': 1439,
110
- } }) breakpoints!: TBreakPointsObject
111
- @Prop({ default: [] }) keywordDefinitions!: { keyword: string; definition: string }[]
112
-
113
- get explanation () {
114
- return highlightKeywordsInText({
115
- text: this.question.explanation || '',
116
- keywordDefinitions: this.keywordDefinitions,
117
- isDarkMode: this.isDarkMode,
118
- location: 'explanation',
119
- })
120
- }
121
-
122
- @Emit('toggleDropdownExplanationImageLongAlt')
123
- toggleDropdownExplanationImageLongAlt () {
124
- return
125
- }
109
+
110
+ const toggleDropdownExplanationImageLongAlt = () => {
111
+ emit('toggleDropdownExplanationImageLongAlt')
126
112
  }
127
113
  </script>
128
114