@pocketprep/ui-kit 3.4.34 → 3.4.36

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.
@@ -18,6 +18,7 @@
18
18
  >{{ label }}</label>
19
19
  <div
20
20
  v-if="showIconAndTooltip"
21
+ class="uikit-textarea__tooltip-container"
21
22
  @mouseenter="showTextAreaTooltip = true"
22
23
  @mouseleave="showTextAreaTooltip = false"
23
24
  @focus="showTextAreaTooltip = true"
@@ -152,6 +153,10 @@ export default class Textarea extends Vue {
152
153
  }
153
154
  }
154
155
 
156
+ &__tooltip-container {
157
+ margin-top: -2px;
158
+ }
159
+
155
160
  &__icon {
156
161
  padding: 0 0 2px 5px;
157
162
  color: $brand-blue;
@@ -218,4 +223,4 @@ export default class Textarea extends Vue {
218
223
  }
219
224
  }
220
225
  }
221
- </style>
226
+ </style>
@@ -166,7 +166,9 @@
166
166
  :is-dark-mode="isDarkMode"
167
167
  :question-el="questionEl"
168
168
  :breakpoints="breakpoints"
169
+ :keyword-definitions="keywordDefinitions"
169
170
  @toggleDropdownExplanationImageLongAlt="toggleDropdownExplanationImageLongAlt"
171
+ @click="handleClick"
170
172
  />
171
173
  </div>
172
174
  <template v-if="!globalMetrics">
@@ -323,6 +325,7 @@ export default class ChoicesContainer extends Vue {
323
325
  'tablet-portrait': 1023,
324
326
  'tablet-landscape': 1439,
325
327
  } }) breakpoints!: TBreakPointsObject
328
+ @Prop({ default: [] }) keywordDefinitions!: { keyword: string; definition: string }[]
326
329
 
