@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
@@ -3,7 +3,7 @@
3
3
  ref="sidepanelContainer"
4
4
  v-dark="isDarkMode"
5
5
  class="uikit-page-overlay"
6
- :class="{
6
+ :class="{
7
7
  'uikit-page-overlay--open': openSidePanel,
8
8
  'uikit-page-overlay--disable-transition': disableTransition
9
9
  }"
@@ -19,10 +19,10 @@
19
19
  class="uikit-side-panel"
20
20
  :style="{ width: `${sidePanelWidth}px`, right: `-${sidePanelWidth}px` }"
21
21
  >
22
- <div
23
- v-dark="isDarkMode"
22
+ <div
23
+ v-dark="isDarkMode"
24
24
  class="uikit-side-panel__head"
25
- :class="{
25
+ :class="{
26
26
  'uikit-side-panel__head--has-tabs': tabs && tabs.length,
27
27
  'uikit-side-panel__head--has-stepped-tabs': tabs && tabs.length && steppedTabs,
28
28
  'uikit-side-panel__head--teach-side-panel': isTeachSidePanel,
@@ -62,7 +62,7 @@
62
62
  :key="tab"
63
63
  v-dark="isDarkMode"
64
64
  class="uikit-side-panel__tab"
65
- :class="{
65
+ :class="{
66
66
  'uikit-side-panel__tab--active': activeTabName === tab,
67
67
  'uikit-side-panel__tab--stepper': steppedTabs,
68
68
  }"
@@ -81,10 +81,10 @@
81
81
  </div>
82
82
  </div>
83
83
  <slot name="sidePanelContent">
84
- <div
84
+ <div
85
85
  v-dark="isDarkMode"
86
86
  class="uikit-side-panel__content"
87
- :class="{
87
+ :class="{
88
88
  'uikit-side-panel__content--has-tabs': tabs && tabs.length,
89
89
  'uikit-side-panel__content--teach-side-panel': isTeachSidePanel,
90
90
  }"
@@ -94,9 +94,9 @@
94
94
  </div>
95
95
  </slot>
96
96
  <slot name="sidePanelFooter">
97
- <div
98
- class="uikit-side-panel__foot"
99
- :class="{
97
+ <div
98
+ class="uikit-side-panel__foot"
99
+ :class="{
100
100
  'uikit-side-panel__foot--dark': isDarkMode,
101
101
  'uikit-side-panel__foot--teach-side-panel': isTeachSidePanel,
102
102
  }"
@@ -122,202 +122,196 @@
122
122
  </div>
123
123
  </template>
124
124
 
125
- <script lang="ts">
126
- import { Component, Vue, Prop, Emit, Watch } from 'vue-facing-decorator'
127
- import Button from '../Buttons/Button.vue'
125
+ <script setup lang="ts">
128
126
  import Icon from '../Icons/Icon.vue'
