@pocketprep/ui-kit 3.8.5 → 3.9.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 (159) hide show
  1. package/dist/@pocketprep/ui-kit.css +1 -1
  2. package/dist/@pocketprep/ui-kit.js +14466 -17728
  3. package/dist/@pocketprep/ui-kit.js.map +1 -1
  4. package/dist/@pocketprep/ui-kit.umd.cjs +19 -29
  5. package/dist/@pocketprep/ui-kit.umd.cjs.map +1 -1
  6. package/eslint.config.ts +38 -11
  7. package/lib/SVGDefinitions.vue +32 -35
  8. package/lib/components/Banners/Banner.vue +10 -14
  9. package/lib/components/Blobs/Blob.vue +6 -14
  10. package/lib/components/Blobs/BlobEmptyState.vue +9 -8
  11. package/lib/components/Blobs/blob.d.ts +1 -1
  12. package/lib/components/BundleIcons/BundleIcon.vue +36 -63
  13. package/lib/components/BundleIcons/bundleIcon.d.ts +1 -1
  14. package/lib/components/Bundles/BundleList.vue +71 -59
  15. package/lib/components/Bundles/BundleSearch.vue +93 -117
  16. package/lib/components/Bundles/PremiumPill.vue +6 -12
  17. package/lib/components/Buttons/Button.vue +32 -35
  18. package/lib/components/Buttons/Link.vue +32 -31
  19. package/lib/components/Buttons/Tab.vue +14 -17
  20. package/lib/components/Calendar/Calendar.vue +87 -85
  21. package/lib/components/Charts/Bar.vue +192 -263
  22. package/lib/components/Charts/Pie.vue +55 -61
  23. package/lib/components/Charts/highcharts-wrap.ts +81 -0
  24. package/lib/components/Controls/SegmentControl.vue +26 -24
  25. package/lib/components/Controls/Slider.vue +51 -47
  26. package/lib/components/Controls/ToggleSwitch.vue +33 -31
  27. package/lib/components/EmptyStates/EmptyState.vue +69 -73
  28. package/lib/components/Exams/ExamCard.vue +59 -47
  29. package/lib/components/Exams/ExamMenuCard.vue +30 -28
  30. package/lib/components/Filters/FilterDropdown.vue +83 -86
  31. package/lib/components/Filters/FilterOptions.vue +83 -88
  32. package/lib/components/Forms/Checkbox.vue +27 -27
  33. package/lib/components/Forms/CheckboxOption.vue +30 -30
  34. package/lib/components/Forms/Errors.vue +21 -24
  35. package/lib/components/Forms/Input.vue +71 -59
  36. package/lib/components/Forms/Radio.vue +2 -2
  37. package/lib/components/Forms/RadioButton.vue +8 -8
  38. package/lib/components/Forms/Select.vue +265 -257
  39. package/lib/components/Forms/Textarea.vue +49 -35
  40. package/lib/components/Icons/IconAccordionArrow.vue +7 -9
  41. package/lib/components/Icons/IconActivity.vue +7 -9
  42. package/lib/components/Icons/IconAdd.vue +7 -11
  43. package/lib/components/Icons/IconAddCircle.vue +7 -9
  44. package/lib/components/Icons/IconArrow.vue +7 -9
  45. package/lib/components/Icons/IconBarChart.vue +7 -9
  46. package/lib/components/Icons/IconCalendar.vue +7 -9
  47. package/lib/components/Icons/IconCalendarPicker.vue +7 -9
  48. package/lib/components/Icons/IconChat.vue +7 -9
  49. package/lib/components/Icons/IconCheck.vue +7 -9
  50. package/lib/components/Icons/IconClose.vue +7 -9
  51. package/lib/components/Icons/IconConcept.vue +1 -1
  52. package/lib/components/Icons/IconCorrect.vue +7 -9
  53. package/lib/components/Icons/IconEdit.vue +7 -11
  54. package/lib/components/Icons/IconExam.vue +7 -9
  55. package/lib/components/Icons/IconExternalLink.vue +7 -9
  56. package/lib/components/Icons/IconEyeHide.vue +7 -9
  57. package/lib/components/Icons/IconEyeShow.vue +7 -9
  58. package/lib/components/Icons/IconFilter.vue +7 -9
  59. package/lib/components/Icons/IconFilterActive.vue +7 -9
  60. package/lib/components/Icons/IconFlag.vue +7 -9
  61. package/lib/components/Icons/IconFlagContent.vue +8 -9
  62. package/lib/components/Icons/IconFlagFeedback.vue +8 -10
  63. package/lib/components/Icons/IconFlagFilled.vue +7 -9
  64. package/lib/components/Icons/IconFullView.vue +7 -9
  65. package/lib/components/Icons/IconFullViewActive.vue +7 -9
  66. package/lib/components/Icons/IconGridDrag.vue +2 -2
  67. package/lib/components/Icons/IconHandle.vue +7 -9
  68. package/lib/components/Icons/IconHeart.vue +7 -9
  69. package/lib/components/Icons/IconHelp.vue +7 -9
  70. package/lib/components/Icons/IconHighlight.vue +2 -2
  71. package/lib/components/Icons/IconHourglass.vue +7 -9
  72. package/lib/components/Icons/IconImage.vue +7 -9
  73. package/lib/components/Icons/IconIncorrect.vue +7 -9
  74. package/lib/components/Icons/IconInfo.vue +7 -9
  75. package/lib/components/Icons/IconKeyboard.vue +7 -9
  76. package/lib/components/Icons/IconLaunch.vue +7 -9
  77. package/lib/components/Icons/IconLevelUp.vue +7 -9
  78. package/lib/components/Icons/IconLightbulb.vue +7 -9
  79. package/lib/components/Icons/IconLightning.vue +7 -9
  80. package/lib/components/Icons/IconLink.vue +7 -9
  81. package/lib/components/Icons/IconList.vue +7 -9
  82. package/lib/components/Icons/IconLoading.vue +7 -9
  83. package/lib/components/Icons/IconLoading2.vue +11 -11
  84. package/lib/components/Icons/IconLock.vue +7 -9
  85. package/lib/components/Icons/IconMissedQuestions.vue +7 -9
  86. package/lib/components/Icons/IconMoon.vue +7 -9
  87. package/lib/components/Icons/IconPaginationArrow.vue +7 -9
  88. package/lib/components/Icons/IconPaginationArrowDouble.vue +7 -9
  89. package/lib/components/Icons/IconPassage.vue +7 -9
  90. package/lib/components/Icons/IconPencil.vue +7 -9
  91. package/lib/components/Icons/IconPeople.vue +7 -9
  92. package/lib/components/Icons/IconPercent.vue +7 -9
  93. package/lib/components/Icons/IconPerson.vue +8 -9
  94. package/lib/components/Icons/IconPresent.vue +7 -9
  95. package/lib/components/Icons/IconPreview.vue +7 -9
  96. package/lib/components/Icons/IconQuestions.vue +7 -9
  97. package/lib/components/Icons/IconQuick10.vue +7 -9
  98. package/lib/components/Icons/IconQuickActions.vue +2 -2
  99. package/lib/components/Icons/IconRecommendedFilter.vue +1 -1
  100. package/lib/components/Icons/IconRemoveCircle.vue +7 -9
  101. package/lib/components/Icons/IconReviewFlag.vue +7 -9
  102. package/lib/components/Icons/IconSearch.vue +7 -9
  103. package/lib/components/Icons/IconShare.vue +7 -9
  104. package/lib/components/Icons/IconSideBar.vue +7 -9
  105. package/lib/components/Icons/IconSideBarActive.vue +7 -9
  106. package/lib/components/Icons/IconStar.vue +1 -1
  107. package/lib/components/Icons/IconStopwatch.vue +7 -9
  108. package/lib/components/Icons/IconStrike.vue +7 -9
  109. package/lib/components/Icons/IconSubject.vue +7 -9
  110. package/lib/components/Icons/IconText.vue +7 -9
  111. package/lib/components/Icons/IconTimer.vue +8 -9
  112. package/lib/components/Icons/IconWarning.vue +7 -9
  113. package/lib/components/Icons/icon.d.ts +1 -1
  114. package/lib/components/Loaders/SkeletonLoader.vue +1 -5
  115. package/lib/components/Modal/Modal.vue +23 -29
  116. package/lib/components/Modal/ModalContainer.vue +135 -135
  117. package/lib/components/Onboarding/EmailAuth.vue +66 -70
  118. package/lib/components/Onboarding/MagicCodeEntry.vue +88 -83
  119. package/lib/components/Pagination/QuestionReviewPagination.vue +3 -3
  120. package/lib/components/Pagination/TablePagination.vue +47 -44
  121. package/lib/components/PhonePerson/PhonePerson.vue +18 -18
  122. package/lib/components/PhonePerson/phonePerson.d.ts +1 -1
  123. package/lib/components/Quiz/FlagToggle.vue +45 -44
  124. package/lib/components/Quiz/GlobalMetricsToggle.vue +29 -28
  125. package/lib/components/Quiz/KeyboardShortcutsButton.vue +16 -23
  126. package/lib/components/Quiz/KeyboardShortcutsModal.vue +36 -37
  127. package/lib/components/Quiz/Question/BuildListChoicesContainer.vue +65 -65
  128. package/lib/components/Quiz/Question/ChoicesContainer.vue +5 -5
  129. package/lib/components/Quiz/Question/DropdownExplanation.vue +5 -5
  130. package/lib/components/Quiz/Question/Explanation.vue +6 -6
  131. package/lib/components/Quiz/Question/MPMCChoicesContainer.vue +17 -17
  132. package/lib/components/Quiz/Question/MPMCRadioGroup.vue +2 -2
  133. package/lib/components/Quiz/Question/MatrixChoicesContainer.vue +39 -39
  134. package/lib/components/Quiz/Question/MatrixRadioGroup.vue +6 -6
  135. package/lib/components/Quiz/Question/MobileMatrixChoicesContainer.vue +27 -28
  136. package/lib/components/Quiz/Question/MobileMatrixRadioGroup.vue +2 -2
  137. package/lib/components/Quiz/Question/PassageAndImage.vue +3 -3
  138. package/lib/components/Quiz/Question/PassageAndImageDropdown.vue +7 -7
  139. package/lib/components/Quiz/Question/Paywall.vue +2 -2
  140. package/lib/components/Quiz/Question/QuestionContext.vue +1 -1
  141. package/lib/components/Quiz/Question/StatsSummary.vue +2 -2
  142. package/lib/components/Quiz/Question/Summary.vue +11 -11
  143. package/lib/components/Quiz/Question.vue +90 -82
  144. package/lib/components/Quiz/QuizContainer.vue +1 -1
  145. package/lib/components/Quiz/QuizProgressBar.vue +23 -23
  146. package/lib/components/Quiz/question.d.ts +3 -3
  147. package/lib/components/Search/Pill.vue +16 -19
  148. package/lib/components/Search/Search.vue +52 -47
  149. package/lib/components/SidePanels/SidePanel.vue +168 -174
  150. package/lib/components/Tables/Table.vue +135 -122
  151. package/lib/components/Tables/TableActions.vue +81 -76
  152. package/lib/components/Tables/table.d.ts +1 -1
  153. package/lib/components/Tags/Tag.vue +49 -39
  154. package/lib/components/Toasts/Toast.vue +44 -42
  155. package/lib/components/Tooltips/OverflowTooltip.vue +39 -45
  156. package/lib/components/Tooltips/Tooltip.vue +69 -70
  157. package/lib/directives.ts +4 -4
  158. package/lib/utils.ts +13 -12
  159. package/package.json +27 -28
