@pocketprep/ui-kit 3.4.1 → 3.4.3

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.
@@ -34,65 +34,27 @@
34
34
  }"
35
35
  >
36
36
  <slot name="context">
37
- <div
37
+ <QuestionContext
38
38
  ref="uikit-question__context"
39
39
  v-breakpoint:questionEl="breakpoints"
40
40
  class="uikit-question__context"
41
41
  tabindex="-1"
42
+ :quiz-length="quizLength"
43
+ :quiz-mode="quizMode"
44
+ :question-number="questionNumber"
45
+ :is-dark-mode="isDarkMode"
46
+ :context-icon-type="contextIconType"
47
+ :show-answers="showAnswers"
48
+ :question-el="questionEl"
49
+ :breakpoints="breakpoints"
42
50
  >
43
- <slot name="contextIcon">
44
- <Icon
45
- v-dark="isDarkMode"
46
- class="uikit-question__context-icon"
47
- :type="contextIconType"
48
- />
49
- </slot>
50
- <slot name="contextText">
51
- <h2
52
- v-if="quizMode === 'qotd'"
53
- v-dark="isDarkMode"
54
- class="uikit-question__context-text"
55
- >
56
- Question of the Day
57
- </h2>
58
- <h2
59
- v-else
60
- v-dark="isDarkMode"
61
- class="uikit-question__context-text"
62
- :aria-label="`Question ${
63
- questionNumber
64
- }${
65
- quizMode !== 'timed'
66
- ? ` of ${quizLength}`
67
- : ''
68
- }${
69
- showAnswers
70
- ? isCorrect
71
- ? ', Answered Correctly'
72
- : ', Answered Incorrectly'
73
- : ''
74
- }`"
75
- aria-live="assertive"
76
- >
77
- <div class="uikit-question__current-index" aria-hidden="true">
78
- Question {{ questionNumber }}
79
- </div>
80
- <div
81
- v-if="quizMode !== 'timed'"
82
- class="uikit-question__quiz-length"
83
- aria-hidden="true"
84
- >
85
- / {{ quizLength }}
86
- </div>
87
- </h2>
88
- </slot>
89
- <div
90
- class="uikit-question__tag"
91
- v-breakpoint:questionEl="breakpoints"
92
- >
51
+ <template #contextIcon>
52
+ <slot name="contextIcon" />
53
+ </template>
54
+ <template #tag>
93
55
  <slot name="tag" />
94
- </div>
95
- </div>
56
+ </template>
57
+ </QuestionContext>
96
58
  </slot>
97
59
  <div
98
60
  ref="prompt"
@@ -112,103 +74,22 @@
112
74
  >
113
75
  Skip to Passage
114
76
  </PocketButton>
115
- <div
77
+ <PassageAndImageDropdown
116
78
  v-if="question.passage || passageImageUrl"
117
- v-breakpoint:questionEl="breakpoints"
118
- v-dark="isDarkMode"
79
+ ref="uikit-question__passage-and-image-dropdown"
119
80
  class="uikit-question__passage-and-image-dropdown"
120
- :class="{ 'uikit-question__passage-and-image-dropdown--review-mode': reviewMode }"
121
- >
122
- <div
123
- v-dark="isDarkMode"
124
- class="uikit-question__passage-and-image-dropdown-btn"
125
- tabindex="0"
126
- role="button"
127
- :aria-expanded="showPassageImageDropdown ? 'true' : 'false'"
128
- @click.stop="showPassageImageDropdown = !showPassageImageDropdown"
129
- @keydown.enter.stop="showPassageImageDropdown = !showPassageImageDropdown"
130
- @mousedown.prevent
131
- >
132
- <Icon
133
- v-if="question.passage"
134
- class="uikit-question__passage-dropdown-icon"
135
- type="passage"
136
- />
137
- <Icon
138
- v-else
139
- class="uikit-question__image-dropdown-icon"
140
- type="image"
141
- />
142
- <span v-dark="isDarkMode" class="uikit-question__passage-and-image-dropdown-text">
143
- {{ showPassageImageDropdown ? 'Hide' : 'Show' }}
144
- {{ passageAndImageTitle }}
145
- </span>
146
- <Icon
147
- v-dark="isDarkMode"
148
- class="uikit-question__passage-and-image-dropdown-arrow"
149
- :class="{
150
- 'uikit-question__passage-and-image-dropdown-arrow--up': showPassageImageDropdown,
151
- }"
152
- type="accordionArrow"
153
- />
154
- </div>
155
- <div
156
- v-if="showPassageImageDropdown"
157
- v-breakpoint:questionEl="breakpoints"
158
- class="uikit-question__passage-and-image-dropdown-container"
159
- >
160
- <div
161
- v-if="question.passage"
162
- v-breakpoint:questionEl="breakpoints"
163
- class="uikit-question__passage-dropdown-passage"
164
- :class="{
165
- 'uikit-question__passage-dropdown-passage--with-image': passageImageUrl,
166
- }"
167
- v-html="question.passage"
168
- />
169
- <img
170
- v-if="passageImageUrl"
171
- v-dark="isDarkMode"
172
- class="uikit-question__image-dropdown-image"
173
- :class="{
174
- 'uikit-question__image-dropdown-image--with-passage': question.passage,
175
- }"
176
- :src="passageImageUrl"
177
- :alt="`${passageImageAlt}. Extended image description below.`"
178
- >
179
- <PocketButton
180
- v-if="passageImageLongAlt"
181
- v-breakpoint:questionEl="breakpoints"
182
- type="tertiary-small"
183
- class="uikit-question__toggle-img-dropdown-img-description"
184
- :class="{
185
- 'uikit-question__toggle-img-dropdown-img-description--open': showPassageImageLongAlt,
186
- }"
187
- :is-dark-mode="isDarkMode"
188
- :aria-expanded="showPassageImageLongAlt ? 'true' : 'false'"
189
- @click.stop="togglePassageImageLongAlt"
190
- @mousedown.prevent
191
- >
192
- <span class="uikit-question__toggle-img-dropdown-img-description-text">Image Description</span>
193
- <Icon
194
- class="uikit-question__toggle-img-dropdown-img-description-icon"
195
- :class="{
196
- 'uikit-question__toggle-img-dropdown-img-description-icon--up': showPassageImageLongAlt,
197
- }"
198
- type="accordionArrow"
199
- />
200
- </PocketButton>
201
- <div
202
- v-if="showPassageImageLongAlt"
203
- ref="uikit-question__img-dropdown-img-description"
204
- v-breakpoint:questionEl="breakpoints"
205
- v-dark="isDarkMode"
206
- class="uikit-question__img-dropdown-img-description"
207
- tabindex="-1"
208
- v-html="passageImageLongAlt"
209
- />
210
- </div>
211
- </div>
81
+ :question="question"
82
+ :question-el="questionEl"
83
+ :breakpoints="breakpoints"
84
+ :is-dark-mode="isDarkMode"
85
+ :review-mode="reviewMode"
86
+ :image-url-prefix="imageUrlPrefix"
87
+ :passage-image-url="passageImageUrl"
88
+ :passage-image-long-alt="passageImageLongAlt"
89
+ :passage-image-alt="passageImageAlt"
90
+ :passage-and-image-title="passageAndImageTitle"
91
+ @emitTogglePassageImageLongAlt="togglePassageImageLongAlt"
92
+ />
212
93
  <div
213
94
  v-if="showPaywall"
214
95
  class="uikit-question__paywall-container"
@@ -951,42 +832,20 @@
951
832
 
952
833
  <script lang="ts">
953
834
  import { Component, Vue, Prop, Watch, Emit } from 'vue-facing-decorator'
835
+ import type { ComponentPublicInstance } from 'vue'
954
836
  import PocketButton from '../Buttons/Button.vue'
955
837
  import Icon from '../Icons/Icon.vue'
956
838
  import type { ITableColumn, ITableSortSettings } from '../Tables/table'
957
839
  import Table from '../Tables/Table.vue'
958
840
  import OverflowTooltip from '../Tooltips/OverflowTooltip.vue'
841
+ import QuestionContext from '../Quiz/Question/QuestionContext.vue'
842
+ import PassageAndImageDropdown from '../Quiz/Question/PassageAndImageDropdown.vue'
959
843
  import type { Study } from '@pocketprep/types'
960
844
  import { breakpoint, dark } from '../../directives'
961
845
  import { studyModes } from '../../utils'
962
846
  import PaywallImageLight from '../../assets/question/paywall-light.png'
963
847
  import PaywallImageDark from '../../assets/question/paywall-dark.png'
964
-
965
- type TChoiceKey = `${'a' | 'd'}${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`
966
- type TChoice = { text?: string; key: TChoiceKey }
967
- type TChoiceScores = Partial<Record<TChoiceKey, number>> & {
968
- totalAnswered: number
969
- answeredCorrectly: number
970
- }
971
- type TQuizMode = 'qotd' | 'quick10' | 'timed' | 'weakest' | 'missed' | 'custom'
972
- type Ref = HTMLElement | null
973
- type TNamesRow = {
974
- id: string
975
- nameOne: string
976
- isFlaggedByNameOne: boolean
977
- nameTwo?: string
978
- isFlaggedByNameTwo?: boolean
979
- nameThree?: string
980
- isFlaggedByNameThree?: boolean
981
- }
982
-
983
- type TViewNames = {
984
- [ key: string ]: {
985
- id: string
986
- name: string
987
- isFlaggedByStudent: boolean
988
- }[]
989
- }
848
+ import type { Ref, TQuizMode, TChoiceKey, TChoice, TChoiceScores, TNamesRow, TViewNames } from './question'
990
849
 
991
850
  @Component({
992
851
  components: {
@@ -994,6 +853,8 @@ type TViewNames = {
994
853
  Icon,
995
854
  Table,
996
855
  OverflowTooltip,
856
+ QuestionContext,
857
+ PassageAndImageDropdown,
997
858
  },
998
859
  directives: {
999
860
  breakpoint,
@@ -1238,7 +1099,8 @@ export default class Question extends Vue {
1238
1099
  this.moveFocusToPrompt()
1239
1100
  } else if (this.autoFocusPrompt === false) {
1240
1101
  setTimeout(() => {
1241
- const contextEl = this.$refs['uikit-question__context'] as HTMLElement | undefined
1102
+ const contextComp = this.$refs['uikit-question__context'] as ComponentPublicInstance | undefined
1103
+ const contextEl = contextComp?.$refs['uikit-question-context'] as HTMLElement | undefined
1242
1104
  contextEl?.focus()
1243
1105
  }, 0)
1244
1106
  }
@@ -1500,12 +1362,17 @@ export default class Question extends Vue {
1500
1362
 
1501
1363
  if (this.showPassageImageLongAlt) {
1502
1364
  setTimeout(() => {
1503
- const mobileLongAlt = this.$refs['uikit-question__img-dropdown-img-description'] as Ref
1365
+ const mobileLongAltComp =
1366
+ this.$refs['uikit-question__passage-and-image-dropdown'] as ComponentPublicInstance | undefined
1367
+ const mobileImgDropdownImgDescription =
1368
+ // eslint-disable-next-line max-len
1369
+ mobileLongAltComp?.$refs['uikit-question-passage-and-image-dropdown__img-dropdown-img-description'] as HTMLElement | undefined
1370
+
1504
1371
  const longAlt = this.$refs['uikit-question__passage-image-description'] as Ref
1505
1372
 
1506
1373
  // Checking offsetParent tells us which element is visible
1507
- if (mobileLongAlt?.offsetParent) {
1508
- mobileLongAlt.focus()
1374
+ if (mobileImgDropdownImgDescription?.offsetParent) {
1375
+ mobileImgDropdownImgDescription.focus()
1509
1376
  } else if (longAlt?.offsetParent) {
1510
1377
  longAlt.focus()
1511
1378
  }
@@ -1865,7 +1732,6 @@ export default class Question extends Vue {
1865
1732
 
1866
1733
  &__toggle-passage-image-description-text,
1867
1734
  &__toggle-explanation-img-description-text,
1868
- &__toggle-img-dropdown-img-description-text,
1869
1735
  &__toggle-dropdown-explanation-img-description-text,
1870
1736
  &__toggle-summary-dropdown-explanation-img-description-text {
1871
1737
  outline: none;
@@ -1873,7 +1739,6 @@ export default class Question extends Vue {
1873
1739
 
1874
1740
  &__toggle-passage-image-description-icon,
1875
1741
  &__toggle-explanation-img-description-icon,
1876
- &__toggle-img-dropdown-img-description-icon,
1877
1742
  &__toggle-dropdown-explanation-img-description-icon,
1878
1743
  &__toggle-summary-dropdown-explanation-img-description-icon {
1879
1744
  margin-left: 8px;
@@ -2091,66 +1956,6 @@ export default class Question extends Vue {
2091
1956
  font-weight: 600;
2092
1957
  }
2093
1958
 
2094
- &__context {
2095
- display: flex;
2096
- flex-direction: column;
2097
- align-items: center;
2098
- flex-shrink: 0;
2099
- margin-bottom: 28px;
2100
- padding-top: 60px;
2101
- outline: none;
2102
-
2103
- &--tablet-landscape {
2104
- padding-top: 42px;
2105
- }
2106
-
2107
- &--tablet-portrait {
2108
- padding-top: 52px;
2109
- }
2110
-
2111
- &--mobile {
2112
- padding-top: 22px;
2113
- }
2114
- }
2115
-
2116
- &__context-icon {
2117
- margin-bottom: 8px;
2118
- margin-left: 6px;
2119
- color: $ash;
2120
-
2121
- &--dark {
2122
- color: $fog;
2123
- }
2124
- }
2125
-
2126
- &__context-text {
2127
- display: flex;
2128
- font-size: 14px;
2129
- font-weight: 600;
2130
- letter-spacing: 0.2px;
2131
- line-height: 17px;
2132
- color: $ash;
2133
- margin: 0;
2134
-
2135
- &--dark {
2136
- color: $fog;
2137
- }
2138
- }
2139
-
2140
- &__quiz-length {
2141
- margin-left: 5px;
2142
- font-weight: 500;
2143
- }
2144
-
2145
- &__tag {
2146
- margin-top: 8px;
2147
- margin-bottom: -5px;
2148
-
2149
- &--mobile {
2150
- display: none;
2151
- }
2152
- }
2153
-
2154
1959
  &__tag-mobile {
2155
1960
  display: none;
2156
1961
  position: absolute;
@@ -2256,182 +2061,6 @@ export default class Question extends Vue {
2256
2061
  }
2257
2062
  }
2258
2063
 
2259
- &__passage-and-image-dropdown-btn {
2260
- position: relative;
2261
- display: flex;
2262
- align-items: center;
2263
- border: 1px solid rgba($pewter, 0.85);
2264
- border-radius: 5px;
2265
- box-shadow: 0 1px 4px 0 rgba($ash, 0.3);
2266
- box-sizing: border-box;
2267
- height: 50px;
2268
- padding: 15px 57px 16px 48px;
2269
- margin: -1px;
2270
- cursor: pointer;
2271
- outline: none;
2272
-
2273
- &:hover {
2274
- .uikit-question__passage-and-image-dropdown-text {
2275
- color: mix($brand-blue, black, 90%);
2276
- }
2277
-
2278
- .uikit-question__passage-and-image-dropdown-arrow {
2279
- color: mix($brand-blue, black, 90%);
2280
- }
2281
-
2282
- &::before {
2283
- content: '';
2284
- left: -2px;
2285
- top: -2px;
2286
- width: 100%;
2287
- height: 100%;
2288
- border: 2px solid $slate;
2289
- position: absolute;
2290
- border-radius: 5px;
2291
- }
2292
- }
2293
-
2294
- &:focus::before {
2295
- content: '';
2296
- left: -3px;
2297
- top: -3px;
2298
- width: calc(100% + 4px);
2299
- height: calc(100% + 4px);
2300
- border: 1px solid $brand-blue;
2301
- position: absolute;
2302
- border-radius: 8px;
2303
- }
2304
-
2305
- &--dark {
2306
- box-shadow: 0 1px 4px 0 rgba($jet, 0.3);
2307
- border-color: $slate;
2308
-
2309
- &:hover {
2310
- .uikit-question__passage-and-image-dropdown-text {
2311
- color: $butterscotch;
2312
- }
2313
-
2314
- .uikit-question__passage-and-image-dropdown-arrow {
2315
- color: $butterscotch;
2316
- }
2317
-
2318
- &::before {
2319
- border-color: rgba($white, 0.6);
2320
- }
2321
- }
2322
-
2323
- &:focus::before {
2324
- border-color: $banana-bread;
2325
- }
2326
- }
2327
- }
2328
-
2329
- &__passage-and-image-dropdown-text {
2330
- font-size: 16px;
2331
- line-height: 24px;
2332
- font-weight: 600;
2333
- color: $brand-blue;
2334
-
2335
- &--dark {
2336
- color: $banana-bread;
2337
- }
2338
- }
2339
-
2340
- &__passage-dropdown-icon,
2341
- &__image-dropdown-icon {
2342
- position: absolute;
2343
- left: 17px;
2344
- width: 19px;
2345
- }
2346
-
2347
- &__passage-and-image-dropdown-arrow {
2348
- position: absolute;
2349
- right: 20px;
2350
- color: $brand-blue;
2351
-
2352
- &--dark {
2353
- color: $banana-bread;
2354
- }
2355
-
2356
- &--up {
2357
- transform: rotate(180deg);
2358
- }
2359
- }
2360
-
2361
- &__passage-and-image-dropdown-container {
2362
- padding: 14px 15px 16px 16px;
2363
-
2364
- &--mobile {
2365
- padding: 12px 15px 16px 15px;
2366
- }
2367
- }
2368
-
2369
- &__passage-dropdown-passage {
2370
- box-sizing: border-box;
2371
- margin: 14px 20px 24px 17px;
2372
- line-height: 24px;
2373
- font-size: 16px;
2374
- font-weight: 400;
2375
- letter-spacing: -0.1;
2376
-
2377
- &--mobile {
2378
- line-height: 24px;
2379
- font-size: 16px;
2380
- }
2381
-
2382
- &--with-image {
2383
- margin-bottom: 16px;
2384
- }
2385
- }
2386
-
2387
- &__image-dropdown-image {
2388
- display: block;
2389
- box-sizing: border-box;
2390
- width: 100%;
2391
- border: 1px solid $fog;
2392
-
2393
- &--with-passage {
2394
- padding-top: 0;
2395
- }
2396
-
2397
- &--dark {
2398
- border: 1px solid $jet;
2399
- }
2400
- }
2401
-
2402
- &__toggle-img-dropdown-img-description {
2403
- margin-top: 16px;
2404
-
2405
- &--open {
2406
- margin-bottom: 8px;
2407
- }
2408
- }
2409
-
2410
- &__img-dropdown-img-description {
2411
- outline: none;
2412
- color: $ash;
2413
- font-size: 15px;
2414
- line-height: 22px;
2415
- font-weight: 500;
2416
- letter-spacing: -0.2;
2417
-
2418
- &--dark {
2419
- color: $fog;
2420
- }
2421
-
2422
- &--tablet-landscape {
2423
- margin-bottom: 4px;
2424
- }
2425
-
2426
- &--tablet-portrait {
2427
- margin-bottom: 0;
2428
- }
2429
-
2430
- p {
2431
- margin: 0;
2432
- }
2433
- }
2434
-
2435
2064
  &__unanswered-teach-review-label {
2436
2065
  margin-bottom: 12px;
2437
2066
  display: flex;
@@ -0,0 +1,41 @@
1
+ export type Ref = HTMLElement | null
2
+
3
+ export type TChoiceKey = `${'a' | 'd'}${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`
4
+
5
+ export type TQuizMode = 'qotd' | 'quick10' | 'timed' | 'weakest' | 'missed' | 'custom'
6
+
7
+ // eslint-disable-next-line max-len
8
+ export type TContextIcon = 'quick10' | 'calendar' | 'missedQuestions' | 'subject' | 'stopwatch' | 'exam' | 'levelup' | 'pencil'
9
+
10
+ export type TBreakPointsObject = {
11
+ mobile: number
12
+ tabletPortrait: number
13
+ tabletLandscape: number
14
+ }
15
+
16
+ export type TChoice = { text?: string; key: TChoiceKey }
17
+
18
+ export type TChoiceScores = Partial<Record<TChoiceKey, number>> & {
19
+ totalAnswered: number
20
+ answeredCorrectly: number
21
+ }
22
+
23
+ export type TQuestionPassageAndImageTitle = 'Passage + Image' | 'Image' | 'Passage'
24
+
25
+ export type TNamesRow = {
26
+ id: string
27
+ nameOne: string
28
+ isFlaggedByNameOne: boolean
29
+ nameTwo?: string
30
+ isFlaggedByNameTwo?: boolean
31
+ nameThree?: string
32
+ isFlaggedByNameThree?: boolean
33
+ }
34
+
35
+ export type TViewNames = {
36
+ [ key: string ]: {
37
+ id: string
38
+ name: string
39
+ isFlaggedByStudent: boolean
40
+ }[]
41
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pocketprep/ui-kit",
3
- "version": "3.4.1",
3
+ "version": "3.4.3",
4
4
  "description": "Pocket Prep UI Kit",
5
5
  "author": "pocketprep",
6
6
  "scripts": {