129
- import { dark } from '../../directives'
130
-
131
- @Component({
132
- name: 'SidePanel',
133
- components: {
134
- Icon,
135
- PocketButton: Button,
136
- },
137
- directives: {
138
- dark,
139
- },
127
+ import PocketButton from '../Buttons/Button.vue'
128
+ import { dark as vDark } from '../../directives'
129
+ import { computed, onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from 'vue'
130
+
131
+ const {
132
+ name,
133
+ tabs = [],
134
+ activeTabName = undefined,
135
+ steppedTabs = false,
136
+ cancelButtonText = 'Cancel',
137
+ customCancelButtonAction = false,
138
+ customContentStyles = {},
139
+ width = 'large',
140
+ disableTransition = false,
141
+ isTeachSidePanel = false,
142
+ isDarkMode = false,
143
+ showCancelButton = true,
144
+ trapFocus = true,
145
+ } = defineProps<{
146
+ name: string
147
+ tabs?: string[]
148
+ activeTabName?: string
149
+ steppedTabs?: boolean
150
+ cancelButtonText?: string
151
+ customCancelButtonAction?: boolean
152
+ customContentStyles?: Record<string, string>
153
+ width?: 'large' | 'medium' | number
154
+ disableTransition?: boolean
155
+ isTeachSidePanel?: boolean
156
+ isDarkMode?: boolean
157
+ showCancelButton?: boolean
158
+ trapFocus?: boolean
159
+ }>()
160
+
161
+ const emit = defineEmits<{
162
+ 'mounted': []
163
+ 'unmounted': []
164
+ 'selectTab': [tabName: string]
165
+ 'close': []
166
+ 'close-button': []
167
+ }>()
168
+
169
+ const openSidePanel = ref(false)
170
+ const focusListener = ref<Parameters<typeof addEventListener>[1] | null>(null)
171
+ const sidePanelNumber = ref(0)
172
+
173
+ const sidePanelRef = useTemplateRef<HTMLElement>('uikit-side-panel')
174
+ const titleRef = useTemplateRef<HTMLElement>('uikit-side-panel__title')
175
+ const sidePanelContainerRef = useTemplateRef<HTMLElement>('sidepanelContainer')
176
+
177
+ const sidePanelWidth = computed(() => {
178
+ return width === 'large'
179
+ ? 572
180
+ : width === 'medium'
181
+ ? 460
182
+ : width
140
183
  })
141
- export default class SidePanel extends Vue {
142
- @Prop() name!: string
143
- @Prop({ default: () => [] }) tabs!: string[]
144
- @Prop({ default: undefined }) activeTabName!: string
145
- @Prop({ default: false }) steppedTabs!: boolean
146
- @Prop({ default: 'Cancel' }) cancelButtonText!: string
147
- @Prop({ default: false }) customCancelButtonAction!: boolean
148
- @Prop({ default: () => ({}) }) customContentStyles!: { [key: string]: string }
149
- @Prop({ default: 'large' }) width!: 'large' | 'medium' | number
150
- @Prop({ default: false }) disableTransition!: boolean
151
- @Prop({ default: false }) isTeachSidePanel!: boolean
152
- @Prop({ default: false }) isDarkMode!: boolean
153
- @Prop({ default: true }) showCancelButton!: boolean
154
- @Prop({ default: true }) trapFocus!: boolean
155
-
156
- openSidePanel = false
157
- notContentHeight = this.tabs?.length ? 262 : 218
158
- focusListener: Parameters<typeof addEventListener>[1] | null = null
159
- savedYPosition = 0
160
- sidePanelNumber = 0
161
-
162
- get sidePanelWidth () {
163
- return this.width === 'large'
164
- ? 572
165
- : this.width === 'medium'
166
- ? 460
167
- : this.width
168
- }
169
-
170
- numberOfSidepanels () {
171
- return document.querySelectorAll('.uikit-side-panel').length
172
- }
173
184
 
174
- mounted () {
175
- this.sidePanelNumber = this.numberOfSidepanels()
176
-
177
- // delay opening to show animation
178
- setTimeout(() => {
179
- this.openSidePanel = true
180
- }, 1)
181
-
182
-
183
- // Focus title after opening transition
184
- const sidePanelEl = this.$refs['uikit-side-panel'] as HTMLElement | undefined
185
- sidePanelEl?.addEventListener('transitionend', () => {
186
- const titleEl = this.$refs['uikit-side-panel__title'] as HTMLElement | undefined
187
- titleEl?.focus()
188
- })
189
-
190
- // Trap the user's focus within the side panel - don't allow focusing elements behind the overlay
191
- this.focusListener = event => {
192
- if (this.sidePanelNumber === this.numberOfSidepanels()) { // Only focus on the last open panel
193
- const target = (event as FocusEvent).target as HTMLElement // The element receiving focus
194
- const sidePanelContainerEl = this.$refs['sidepanelContainer'] as HTMLElement
195
- const isFocusOutside = target && sidePanelContainerEl && !sidePanelContainerEl.contains(target)
196
- const hasCalendarClass = target
197
- && Array.from(target.classList).find(
198
- c => c === 'button-next-month' || c === 'button-previous-month' || c === 'day-item'
199
- )
200
- if (isFocusOutside && !hasCalendarClass) {
201
- const focusableSidePanelChildren = Array.from<HTMLElement>(sidePanelContainerEl.querySelectorAll(
202
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
203
- ))
204
- const firstFocusableSidePanelChild = focusableSidePanelChildren.find(
205
- el => !!el.getBoundingClientRect().width
206
- )
207
- const reversedSidePanelChildren = [ ...focusableSidePanelChildren ].reverse()
208
- const lastFocusableSidePanelChild = reversedSidePanelChildren.find(
209
- el => !!el.getBoundingClientRect().width
210
- )
211
- if (firstFocusableSidePanelChild) {
212
- const relatedTarget = (event as FocusEvent).relatedTarget // The element last focused
213
- if (relatedTarget === firstFocusableSidePanelChild && lastFocusableSidePanelChild) {
214
- // If focus moves from first element -> outside side panel, focus the last element instead
215
- lastFocusableSidePanelChild.focus()
216
- } else {
217
- // If focus goes outside the side panel in any other way, focus the first element
218
- firstFocusableSidePanelChild.focus()
219
- }
185
+ onMounted(() => {
186
+ sidePanelNumber.value = numberOfSidepanels()
187
+
188
+ // delay opening to show animation
189
+ setTimeout(() => {
190
+ openSidePanel.value = true
191
+ }, 1)
192
+
193
+
194
+ // Focus title after opening transition
195
+ sidePanelRef.value?.addEventListener('transitionend', () => {
196
+ titleRef.value?.focus()
197
+ })
198
+
199
+ // Trap the user's focus within the side panel - don't allow focusing elements behind the overlay
200
+ focusListener.value = event => {
201
+ if (sidePanelNumber.value === numberOfSidepanels()) { // Only focus on the last open panel
202
+ const target = (event as FocusEvent).target as HTMLElement // The element receiving focus
203
+ const isFocusOutside = target
204
+ && sidePanelContainerRef.value
205
+ && !sidePanelContainerRef.value.contains(target)
206
+ const hasCalendarClass = target?.classList
207
+ && Array.from(target.classList).find(
208
+ c => c === 'button-next-month' || c === 'button-previous-month' || c === 'day-item'
209
+ )
210
+ if (isFocusOutside && !hasCalendarClass) {
211
+ const focusableSidePanelChildren = Array.from<HTMLElement>(sidePanelContainerRef.value.querySelectorAll(
212
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
213
+ ))
214
+ const firstFocusableSidePanelChild = focusableSidePanelChildren.find(
215
+ el => !!el.getBoundingClientRect().width
216
+ )
217
+ const reversedSidePanelChildren = [ ...focusableSidePanelChildren ].reverse()
218
+ const lastFocusableSidePanelChild = reversedSidePanelChildren.find(
219
+ el => !!el.getBoundingClientRect().width
220
+ )
221
+ if (firstFocusableSidePanelChild) {
222
+ const relatedTarget = (event as FocusEvent).relatedTarget // The element last focused
223
+ if (relatedTarget === firstFocusableSidePanelChild && lastFocusableSidePanelChild) {
224
+ // If focus moves from first element -> outside side panel, focus the last element instead
225
+ lastFocusableSidePanelChild.focus()
220
226
  } else {
221
- // If the side panel doesn't have any focusable children, focus the container instead
222
- if (sidePanelContainerEl.tabIndex === -1) {
223
- sidePanelContainerEl.tabIndex = 0
224
- }
225
- sidePanelContainerEl.focus()
227
+ // If focus goes outside the side panel in any other way, focus the first element
228
+ firstFocusableSidePanelChild.focus()
226
229
  }
230
+ } else {
231
+ // If the side panel doesn't have any focusable children, focus the container instead
232
+ if (sidePanelContainerRef.value.tabIndex === -1) {
233
+ sidePanelContainerRef.value.tabIndex = 0
234
+ }
235
+ sidePanelContainerRef.value.focus()
227
236
  }
228
237
  }
229
238
  }
239
+ }
230
240
 
231
- if (this.trapFocus) {
232
- document.addEventListener('focusin', this.focusListener)
233
- }
234
-
235
- // prevent scrolling outside of modal
236
- const openSidePanelCount = Number(document.body.getAttribute('data-openSidePanelCount'))
237
- document.body.setAttribute('data-openSidePanelCount', String(openSidePanelCount + 1))
238
- document.body.classList.add('uikit-sidepanel-open')
239
-
240
- this.emitMounted()
241
+ if (trapFocus) {
242
+ document.addEventListener('focusin', focusListener.value)
241
243
  }
242
244
 
243
- beforeUnmount () {
244
- if (this.focusListener) {
245
- document.removeEventListener('focusin', this.focusListener)
246
- }
245
+ // prevent scrolling outside of modal
246
+ const openSidePanelCount = Number(document.body.getAttribute('data-openSidePanelCount'))
247
+ document.body.setAttribute('data-openSidePanelCount', String(openSidePanelCount + 1))
248
+ document.body.classList.add('uikit-sidepanel-open')
247
249
 
248
- const openSidePanelCount = Number(document.body.getAttribute('data-openSidePanelCount'))
249
- document.body.setAttribute('data-openSidePanelCount', String(openSidePanelCount - 1))
250
- if (openSidePanelCount <= 1) {
251
- document.body.classList.remove('uikit-sidepanel-open')
252
- document.body.scrollTo(0, 0)
253
- }
250
+ emit('mounted')
251
+ })
254
252
 
255
- this.emitUnmounted()
253
+ onBeforeUnmount(() => {
254
+ if (focusListener.value) {
255
+ document.removeEventListener('focusin', focusListener.value)
256
256
  }
257
257
 
258
- selectTab (e: MouseEvent | KeyboardEvent, tabName: string) {
259
- e.preventDefault()
260
- this.emitSelectTab(tabName)
258
+ const openSidePanelCount = Number(document.body.getAttribute('data-openSidePanelCount'))
259
+ document.body.setAttribute('data-openSidePanelCount', String(openSidePanelCount - 1))
260
+ if (openSidePanelCount <= 1) {
261
+ document.body.classList.remove('uikit-sidepanel-open')
262
+ document.body.scrollTo(0, 0)
261
263
  }
262
264
 
263
- keydownListener (e: Event | KeyboardEvent) {
264
- if (!('key' in e)) {
265
- return
266
- }
267
-
268
- if (e.key.match(/^[A-Za-z0-9\s\-_@]$/)) {
269
- e.stopPropagation()
270
- }
265
+ emit('unmounted')
266
+ })
271
267
 
272
- if (e.key === 'Escape') {
273
- this.emitClose()
274
- }
275
- }
268
+ const numberOfSidepanels = () => {
269
+ return document.querySelectorAll('.uikit-side-panel').length
270
+ }
276
271
 
277
- closeKeyPress (e: KeyboardEvent) {
278
- if (e.key === 'Enter' || e.key === ' ') {
279
- e.preventDefault()
280
- this.emitClose()
281
- }
282
- }
272
+ const selectTab = (e: MouseEvent | KeyboardEvent, tabName: string) => {
273
+ e.preventDefault()
274
+ emit('selectTab', tabName)
275
+ }
283
276
 
284
- @Emit('close')
285
- emitClose () {
286
- return true
277
+ const keydownListener = (e: Event | KeyboardEvent) => {
278
+ if (!('key' in e)) {
279
+ return
287
280
  }
288
281
 
289
- @Emit('close-button')
290
- emitCloseButton () {
291
- return true
282
+ if (e.key.match(/^[A-Za-z0-9\s\-_@]$/)) {
283
+ e.stopPropagation()
292
284
  }
293
285
 
294
- @Emit('selectTab')
295
- emitSelectTab (tabName: string) {
296
- return tabName
286
+ if (e.key === 'Escape') {
287
+ emitClose()
297
288
  }
289
+ }
298
290
 
299
- @Emit('mounted')
300
- emitMounted () {
301
- return true
291
+ const closeKeyPress = (e: KeyboardEvent) => {
292
+ if (e.key === 'Enter' || e.key === ' ') {
293
+ e.preventDefault()
294
+ emitClose()
302
295
  }
296
+ }
303
297
 
304
- @Emit('unmounted')
305
- emitUnmounted () {
306
- return true
307
- }
298
+ const emitClose = () => {
299
+ emit('close')
300
+ }
308
301
 
302
+ const emitCloseButton = () => {
303
+ emit('close-button')
304
+ }
309
305
 
310
- @Watch('trapFocus')
311
- toggleTrapFocus () {
312
- if (this.focusListener) {
313
- if (this.trapFocus) {
314
- document.addEventListener('focusin', this.focusListener)
315
- } else {
316
- document.removeEventListener('focusin', this.focusListener)
317
- }
306
+ watch(() => trapFocus, () => {
307
+ if (focusListener.value) {
308
+ if (trapFocus) {
309
+ document.addEventListener('focusin', focusListener.value)
310
+ } else {
311
+ document.removeEventListener('focusin', focusListener.value)
318
312
  }
319
313
  }
320
- }
314
+ })
321
315
  </script>
322
316
 
323
317
  <style lang="scss">