@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
@@ -5,43 +5,45 @@
5
5
  v-dark="isDarkMode"
6
6
  class="uikit-quiz-container"
7
7
  >
8
- <div
9
- v-breakpoint:quizContainerEl
10
- class="uikit-quiz-container__header"
11
- :class="{'uikit-quiz-container__header--dark': isDarkMode}"
12
- :style="customHeaderStyles"
13
- >
14
- <slot name="header" />
15
- </div>
16
- <div class="uikit-quiz-container__main" :style="customMainStyles">
8
+ <template v-if="quizContainerEl">
17
9
  <div
18
- v-if="showSide"
19
- v-breakpoint:quizContainerEl
20
- v-dark="isDarkMode"
21
- class="uikit-quiz-container__side"
10
+ v-breakpoint="{ containerEl: quizContainerEl }"
11
+ class="uikit-quiz-container__header"
12
+ :class="{'uikit-quiz-container__header--dark': isDarkMode}"
13
+ :style="customHeaderStyles"
22
14
  >
23
- <slot name="definition"></slot>
24
- <slot name="side" />
15
+ <slot name="header" />
16
+ </div>
17
+ <div class="uikit-quiz-container__main" :style="customMainStyles">
18
+ <div
19
+ v-if="showSide"
20
+ v-breakpoint="{ containerEl: quizContainerEl }"
21
+ v-dark="isDarkMode"
22
+ class="uikit-quiz-container__side"
23
+ >
24
+ <slot name="definition"></slot>
25
+ <slot name="side" />
26
+ </div>
27
+ <div
28
+ v-breakpoint="{ containerEl: quizContainerEl }"
29
+ class="uikit-quiz-container__question"
30
+ :class="{
31
+ 'uikit-quiz-container__question--show-side': showSide,
32
+ 'uikit-quiz-container__question--dark': isDarkMode
33
+ }"
34
+ >
35
+ <slot name="question" />
36
+ </div>
25
37
  </div>
26
38
  <div
27
- v-breakpoint:quizContainerEl
28
- class="uikit-quiz-container__question"
29
- :class="{
30
- 'uikit-quiz-container__question--show-side': showSide,
31
- 'uikit-quiz-container__question--dark': isDarkMode
32
- }"
39
+ v-breakpoint="{ containerEl: quizContainerEl }"
40
+ class="uikit-quiz-container__footer"
41
+ :class="{'uikit-quiz-container__footer--dark': isDarkMode}"
42
+ :style="customFooterStyles"
33
43
  >
34
- <slot name="question" />
44
+ <slot name="footer" />
35
45
  </div>
36
- </div>
37
- <div
38
- v-breakpoint:quizContainerEl
39
- class="uikit-quiz-container__footer"
40
- :class="{'uikit-quiz-container__footer--dark': isDarkMode}"
41
- :style="customFooterStyles"
42
- >
43
- <slot name="footer" />
44
- </div>
46
+ </template>
45
47
  </div>
46
48
  </template>
47
49
 