327
330
  stripText (string?: string) {
328
331
  return string?.replace(/<[^\s>]+[^>]*>/gi, ' ').trim()
@@ -383,6 +386,11 @@ export default class ChoicesContainer extends Vue {
383
386
  toggleDropdownExplanationImageLongAlt () {
384
387
  return
385
388
  }
389
+
390
+ @Emit('click')
391
+ handleClick (event: MouseEvent) {
392
+ return event
393
+ }
386
394
  }
387
395
  </script>
388
396
 
@@ -10,7 +10,7 @@
10
10
  <div
11
11
  v-dark="isDarkMode"
12
12
  class="uikit-question-dropdown-explanation__dropdown-explanation-text"
13
- v-html="question.explanation"
13
+ v-html="explanation"
14
14
  />
15
15
  <img
16
16
  v-if="explanationImageUrl"
@@ -74,6 +74,7 @@ import Icon from '../../Icons/Icon.vue'
74
74
  import PocketButton from '../../Buttons/Button.vue'
75
75
  import { breakpoint, dark } from '../../../directives'
76
76
  import type { TBreakPointsObject, TChoice, TChoiceKey } from './../question'
77
+ import { highlightKeywordsInText } from '../../../utils'
77
78
 
78
79
  @Component({
79
80
  components: {
@@ -105,6 +106,16 @@ export default class DropdownExplanation extends Vue {
105
106
  'tablet-portrait': 1023,
106
107
  'tablet-landscape': 1439,
107
108
  } }) breakpoints!: TBreakPointsObject
109
+ @Prop({ default: [] }) keywordDefinitions!: { keyword: string; definition: string }[]
110
+
111
+ get explanation () {
112
+ return highlightKeywordsInText({
113
+ text: this.question.explanation || '',
114
+ keywordDefinitions: this.keywordDefinitions,
115
+ isDarkMode: this.isDarkMode,
116
+ location: 'dropdown-explanation',
117
+ })
118
+ }
108
119
 
109
120
  @Emit('toggleDropdownExplanationImageLongAlt')
110
121
  toggleDropdownExplanationImageLongAlt () {
@@ -17,7 +17,7 @@
17
17
  v-dark="isDarkMode"
18
18
  v-breakpoint:questionEl="breakpoints"
19
19
  class="uikit-question-explanation__explanation-text"
20
- v-html="question.explanation"
20
+ v-html="explanation"
21
21
  />
22
22
  <img
23
23
  v-if="explanationImageUrl"
@@ -92,6 +92,7 @@ import Icon from '../../Icons/Icon.vue'
92
92
  import PocketButton from '../../Buttons/Button.vue'
93
93
  import { breakpoint, dark } from '../../../directives'
94
94
  import type { TBreakPointsObject } from './../question'
95
+ import { highlightKeywordsInText } from '../../../utils'
95
96
 
96
97
  @Component({
97
98
  components: {
@@ -121,6 +122,16 @@ export default class Explanation extends Vue {
121
122
  'tablet-portrait': 1023,
122
123
  'tablet-landscape': 1439,
123
124
  } }) breakpoints!: TBreakPointsObject
125
+ @Prop({ default: [] }) keywordDefinitions!: { keyword: string; definition: string }[]
126
+
127
+ get explanation () {
128
+ return highlightKeywordsInText({
129
+ text: this.question.explanation || '',
130
+ keywordDefinitions: this.keywordDefinitions,
131
+ isDarkMode: this.isDarkMode,
132
+ location: 'explanation',
133
+ })
134
+ }
124
135
 
125
136
  @Emit('toggleExplanationImageLongAlt')
126
137
  toggleExplanationImageLongAlt () {
@@ -66,7 +66,8 @@
66
66
  :class="{
67
67
  'uikit-question__prompt--passage-and-image': question.passage || passageImageUrl,
68
68
  }"
69
- v-html="question.prompt"
69
+ @click="keywordClick"
70
+ v-html="prompt"
70
71
  />
71
72
  <PocketButton
72
73
  v-if="question.passage || passageImageUrl"
@@ -178,6 +179,7 @@
178
179
  :is-dark-mode="isDarkMode"
179
180
  :question-el="questionEl"
180
181
  :breakpoints="breakpoints"
182
+ :keyword-definitions="keywordDefinitions"
181
183
  @emitChoiceMouseOver="choiceMouseOver"
182
184
  @emitChoiceMouseLeave="choiceMouseLeave"
183
185
  @emitChoiceFocusIn="choiceFocusIn"
@@ -189,6 +191,7 @@
189
191
  @emitClickChoiceStrike="clickChoiceStrike"
190
192
  @toggleChoiceExplanation="toggleExplanation"
191
193
  @toggleDropdownExplanationImageLongAlt="toggleExplanationImageLongAlt"
194
+ @click="keywordClick"
192
195
  >
193
196
  <template #motivationalMoment="{
194
197
  isCorrect,
@@ -330,7 +333,7 @@
330
333
  :breakpoints="breakpoints"
331
334
  @emitTogglePassageImageLongAlt="togglePassageImageLongAlt"
332
335
  @emitMoveFocusToPrompt="moveFocusToPrompt"
333
- />
336
+ />
334
337
  <Explanation
335
338
  ref="uikit-question__explanation"
336
339
  class="uikit-question__explanation"
@@ -347,8 +350,10 @@
347
350
  :is-dark-mode="isDarkMode"
348
351
  :question-el="questionEl"
349
352
  :breakpoints="breakpoints"
353
+ :keyword-definitions="keywordDefinitions"
350
354
  @toggleExplanationImageLongAlt="toggleExplanationImageLongAlt"
351
355
  @toggleExplanation="toggleExplanation"
356
+ @click="keywordClick"
352
357
  />
353
358
  </div>
354
359
  </div>
@@ -373,7 +378,7 @@ import Explanation from '../Quiz/Question/Explanation.vue'
373
378
  import PassageAndImage from '../Quiz/Question/PassageAndImage.vue'
374
379
  import type { Study } from '@pocketprep/types'
375
380
  import { breakpoint, dark } from '../../directives'
376
- import { studyModes } from '../../utils'
381
+ import { highlightKeywordsInText, studyModes } from '../../utils'
377
382
  import type { Ref, TQuizMode, TChoiceKey, TChoice, TChoiceScores, TNamesRow, TViewNames } from './question'
378
383
 
379
384
  @Component({
@@ -421,6 +426,7 @@ export default class Question extends Vue {
421
426
  @Prop({ default: false }) showPaywall!: boolean
422
427
  @Prop({ default: false }) hideReferences!: boolean
423
428
  @Prop({ default: false }) isTeachReview!: boolean
429
+ @Prop({ default: [] }) keywordDefinitions!: { keyword: string; definition: string }[]
424
430
 
425
431
  hoverChoiceKey: TChoiceKey | null = null
426
432
  focusChoiceKey: TChoiceKey | null = null
@@ -606,6 +612,15 @@ export default class Question extends Vue {
606
612
  return this.selectedChoices.length === 0
607
613
  }
608
614
 
615
+ get prompt () {
616
+ return highlightKeywordsInText({
617
+ text: this.question.prompt,
618
+ keywordDefinitions: this.keywordDefinitions,
619
+ isDarkMode: this.isDarkMode,
620
+ location: 'prompt',
621
+ })
622
+ }
623
+
609
624
  mounted () {
610
625
  if (this.reviewMode) {
611
626
  this.startReviewMode()
@@ -718,6 +733,19 @@ export default class Question extends Vue {
718
733
  }, 0)
719
734
  }
720
735
 
736
+ @Emit('keyword-click')
737
+ keywordClick (event: MouseEvent) {
738
+ const target = event.target as HTMLElement
739
+ if (target.classList.contains('keyword-highlight')) {
740
+ const keyword = target.innerHTML
741
+ const location = target.getAttribute('data-location')
742
+ return {
743
+ keyword,
744
+ location,
745
+ }
746
+ }
747
+ }
748
+
721
749
  startReviewMode () {
722
750
  this.showAnswers = true
723
751
  this.showExplanation = this.defaultShowExplanation === null ? true : this.defaultShowExplanation
@@ -1283,6 +1311,16 @@ export default class Question extends Vue {
1283
1311
  }
1284
1312
  }
1285
1313
 
1314
+ .keyword-highlight {
1315
+ text-decoration: underline;
1316
+ text-decoration-color: $brand-blue;
1317
+ cursor: pointer;
1318
+
1319
+ &--dark {
1320
+ text-decoration-color: $banana-bread;
1321
+ }
1322
+ }
1323
+
1286
1324
  &__prompt {
1287
1325
  outline: none;
1288
1326
  font-weight: 600;
package/lib/utils.ts CHANGED
@@ -58,3 +58,25 @@ export const studyModes = {
58
58
  iconColorDM: BrandColors.pewter,
59
59
  },
60
60
  } as const
61
+
62
+ export const highlightKeywordsInText = (params: {
63
+ text: string
64
+ keywordDefinitions: { keyword: string }[]
65
+ isDarkMode: boolean
66
+ location?: string
67
+ }) => {
68
+ if (!params.keywordDefinitions.length) {
69
+ return params.text
70
+ }
71
+
72
+ const keywords = params.keywordDefinitions.map(k => k.keyword)
73
+
74
+ return keywords.reduce((acc, word) => {
75
+ const regex = new RegExp(`(${word})`, 'i')
76
+ return acc.replace(
77
+ regex,
78
+ `<span class="keyword-highlight${params.isDarkMode
79
+ ? ' keyword-highlight--dark' : ''}" data-location="${params.location}">$1</span>`
80
+ )
81
+ }, params.text)
82
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pocketprep/ui-kit",
3
- "version": "3.4.34",
3
+ "version": "3.4.36",
4
4
  "description": "Pocket Prep UI Kit",
5
5
  "author": "pocketprep",
6
6
  "scripts": {