@pocketprep/ui-kit 3.8.4 → 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 +14469 -17731
  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 -133
  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,160 +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.querySelectorAll(focusableSelectors))
74
- if (modalFocusableEls.length) {
75
- modalFocusableEls[modalFocusableEls.length - 1]?.focus()
76
- modalFocusableEls[modalFocusableEls.length - 1]?.blur()
77
- }
78
-
79
-
80
- this.focusListener = event => {
81
- if (this.modalNumber === this.numberOfModals()) { // Only focus on the last open panel
82
- const target = (event as FocusEvent).target as HTMLElement // The element receiving focus
83
- const isFocusOutside = target && modalContainerEl && !modalContainerEl.contains(target)
84
- const hasCalendarClass = target
85
- && Array.from(target.classList).find(
86
- c => c === 'button-next-month' || c === 'button-previous-month' || c === 'day-item'
87
- )
88
- if (isFocusOutside && !hasCalendarClass) {
89
- const focusableModalChildren = Array.from<HTMLElement>(modalContainerEl.querySelectorAll(
90
- focusableSelectors
91
- ))
92
- const firstFocusableModalChild = focusableModalChildren.find(
93
- el => !!el.getBoundingClientRect().width
94
- )
95
- const reversedModalChildren = [ ...focusableModalChildren ].reverse()
96
- const lastFocusableModalChild = reversedModalChildren.find(
97
- el => !!el.getBoundingClientRect().width
98
- )
99
- if (firstFocusableModalChild) {
100
- const relatedTarget = (event as FocusEvent).relatedTarget // The element last focused
101
- if (relatedTarget === firstFocusableModalChild && lastFocusableModalChild) {
102
- // If focus moves from first element -> outside modal, focus the last element instead
103
- lastFocusableModalChild.focus()
104
- } else if (relatedTarget === lastFocusableModalChild && firstFocusableModalChild) {
105
- // If focus moves from last element -> outside modal, focus the first element instead
106
- firstFocusableModalChild.focus()
107
- } else if (relatedTarget && relatedTarget instanceof HTMLElement) {
108
- // If focus goes outside in a different way, return focus to where it came from if possible
109
- relatedTarget.focus()
110
- } else {
111
- // Otherwise, just return focus to the first element
112
- firstFocusableModalChild.focus()
113
- }
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()
114
117
  } else {
115
- // If the modal doesn't have any focusable children, focus the container instead
116
- if (modalContainerEl.tabIndex === -1) {
117
- modalContainerEl.tabIndex = 0
118
- }
119
- modalContainerEl.focus()
118
+ // Otherwise, just return focus to the first element
119
+ firstFocusableModalChild.focus()
120
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()
121
127
  }
122
128
  }
123
129
  }
124
- // Trap the user's focus within the modal - don't allow focusing elements behind the overlay
125
- if (this.trapFocus) {
126
- document.addEventListener('focusin', this.focusListener)
127
- }
128
-
129
- // prevent scrolling outside of modal
130
- const openModalCount = Number(document.body.getAttribute('data-openModalCount'))
131
- document.body.setAttribute('data-openModalCount', String(openModalCount + 1))
132
- document.body.classList.add('uikit-modal-open')
133
-
134
- this.emitMounted()
135
130
  }
136
-
137
- beforeUnmount () {
138
- if (this.focusListener) {
139
- document.removeEventListener('focusin', this.focusListener)
140
- }
141
-
142
- const openModalCount = Number(document.body.getAttribute('data-openModalCount'))
143
- document.body.setAttribute('data-openModalCount', String(openModalCount - 1))
144
- if (openModalCount <= 1) {
145
- document.body.classList.remove('uikit-modal-open')
146
- }
147
- 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)
148
134
  }
149
135
 
150
- keydownListener (e: Event | KeyboardEvent) {
151
- if (!('key' in e)) {
152
- return
153
- }
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')
154
140
 
155
- if (e.key.match(/^[A-Za-z0-9\s\-_@]$/)) {
156
- e.stopPropagation()
157
- }
141
+ emitMounted()
142
+ })
158
143
 
159
- if (e.key === 'Escape') {
160
- this.emitClose()
161
- }
144
+ onBeforeUnmount(() => {
145
+ if (focusListener.value) {
146
+ document.removeEventListener('focusin', focusListener.value)
162
147
  }
163
148
 
164
- @Emit('close')
165
- emitClose () {
166
- 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')
167
153
  }
154
+ emitUnmounted()
155
+ })
168
156
 
169
- @Emit('mounted')
170
- emitMounted () {
171
- return true
157
+ const keydownListener = (e: Event | KeyboardEvent) => {
158
+ if (!('key' in e)) {
159
+ return
172
160
  }
173
161
 
174
- @Emit('unmounted')
175
- emitUnmounted () {
176
- return true
162
+ if (e.key.match(/^[A-Za-z0-9\s\-_@]$/)) {
163
+ e.stopPropagation()
177
164
  }
178
165
 
179
- @Watch('trapFocus')
180
- toggleTrapFocus () {
181
- if (this.focusListener) {
182
- if (this.trapFocus) {
183
- document.addEventListener('focusin', this.focusListener)
184
- } else {
185
- document.removeEventListener('focusin', this.focusListener)
186
- }
187
- }
166
+ if (e.key === 'Escape') {
167
+ emitClose()
188
168
  }
189
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
+ })
190
192
  </script>
191
193
 
192
194
  <style lang="scss">
@@ -246,4 +248,4 @@ export default class ModalContainer extends Vue {
246
248
  }
247
249
  }
248
250
  }
249
- </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>