@@ -66,9 +68,7 @@ export default class QuizContainer extends Vue {
66
68
  @Prop({ default: () => ({}) }) customMainStyles!: Record<string, string>
67
69
  @Prop({ default: () => ({}) }) customFooterStyles!: Record<string, string>
68
70
 
69
- get quizContainerEl () {
70
- return this.$refs['quiz-container']
71
- }
71
+ quizContainerEl: HTMLElement | null = null
72
72
 
73
73
  beforeUnmount () {
74
74
  const bodyEl = document.getElementsByTagName('body')[0]
@@ -82,6 +82,8 @@ export default class QuizContainer extends Vue {
82
82
  if (bodyEl) {
83
83
  bodyEl.style.overflow = 'hidden'
84
84
  }
85
+ const quizContainerEl = this.$refs['quiz-container'] as HTMLElement || null
86
+ this.quizContainerEl = quizContainerEl
85
87
  }
86
88
  }
87
89
  </script>
@@ -6,12 +6,12 @@ export type TMatrixChoiceKey = `${'a' | 'd'}${1 | 2 | 3 }_${1 | 2 | 3 | 4 | 5 |
6
6
  export type TQuizMode = 'qotd' | 'quick10' | 'timed' | 'weakest' | 'missed' | 'custom'
7
7
 
8
8
  // eslint-disable-next-line max-len
9
- export type TContextIcon = 'quick10' | 'calendar' | 'missedQuestions' | 'subject' | 'stopwatch' | 'exam' | 'levelup' | 'pencil'
9
+ export type TContextIcon = 'quick10' | 'calendar' | 'missedQuestions' | 'subject' | 'stopwatch' | 'exam' | 'levelup' | 'pencil' | 'link'
10
10
 
11
11
  export type TBreakPointsObject = {
12
- mobile: number
13
- tabletPortrait: number
14
- tabletLandscape: number
12
+ 'mobile': number
13
+ 'tablet-portrait': number
14
+ 'tablet-landscape': number
15
15
  }
16
16
 
17
17
  export type TChoice = { text?: string; key: TChoiceKey }
package/lib/directives.ts CHANGED
@@ -4,7 +4,11 @@ import { ResizeObserver as ResizeObserverPonyFill } from 'resize-observer'
4
4
 
5
5
  type TBreakpoints = { [breakpointName: string]: number }
6
6
 
7
- const updateBreakpointClasses = (el: HTMLElement, breakpoints?: TBreakpoints, container?: HTMLElement) => {
7
+ const updateBreakpointClasses = (
8
+ el: HTMLElement,
9
+ breakpointsWithEl?: { breakpoints?: TBreakpoints; containerEl?: HTMLElement | null },
10
+ container?: HTMLElement | null
11
+ ) => {
8
12
  // calculate screen width
9
13
  const mediaBreakpoints: string[] = []
10
14
  if (window.matchMedia(`(max-width: ${MediaBreakpoints.blackBear}px)`).matches) {
@@ -20,24 +24,20 @@ const updateBreakpointClasses = (el: HTMLElement, breakpoints?: TBreakpoints, co
20
24
  const customBreakpoints: string[] = []
21
25
 
22
26
  // If no custom breakpoints passed, use default breakpoints that match design's
23
- if (!breakpoints) {
24
- breakpoints = {
25
- 'mobile': Number(MediaBreakpoints.blackBear),
26
- 'tablet-portrait': Number(MediaBreakpoints.brownBear),
27
- 'tablet-landscape': Number(MediaBreakpoints.grizzlyBear),
28
- 'desktop': Number(MediaBreakpoints.polarBear),
29
- }
27
+ const appliedBreakpoints = breakpointsWithEl?.breakpoints || {
28
+ 'mobile': Number(MediaBreakpoints.blackBear),
29
+ 'tablet-portrait': Number(MediaBreakpoints.brownBear),
30
+ 'tablet-landscape': Number(MediaBreakpoints.grizzlyBear),
31
+ 'desktop': Number(MediaBreakpoints.polarBear),
30
32
  }
31
33
 
32
- if (breakpoints) {
33
- Object.entries(breakpoints)
34
- .forEach(([ name, width ]) => {
35
- breakpointSuffixes.push(name)
36
- if (elWidth <= width) {
37
- customBreakpoints.push(name)
38
- }
39
- })
40
- }
34
+ Object.entries(appliedBreakpoints)
35
+ .forEach(([ name, width ]) => {
36
+ breakpointSuffixes.push(name)
37
+ if (elWidth <= width) {
38
+ customBreakpoints.push(name)
39
+ }
40
+ })
41
41
 
42
42
  const classes = el.getAttribute('class')?.split(' ') || []
43
43
  const nonModifierClasses = classes.filter(className => !className.includes('--'))
@@ -65,10 +65,12 @@ const updateBreakpointClasses = (el: HTMLElement, breakpoints?: TBreakpoints, co
65
65
  }
66
66
  }
67
67
 
68
- const getCustomContainer = (binding: DirectiveBinding) => {
69
- const bindingArg = binding.arg
70
- const container = bindingArg && binding.instance && binding.instance[bindingArg as keyof typeof binding.instance]
71
- return container
68
+ const getCustomContainer = (binding: DirectiveBinding<{
69
+ breakpoints?: TBreakpoints
70
+ containerEl?: HTMLElement | null
71
+ } | undefined>) => {
72
+ const container = binding.value?.containerEl
73
+ return container || null
72
74
  }
73
75
 
74
76
  const eventListeners: Partial<Record<string, () => void>> = {}
@@ -105,7 +107,10 @@ export const fixed: Directive = {
105
107
  },
106
108
  }
107
109
 
108
- export const breakpoint: Directive = {
110
+ export const breakpoint: Directive<HTMLElement, {
111
+ breakpoints?: TBreakpoints
112
+ containerEl?: HTMLElement | null
113
+ } | undefined> = {
109
114
  beforeMount (el, binding) {
110
115
  if (!el.dataset.breakpointId) {
111
116
  binding.instance?.$nextTick(() => {
@@ -7,29 +7,23 @@ $teddy-bear: 319;
7
7
 
8
8
  @mixin breakpoint($point) {
9
9
  @if $point == 'polar-bear' {
10
- @media (max-width: $polar-bear + 'px') { @content; }
10
+ @media (max-width: ($polar-bear + 'px')) { @content; }
11
11
  }
12
-
13
12
  @else if $point == 'grizzly-bear' {
14
- @media (max-width: $grizzly-bear + 'px') { @content; }
13
+ @media (max-width: ($grizzly-bear + 'px')) { @content; }
15
14
  }
16
-
17
15
  @else if $point == 'brown-bear' {
18
- @media (max-width: $brown-bear + 'px') { @content; }
16
+ @media (max-width: ($brown-bear + 'px')) { @content; }
19
17
  }
20
-
21
18
  @else if $point == 'black-bear' {
22
- @media (max-width: $black-bear + 'px') { @content; }
19
+ @media (max-width: ($black-bear + 'px')) { @content; }
23
20
  }
24
-
25
21
  @else if $point == 'koala-bear' {
26
- @media (max-width: $koala-bear + 'px') { @content; }
22
+ @media (max-width: ($koala-bear + 'px')) { @content; }
27
23
  }
28
-
29
24
  @else if $point == 'teddy-bear' {
30
- @media (max-width: $teddy-bear + 'px') { @content; }
25
+ @media (max-width: ($teddy-bear + 'px')) { @content; }
31
26
  }
32
-
33
27
  @else {
34
28
  @media (max-width: $point) { @content; }
35
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pocketprep/ui-kit",
3
- "version": "3.4.89",
3
+ "version": "3.5.0",
4
4
  "description": "Pocket Prep UI Kit",
5
5
  "author": "pocketprep",
6
6
  "scripts": {
@@ -9,7 +9,7 @@
9
9
  "build-only": "vite build && vite build --config vite.config.docs.ts",
10
10
  "preview": "vite preview --config vite.config.docs.ts",
11
11
  "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --ignore-path .gitignore && stylelint '**/*.{scss,vue}'",
12
- "type-check": "vue-tsc --noEmit -p tsconfig.json --composite false",
12
+ "type-check": "vue-tsc --noEmit -p tsconfig.cypress-ct.json --composite false",
13
13
  "test:e2e": "start-server-and-test preview :4173 'cypress run --e2e'",
14
14
  "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' :4173 'cypress open --e2e'",
15
15
  "test:unit": "cypress run --component",
@@ -73,7 +73,7 @@
73
73
  "highcharts": "10.3.3",
74
74
  "litepicker": "2.0.12",
75
75
  "resize-observer": "1.0.4",
76
- "vue": "3.4.15",
76
+ "vue": "3.5.13",
77
77
  "vue-facing-decorator": "2.1.20",
78
78
  "vue-router": "4.2.5"
79
79
  },
@@ -87,7 +87,7 @@
87
87
  "cypress": "12.0.2",
88
88
  "eslint": "8.34.0",
89
89
  "eslint-plugin-cypress": "2.12.1",
90
- "eslint-plugin-vue": "9.9.0",
90
+ "eslint-plugin-vue": "9.32.0",
91
91
  "npm-run-all": "4.1.5",
92
92
  "postcss-html": "1.5.0",
93
93
  "sass": "1.58.3",