@@ -11,7 +11,7 @@
11
11
  @keydown="keydownListener"
12
12
  >
13
13
  <div
14
- class="uikit-modal-container__clickable"
14
+ class="uikit-modal-container__clickable"
15
15
  @click.self="emitClose"
16
16
  @mousedown.self.prevent
17
17
  />
@@ -33,162 +33,162 @@
33
33
  </div>
34
34
  </template>
35
35
 
36
- <script lang="ts">
37
- import { Vue, Component, Prop, Emit, Watch } from 'vue-facing-decorator'
36
+ <script setup lang="ts">
38
37
  import Modal from '../Modal/Modal.vue'
39
- import { dark } from '../../directives'
40
-
41
- @Component({
42
- directives: {
43
- dark,
44
- },
45
- components: {
46
- Modal,
47
- },
48
- })
49
- export default class ModalContainer extends Vue {
50
- @Prop({ default: false }) showCloseButton!: boolean
51
- @Prop({ default: () => ({}) }) customCloseStyles?: { [key: string]: unknown }
52
- @Prop({ default: false }) isDarkMode!: boolean
53
- @Prop({ default: true }) trapFocus!: boolean
54
- @Prop({ default: false }) removeHeadBorderBottom!: boolean
55
-
56
- focusListener: Parameters<typeof addEventListener>[1] | null = null
57
- savedYPosition = 0
58
- modalNumber = 0
59
-
60
- numberOfModals () {
61
- return document.querySelectorAll('.uikit-modal-container').length
38
+ import { dark as vDark } from '../../directives'
39
+ import { onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from 'vue'
40
+
41
+ const {
42
+ showCloseButton = false,
43
+ customCloseStyles = {},
44
+ isDarkMode = false,
45
+ trapFocus = true,
46
+ removeHeadBorderBottom = false,
47
+ } = defineProps<{
48
+ showCloseButton?: boolean
49
+ customCloseStyles?: Record<string, string>
50
+ isDarkMode?: boolean
51
+ trapFocus?: boolean
52
+ removeHeadBorderBottom?: boolean
53
+ }>()
54
+
55
+ const emit = defineEmits<{
56
+ 'close': []
57
+ 'mounted': []
58
+ 'unmounted': []
59
+ }>()
60
+
61
+ const focusListener = ref<Parameters<typeof addEventListener>[1] | null>(null)
62
+ const modalNumber = ref(0)
63
+
64
+ const modalContainerRef = useTemplateRef<HTMLElement>('modalContainer')
65
+
66
+ const numberOfModals = () => {
67
+ return document.querySelectorAll('.uikit-modal-container').length
68
+ }
69
+
70
+ onMounted(() => {
71
+ modalNumber.value = numberOfModals()
72
+ // Prevent an error where multiple modals trigger a loop
73
+ // TODO: Find a way to have only the latest modal's focusListener active
74
+
75
+ const focusableSelectors = 'button, [href], input, select, textarea, [tabindex]'
76
+
77
+ // Reset focus to last element in modal so next tab will move it to top
78
+ const modalContainerEl = modalContainerRef.value
79
+ const modalFocusableEls = modalContainerEl && Array.from<HTMLElement>(modalContainerEl
80
+ .querySelectorAll(focusableSelectors))
81
+ .filter(el => !('disabled' in el && el.disabled === true))
82
+ if (modalFocusableEls?.length) {
83
+ modalFocusableEls[modalFocusableEls.length - 1]?.focus()
84
+ modalFocusableEls[modalFocusableEls.length - 1]?.blur()
62
85
  }
63
86
 
64
- mounted () {
65
- this.modalNumber = this.numberOfModals()
66
- // Prevent an error where multiple modals trigger a loop
67
- // TODO: Find a way to have only the latest modal's focusListener active
68
-
69
- const focusableSelectors = 'button, [href], input, select, textarea, [tabindex]'
70
-
71
- // Reset focus to last element in modal so next tab will move it to top
72
- const modalContainerEl = this.$refs['modalContainer'] as HTMLElement
73
- const modalFocusableEls = Array.from<HTMLElement>(modalContainerEl
74
- .querySelectorAll(focusableSelectors))
75
- .filter(el => !('disabled' in el && el.disabled === true))
76
- if (modalFocusableEls.length) {
77
- modalFocusableEls[modalFocusableEls.length - 1]?.focus()
78
- modalFocusableEls[modalFocusableEls.length - 1]?.blur()
79
- }
80
-
81
-
82
- this.focusListener = event => {
83
- if (this.modalNumber === this.numberOfModals()) { // Only focus on the last open panel
84
- const target = (event as FocusEvent).target as HTMLElement // The element receiving focus
85
- const isFocusOutside = target && modalContainerEl && !modalContainerEl.contains(target)
86
- const hasCalendarClass = target?.classList
87
- && Array.from(target.classList).find(
88
- c => c === 'button-next-month' || c === 'button-previous-month' || c === 'day-item'
89
- )
90
- if (isFocusOutside && !hasCalendarClass) {
91
- const focusableModalChildren = Array.from<HTMLElement>(modalContainerEl.querySelectorAll(
92
- focusableSelectors
93
- ))
94
- const firstFocusableModalChild = focusableModalChildren.find(
95
- el => !!el.getBoundingClientRect().width
96
- )
97
- const reversedModalChildren = [ ...focusableModalChildren ].reverse()
98
- const lastFocusableModalChild = reversedModalChildren.find(
99
- el => !!el.getBoundingClientRect().width
100
- )
101
- if (firstFocusableModalChild) {
102
- const relatedTarget = (event as FocusEvent).relatedTarget // The element last focused
103
- if (relatedTarget === firstFocusableModalChild && lastFocusableModalChild) {
104
- // If focus moves from first element -> outside modal, focus the last element instead
105
- lastFocusableModalChild.focus()
106
- } else if (relatedTarget === lastFocusableModalChild && firstFocusableModalChild) {
107
- // If focus moves from last element -> outside modal, focus the first element instead
108
- firstFocusableModalChild.focus()
109
- } else if (relatedTarget && relatedTarget instanceof HTMLElement) {
110
- // If focus goes outside in a different way, return focus to where it came from if possible
111
- relatedTarget.focus()
112
- } else {
113
- // Otherwise, just return focus to the first element
114
- firstFocusableModalChild.focus()
115
- }
87
+ focusListener.value = event => {
88
+ if (modalNumber.value === numberOfModals()) { // Only focus on the last open panel
89
+ const target = (event as FocusEvent).target as HTMLElement // The element receiving focus
90
+ const isFocusOutside = target && modalContainerEl && !modalContainerEl.contains(target)
91
+ const hasCalendarClass = target?.classList
92
+ && Array.from(target.classList).find(
93
+ c => c === 'button-next-month' || c === 'button-previous-month' || c === 'day-item'
94
+ )
95
+ if (isFocusOutside && !hasCalendarClass) {
96
+ const focusableModalChildren = Array.from<HTMLElement>(modalContainerEl.querySelectorAll(
97
+ focusableSelectors
98
+ ))
99
+ const firstFocusableModalChild = focusableModalChildren.find(
100
+ el => !!el.getBoundingClientRect().width
101
+ )
102
+ const reversedModalChildren = [ ...focusableModalChildren ].reverse()
103
+ const lastFocusableModalChild = reversedModalChildren.find(
104
+ el => !!el.getBoundingClientRect().width
105
+ )
106
+ if (firstFocusableModalChild) {
107
+ const relatedTarget = (event as FocusEvent).relatedTarget // The element last focused
108
+ if (relatedTarget === firstFocusableModalChild && lastFocusableModalChild) {
109
+ // If focus moves from first element -> outside modal, focus the last element instead
110
+ lastFocusableModalChild.focus()
111
+ } else if (relatedTarget === lastFocusableModalChild && firstFocusableModalChild) {
112
+ // If focus moves from last element -> outside modal, focus the first element instead
113
+ firstFocusableModalChild.focus()
114
+ } else if (relatedTarget && relatedTarget instanceof HTMLElement) {
115
+ // If focus goes outside in a different way, return focus to where it came from if possible
116
+ relatedTarget.focus()
116
117
  } else {
117
- // If the modal doesn't have any focusable children, focus the container instead
118
- if (modalContainerEl.tabIndex === -1) {
119
- modalContainerEl.tabIndex = 0
120
- }
121
- modalContainerEl.focus()
118
+ // Otherwise, just return focus to the first element
119
+ firstFocusableModalChild.focus()
122
120
  }
121
+ } else {
122
+ // If the modal doesn't have any focusable children, focus the container instead
123
+ if (modalContainerEl.tabIndex === -1) {
124
+ modalContainerEl.tabIndex = 0
125
+ }
126
+ modalContainerEl.focus()
123
127
  }
124
128
  }
125
129
  }
126
- // Trap the user's focus within the modal - don't allow focusing elements behind the overlay
127
- if (this.trapFocus) {
128
- document.addEventListener('focusin', this.focusListener)
129
- }
130
-
131
- // prevent scrolling outside of modal
132
- const openModalCount = Number(document.body.getAttribute('data-openModalCount'))
133
- document.body.setAttribute('data-openModalCount', String(openModalCount + 1))
134
- document.body.classList.add('uikit-modal-open')
135
-
136
- this.emitMounted()
137
130
  }
138
-
139
- beforeUnmount () {
140
- if (this.focusListener) {
141
- document.removeEventListener('focusin', this.focusListener)
142
- }
143
-
144
- const openModalCount = Number(document.body.getAttribute('data-openModalCount'))
145
- document.body.setAttribute('data-openModalCount', String(openModalCount - 1))
146
- if (openModalCount <= 1) {
147
- document.body.classList.remove('uikit-modal-open')
148
- }
149
- this.emitUnmounted()
131
+ // Trap the user's focus within the modal - don't allow focusing elements behind the overlay
132
+ if (trapFocus) {
133
+ document.addEventListener('focusin', focusListener.value)
150
134
  }
151
135
 
152
- keydownListener (e: Event | KeyboardEvent) {
153
- if (!('key' in e)) {
154
- return
155
- }
136
+ // prevent scrolling outside of modal
137
+ const openModalCount = Number(document.body.getAttribute('data-openModalCount'))
138
+ document.body.setAttribute('data-openModalCount', String(openModalCount + 1))
139
+ document.body.classList.add('uikit-modal-open')
156
140
 
157
- if (e.key.match(/^[A-Za-z0-9\s\-_@]$/)) {
158
- e.stopPropagation()
159
- }
141
+ emitMounted()
142
+ })
160
143
 
161
- if (e.key === 'Escape') {
162
- this.emitClose()
163
- }
144
+ onBeforeUnmount(() => {
145
+ if (focusListener.value) {
146
+ document.removeEventListener('focusin', focusListener.value)
164
147
  }
165
148
 
166
- @Emit('close')
167
- emitClose () {
168
- return true
149
+ const openModalCount = Number(document.body.getAttribute('data-openModalCount'))
150
+ document.body.setAttribute('data-openModalCount', String(openModalCount - 1))
151
+ if (openModalCount <= 1) {
152
+ document.body.classList.remove('uikit-modal-open')
169
153
  }
154
+ emitUnmounted()
155
+ })
170
156
 
171
- @Emit('mounted')
172
- emitMounted () {
173
- return true
157
+ const keydownListener = (e: Event | KeyboardEvent) => {
158
+ if (!('key' in e)) {
159
+ return
174
160
  }
175
161
 
176
- @Emit('unmounted')
177
- emitUnmounted () {
178
- return true
162
+ if (e.key.match(/^[A-Za-z0-9\s\-_@]$/)) {
163
+ e.stopPropagation()
179
164
  }
180
165
 
181
- @Watch('trapFocus')
182
- toggleTrapFocus () {
183
- if (this.focusListener) {
184
- if (this.trapFocus) {
185
- document.addEventListener('focusin', this.focusListener)
186
- } else {
187
- document.removeEventListener('focusin', this.focusListener)
188
- }
189
- }
166
+ if (e.key === 'Escape') {
167
+ emitClose()
190
168
  }
191
169
  }
170
+
171
+ const emitClose = () => {
172
+ emit('close')
173
+ }
174
+
175
+ const emitMounted = () => {
176
+ emit('mounted')
177
+ }
178
+
179
+ const emitUnmounted = () => {
180
+ emit('unmounted')
181
+ }
182
+
183
+ watch(() => trapFocus, () => {
184
+ if (focusListener.value) {
185
+ if (trapFocus) {
186
+ document.addEventListener('focusin', focusListener.value)
187
+ } else {
188
+ document.removeEventListener('focusin', focusListener.value)
189
+ }
190
+ }
191
+ })
192
192
  </script>
193
193
 
194
194
  <style lang="scss">
@@ -248,4 +248,4 @@ export default class ModalContainer extends Vue {
248
248
  }
249
249
  }
250
250
  }
251
- </style>
251
+ </style>
@@ -11,9 +11,9 @@
11
11
  :class="{
12
12
  'uikit-email-auth__magic-code-entry--error': errorMessage,
13
13
  }"
14
- :error="errorMessage"
14
+ :error="!!errorMessage"
15
15
  :modelValue="modelValue"
16
- @update:modelValue="emitUpdateModelValue"
16
+ @update:modelValue="emitUpdateModelValue"
17
17
  @error="(err: string) => errorMessage = err"
18
18
  @submit="submitSignIn"
19
19
  />
@@ -21,7 +21,7 @@
21
21
  <Icon class="uikit-email-auth__error-message-icon" type="warning" />
22
22
  <span>{{ errorMessage }}</span>
23
23
  </div>
24
- <Button
24
+ <PocketButton
25
25
  class="uikit-email-auth__sign-in-btn"
26
26
  :class="{
27
27
  'uikit-email-auth__sign-in-btn--error': errorMessage,
@@ -32,94 +32,90 @@
32
32
  @click="submitSignIn"
33
33
  >
34
34
  Sign In
35
- </Button>
36
- <Button
35
+ </PocketButton>
36
+ <PocketButton
37
37
  type="tertiary"
38
38
  class="uikit-email-auth__resend-email-btn"
39
39
  :disabled="isResending"
40
40
  @click="resendEmail"
41
41
  >
42
42
  Resend Email
43
- </Button>
43
+ </PocketButton>
44
44
  </div>
45
45
  </template>
46
46
 
47
- <script lang="ts">
48
- import { Vue, Component, Prop, Watch, Emit } from 'vue-facing-decorator'
47
+ <script setup lang="ts">
49
48
  import Icon from '../Icons/Icon.vue'
50
- import Button from '../Buttons/Button.vue'
51
- import Link from '../Buttons/Link.vue'
49
+ import PocketButton from '../Buttons/Button.vue'
52
50
  import MagicCodeEntry from '../Onboarding/MagicCodeEntry.vue'
53
-
54
- @Component({
55
- components: {
56
- Button,
57
- Link,
58
- Icon,
59
- MagicCodeEntry,
60
- },
61
- })
62
- export default class EmailAuth extends Vue {
63
- @Prop({ default: '' }) parentError!: string
64
- @Prop({ default: false }) parentIsLoading!: boolean
65
- @Prop() email!: string
66
- @Prop({ default: '' }) modelValue!: string
67
-
68
- errorMessage = ''
69
- isLoading = false
70
- isResending = false
71
- highlightInput = false
72
-
73
- @Watch('parentError')
74
- parentErrorChanged (newVal: string, oldVal: string) {
75
- if (newVal !== oldVal) {
76
- this.errorMessage = newVal
77
- }
78
- }
79
-
80
- @Watch('parentIsLoading')
81
- parentIsLoadingChanged (newVal: boolean, oldVal: boolean) {
82
- if (newVal !== oldVal) {
83
- this.isLoading = newVal
51
+ import { ref, watch } from 'vue'
52
+
53
+ const {
54
+ parentError = '',
55
+ parentIsLoading = false,
56
+ email,
57
+ modelValue = '',
58
+ } = defineProps<{
59
+ parentError?: string
60
+ parentIsLoading?: boolean
61
+ email: string
62
+ modelValue?: string
63
+ }>()
64
+
65
+ const emit = defineEmits<{
66
+ 'submit': [results: { email: string; code: string }]
67
+ 'resend': [resendInfo: { email: string }]
68
+ 'update:modelValue': [code: string]
69
+ }>()
70
+
71
+ const errorMessage = ref('')
72
+ const isLoading = ref(false)
73
+ const isResending = ref(false)
74
+
75
+ const submitSignIn = () => {
76
+ isLoading.value = true
77
+ errorMessage.value = ''
78
+
79
+ if (email && modelValue) {
80
+ if (modelValue.trim().length !== 6) {
81
+ errorMessage.value = 'Code must be six digits'
82
+ } else {
83
+ emitSubmit({ email, code: modelValue })
84
84
  }
85
85
  }
86
86
 
87
- submitSignIn () {
88
- this.isLoading = true
89
- this.errorMessage = ''
87
+ isLoading.value = false
88
+ }
90
89
 
91
- if (this.email && this.modelValue) {
92
- if (this.modelValue.trim().length !== 6) {
93
- this.errorMessage = 'Code must be six digits'
94
- } else {
95
- this.emitSubmit({ email: this.email, code: this.modelValue })
96
- }
97
- }
90
+ const resendEmail = () => {
91
+ errorMessage.value = ''
92
+ isResending.value = true
93
+ emitResend({ email })
94
+ isResending.value = false
95
+ }
98
96
 
99
- this.isLoading = false
97
+ watch(() => parentError, (newVal: string, oldVal: string) => {
98
+ if (newVal !== oldVal) {
99
+ errorMessage.value = newVal
100
100
  }
101
+ })
101
102
 
102
- resendEmail () {
103
- this.errorMessage = ''
104
- this.isResending = true
105
- this.emitResend({ email: this.email })
106
- this.isResending = false
103
+ watch(() => parentIsLoading, (newVal: boolean, oldVal: boolean) => {
104
+ if (newVal !== oldVal) {
105
+ isLoading.value = newVal
107
106
  }
107
+ })
108
108
 
109
- @Emit('submit')
110
- emitSubmit (results: { email: string; code: string }) {
111
- return results
112
- }
109
+ const emitSubmit = (results: { email: string; code: string }) => {
110
+ emit('submit', results)
111
+ }
113
112
 
114
- @Emit('resend')
115
- emitResend (resendInfo: { email: string }) {
116
- return resendInfo
117
- }
113
+ const emitResend = (resendInfo: { email: string }) => {
114
+ emit('resend', resendInfo)
115
+ }
118
116
 
119
- @Emit('update:modelValue')
120
- emitUpdateModelValue (code: string) {
121
- return code
122
- }
117
+ const emitUpdateModelValue = (code: string) => {
118
+ emit('update:modelValue', code)
123
119
  }
124
120
  </script>
125
121
 
@@ -220,4 +216,4 @@ export default class EmailAuth extends Vue {
220
216
  }
221
217
  }
222
218
  }
223
- </style>
219
+ </style>