@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.
- package/dist/@pocketprep/ui-kit.css +1 -1
- package/dist/@pocketprep/ui-kit.js +14466 -17728
- package/dist/@pocketprep/ui-kit.js.map +1 -1
- package/dist/@pocketprep/ui-kit.umd.cjs +19 -29
- package/dist/@pocketprep/ui-kit.umd.cjs.map +1 -1
- package/eslint.config.ts +38 -11
- package/lib/SVGDefinitions.vue +32 -35
- package/lib/components/Banners/Banner.vue +10 -14
- package/lib/components/Blobs/Blob.vue +6 -14
- package/lib/components/Blobs/BlobEmptyState.vue +9 -8
- package/lib/components/Blobs/blob.d.ts +1 -1
- package/lib/components/BundleIcons/BundleIcon.vue +36 -63
- package/lib/components/BundleIcons/bundleIcon.d.ts +1 -1
- package/lib/components/Bundles/BundleList.vue +71 -59
- package/lib/components/Bundles/BundleSearch.vue +93 -117
- package/lib/components/Bundles/PremiumPill.vue +6 -12
- package/lib/components/Buttons/Button.vue +32 -35
- package/lib/components/Buttons/Link.vue +32 -31
- package/lib/components/Buttons/Tab.vue +14 -17
- package/lib/components/Calendar/Calendar.vue +87 -85
- package/lib/components/Charts/Bar.vue +192 -263
- package/lib/components/Charts/Pie.vue +55 -61
- package/lib/components/Charts/highcharts-wrap.ts +81 -0
- package/lib/components/Controls/SegmentControl.vue +26 -24
- package/lib/components/Controls/Slider.vue +51 -47
- package/lib/components/Controls/ToggleSwitch.vue +33 -31
- package/lib/components/EmptyStates/EmptyState.vue +69 -73
- package/lib/components/Exams/ExamCard.vue +59 -47
- package/lib/components/Exams/ExamMenuCard.vue +30 -28
- package/lib/components/Filters/FilterDropdown.vue +83 -86
- package/lib/components/Filters/FilterOptions.vue +83 -88
- package/lib/components/Forms/Checkbox.vue +27 -27
- package/lib/components/Forms/CheckboxOption.vue +30 -30
- package/lib/components/Forms/Errors.vue +21 -24
- package/lib/components/Forms/Input.vue +71 -59
- package/lib/components/Forms/Radio.vue +2 -2
- package/lib/components/Forms/RadioButton.vue +8 -8
- package/lib/components/Forms/Select.vue +265 -257
- package/lib/components/Forms/Textarea.vue +49 -35
- package/lib/components/Icons/IconAccordionArrow.vue +7 -9
- package/lib/components/Icons/IconActivity.vue +7 -9
- package/lib/components/Icons/IconAdd.vue +7 -11
- package/lib/components/Icons/IconAddCircle.vue +7 -9
- package/lib/components/Icons/IconArrow.vue +7 -9
- package/lib/components/Icons/IconBarChart.vue +7 -9
- package/lib/components/Icons/IconCalendar.vue +7 -9
- package/lib/components/Icons/IconCalendarPicker.vue +7 -9
- package/lib/components/Icons/IconChat.vue +7 -9
- package/lib/components/Icons/IconCheck.vue +7 -9
- package/lib/components/Icons/IconClose.vue +7 -9
- package/lib/components/Icons/IconConcept.vue +1 -1
- package/lib/components/Icons/IconCorrect.vue +7 -9
- package/lib/components/Icons/IconEdit.vue +7 -11
- package/lib/components/Icons/IconExam.vue +7 -9
- package/lib/components/Icons/IconExternalLink.vue +7 -9
- package/lib/components/Icons/IconEyeHide.vue +7 -9
- package/lib/components/Icons/IconEyeShow.vue +7 -9
- package/lib/components/Icons/IconFilter.vue +7 -9
- package/lib/components/Icons/IconFilterActive.vue +7 -9
- package/lib/components/Icons/IconFlag.vue +7 -9
- package/lib/components/Icons/IconFlagContent.vue +8 -9
- package/lib/components/Icons/IconFlagFeedback.vue +8 -10
- package/lib/components/Icons/IconFlagFilled.vue +7 -9
- package/lib/components/Icons/IconFullView.vue +7 -9
- package/lib/components/Icons/IconFullViewActive.vue +7 -9
- package/lib/components/Icons/IconGridDrag.vue +2 -2
- package/lib/components/Icons/IconHandle.vue +7 -9
- package/lib/components/Icons/IconHeart.vue +7 -9
- package/lib/components/Icons/IconHelp.vue +7 -9
- package/lib/components/Icons/IconHighlight.vue +2 -2
- package/lib/components/Icons/IconHourglass.vue +7 -9
- package/lib/components/Icons/IconImage.vue +7 -9
- package/lib/components/Icons/IconIncorrect.vue +7 -9
- package/lib/components/Icons/IconInfo.vue +7 -9
- package/lib/components/Icons/IconKeyboard.vue +7 -9
- package/lib/components/Icons/IconLaunch.vue +7 -9
- package/lib/components/Icons/IconLevelUp.vue +7 -9
- package/lib/components/Icons/IconLightbulb.vue +7 -9
- package/lib/components/Icons/IconLightning.vue +7 -9
- package/lib/components/Icons/IconLink.vue +7 -9
- package/lib/components/Icons/IconList.vue +7 -9
- package/lib/components/Icons/IconLoading.vue +7 -9
- package/lib/components/Icons/IconLoading2.vue +11 -11
- package/lib/components/Icons/IconLock.vue +7 -9
- package/lib/components/Icons/IconMissedQuestions.vue +7 -9
- package/lib/components/Icons/IconMoon.vue +7 -9
- package/lib/components/Icons/IconPaginationArrow.vue +7 -9
- package/lib/components/Icons/IconPaginationArrowDouble.vue +7 -9
- package/lib/components/Icons/IconPassage.vue +7 -9
- package/lib/components/Icons/IconPencil.vue +7 -9
- package/lib/components/Icons/IconPeople.vue +7 -9
- package/lib/components/Icons/IconPercent.vue +7 -9
- package/lib/components/Icons/IconPerson.vue +8 -9
- package/lib/components/Icons/IconPresent.vue +7 -9
- package/lib/components/Icons/IconPreview.vue +7 -9
- package/lib/components/Icons/IconQuestions.vue +7 -9
- package/lib/components/Icons/IconQuick10.vue +7 -9
- package/lib/components/Icons/IconQuickActions.vue +2 -2
- package/lib/components/Icons/IconRecommendedFilter.vue +1 -1
- package/lib/components/Icons/IconRemoveCircle.vue +7 -9
- package/lib/components/Icons/IconReviewFlag.vue +7 -9
- package/lib/components/Icons/IconSearch.vue +7 -9
- package/lib/components/Icons/IconShare.vue +7 -9
- package/lib/components/Icons/IconSideBar.vue +7 -9
- package/lib/components/Icons/IconSideBarActive.vue +7 -9
- package/lib/components/Icons/IconStar.vue +1 -1
- package/lib/components/Icons/IconStopwatch.vue +7 -9
- package/lib/components/Icons/IconStrike.vue +7 -9
- package/lib/components/Icons/IconSubject.vue +7 -9
- package/lib/components/Icons/IconText.vue +7 -9
- package/lib/components/Icons/IconTimer.vue +8 -9
- package/lib/components/Icons/IconWarning.vue +7 -9
- package/lib/components/Icons/icon.d.ts +1 -1
- package/lib/components/Loaders/SkeletonLoader.vue +1 -5
- package/lib/components/Modal/Modal.vue +23 -29
- package/lib/components/Modal/ModalContainer.vue +135 -135
- package/lib/components/Onboarding/EmailAuth.vue +66 -70
- package/lib/components/Onboarding/MagicCodeEntry.vue +88 -83
- package/lib/components/Pagination/QuestionReviewPagination.vue +3 -3
- package/lib/components/Pagination/TablePagination.vue +47 -44
- package/lib/components/PhonePerson/PhonePerson.vue +18 -18
- package/lib/components/PhonePerson/phonePerson.d.ts +1 -1
- package/lib/components/Quiz/FlagToggle.vue +45 -44
- package/lib/components/Quiz/GlobalMetricsToggle.vue +29 -28
- package/lib/components/Quiz/KeyboardShortcutsButton.vue +16 -23
- package/lib/components/Quiz/KeyboardShortcutsModal.vue +36 -37
- package/lib/components/Quiz/Question/BuildListChoicesContainer.vue +65 -65
- package/lib/components/Quiz/Question/ChoicesContainer.vue +5 -5
- package/lib/components/Quiz/Question/DropdownExplanation.vue +5 -5
- package/lib/components/Quiz/Question/Explanation.vue +6 -6
- package/lib/components/Quiz/Question/MPMCChoicesContainer.vue +17 -17
- package/lib/components/Quiz/Question/MPMCRadioGroup.vue +2 -2
- package/lib/components/Quiz/Question/MatrixChoicesContainer.vue +39 -39
- package/lib/components/Quiz/Question/MatrixRadioGroup.vue +6 -6
- package/lib/components/Quiz/Question/MobileMatrixChoicesContainer.vue +27 -28
- package/lib/components/Quiz/Question/MobileMatrixRadioGroup.vue +2 -2
- package/lib/components/Quiz/Question/PassageAndImage.vue +3 -3
- package/lib/components/Quiz/Question/PassageAndImageDropdown.vue +7 -7
- package/lib/components/Quiz/Question/Paywall.vue +2 -2
- package/lib/components/Quiz/Question/QuestionContext.vue +1 -1
- package/lib/components/Quiz/Question/StatsSummary.vue +2 -2
- package/lib/components/Quiz/Question/Summary.vue +11 -11
- package/lib/components/Quiz/Question.vue +90 -82
- package/lib/components/Quiz/QuizContainer.vue +1 -1
- package/lib/components/Quiz/QuizProgressBar.vue +23 -23
- package/lib/components/Quiz/question.d.ts +3 -3
- package/lib/components/Search/Pill.vue +16 -19
- package/lib/components/Search/Search.vue +52 -47
- package/lib/components/SidePanels/SidePanel.vue +168 -174
- package/lib/components/Tables/Table.vue +135 -122
- package/lib/components/Tables/TableActions.vue +81 -76
- package/lib/components/Tables/table.d.ts +1 -1
- package/lib/components/Tags/Tag.vue +49 -39
- package/lib/components/Toasts/Toast.vue +44 -42
- package/lib/components/Tooltips/OverflowTooltip.vue +39 -45
- package/lib/components/Tooltips/Tooltip.vue +69 -70
- package/lib/directives.ts +4 -4
- package/lib/utils.ts +13 -12
- 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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
//
|
|
118
|
-
|
|
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
|
-
|
|
140
|
-
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
141
|
+
emitMounted()
|
|
142
|
+
})
|
|
160
143
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
144
|
+
onBeforeUnmount(() => {
|
|
145
|
+
if (focusListener.value) {
|
|
146
|
+
document.removeEventListener('focusin', focusListener.value)
|
|
164
147
|
}
|
|
165
148
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
return
|
|
157
|
+
const keydownListener = (e: Event | KeyboardEvent) => {
|
|
158
|
+
if (!('key' in e)) {
|
|
159
|
+
return
|
|
174
160
|
}
|
|
175
161
|
|
|
176
|
-
@
|
|
177
|
-
|
|
178
|
-
return true
|
|
162
|
+
if (e.key.match(/^[A-Za-z0-9\s\-_@]$/)) {
|
|
163
|
+
e.stopPropagation()
|
|
179
164
|
}
|
|
180
165
|
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
36
|
-
<
|
|
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
|
-
</
|
|
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
|
|
51
|
-
import Link from '../Buttons/Link.vue'
|
|
49
|
+
import PocketButton from '../Buttons/Button.vue'
|
|
52
50
|
import MagicCodeEntry from '../Onboarding/MagicCodeEntry.vue'
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (
|
|
83
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
this.errorMessage = ''
|
|
87
|
+
isLoading.value = false
|
|
88
|
+
}
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
90
|
+
const resendEmail = () => {
|
|
91
|
+
errorMessage.value = ''
|
|
92
|
+
isResending.value = true
|
|
93
|
+
emitResend({ email })
|
|
94
|
+
isResending.value = false
|
|
95
|
+
}
|
|
98
96
|
|
|
99
|
-
|
|
97
|
+
watch(() => parentError, (newVal: string, oldVal: string) => {
|
|
98
|
+
if (newVal !== oldVal) {
|
|
99
|
+
errorMessage.value = newVal
|
|
100
100
|
}
|
|
101
|
+
})
|
|
101
102
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
109
|
+
const emitSubmit = (results: { email: string; code: string }) => {
|
|
110
|
+
emit('submit', results)
|
|
111
|
+
}
|
|
113
112
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
113
|
+
const emitResend = (resendInfo: { email: string }) => {
|
|
114
|
+
emit('resend', resendInfo)
|
|
115
|
+
}
|
|
118
116
|
|
|
119
|
-
|
|
120
|
-
|
|
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>
|