@pocketprep/ui-kit 3.4.90 → 3.5.1

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 (88) hide show
  1. package/README.md +2 -2
  2. package/dist/@pocketprep/ui-kit.css +1 -0
  3. package/dist/@pocketprep/ui-kit.js +16490 -18228
  4. package/dist/@pocketprep/ui-kit.js.map +1 -1
  5. package/dist/@pocketprep/ui-kit.umd.cjs +11 -11
  6. package/dist/@pocketprep/ui-kit.umd.cjs.map +1 -1
  7. package/eslint.config.ts +111 -0
  8. package/lib/components/Banners/Banner.vue +2 -2
  9. package/lib/components/Bundles/BundleList.vue +1 -1
  10. package/lib/components/Bundles/BundleSearch.vue +43 -12
  11. package/lib/components/Bundles/PremiumPill.vue +2 -2
  12. package/lib/components/Buttons/Button.vue +19 -18
  13. package/lib/components/Buttons/Link.vue +9 -8
  14. package/lib/components/Buttons/Tab.vue +4 -3
  15. package/lib/components/Calendar/Calendar.vue +14 -2
  16. package/lib/components/Charts/Bar.vue +3 -3
  17. package/lib/components/Charts/Pie.vue +4 -4
  18. package/lib/components/Controls/SegmentControl.vue +8 -7
  19. package/lib/components/Controls/Slider.vue +2 -3
  20. package/lib/components/Controls/ToggleSwitch.vue +3 -2
  21. package/lib/components/EmptyStates/EmptyState.vue +3 -2
  22. package/lib/components/Exams/ExamCard.vue +3 -3
  23. package/lib/components/Exams/ExamMenuCard.vue +2 -2
  24. package/lib/components/Filters/FilterDropdown.vue +2 -2
  25. package/lib/components/Filters/FilterOptions.vue +2 -2
  26. package/lib/components/Forms/Checkbox.vue +2 -2
  27. package/lib/components/Forms/CheckboxOption.vue +2 -2
  28. package/lib/components/Forms/Errors.vue +2 -2
  29. package/lib/components/Forms/Input.vue +2 -2
  30. package/lib/components/Forms/Radio.vue +37 -39
  31. package/lib/components/Forms/RadioButton.vue +1 -1
  32. package/lib/components/Forms/Select.vue +7 -6
  33. package/lib/components/Forms/Textarea.vue +2 -2
  34. package/lib/components/Icons/Icon.vue +1 -0
  35. package/lib/components/Icons/IconEdit.vue +4 -2
  36. package/lib/components/Icons/IconFullViewActive.vue +1 -1
  37. package/lib/components/Icons/IconLoading2.vue +1 -3
  38. package/lib/components/Loaders/SkeletonLoader.vue +2 -2
  39. package/lib/components/Messaging/InfoMessage.vue +2 -2
  40. package/lib/components/Modal/Modal.vue +2 -2
  41. package/lib/components/Modal/ModalContainer.vue +2 -2
  42. package/lib/components/Onboarding/EmailAuth.vue +5 -5
  43. package/lib/components/Onboarding/MagicCodeEntry.vue +3 -4
  44. package/lib/components/Pagination/QuestionReviewPagination.vue +23 -21
  45. package/lib/components/Pagination/TablePagination.vue +2 -2
  46. package/lib/components/Quiz/FlagToggle.vue +2 -2
  47. package/lib/components/Quiz/GlobalMetricsToggle.vue +3 -2
  48. package/lib/components/Quiz/KeyboardShortcutsButton.vue +1 -1
  49. package/lib/components/Quiz/KeyboardShortcutsModal.vue +1 -1
  50. package/lib/components/Quiz/Question/ChoicesContainer.vue +99 -132
  51. package/lib/components/Quiz/Question/DropdownExplanation.vue +41 -55
  52. package/lib/components/Quiz/Question/Explanation.vue +49 -59
  53. package/lib/components/Quiz/Question/MatrixChoicesContainer.vue +208 -226
  54. package/lib/components/Quiz/Question/MatrixRadioGroup.vue +7 -6
  55. package/lib/components/Quiz/Question/MobileMatrixChoicesContainer.vue +315 -320
  56. package/lib/components/Quiz/Question/MobileMatrixRadioGroup.vue +14 -11
  57. package/lib/components/Quiz/Question/PassageAndImage.vue +34 -45
  58. package/lib/components/Quiz/Question/PassageAndImageDropdown.vue +39 -49
  59. package/lib/components/Quiz/Question/Paywall.vue +30 -41
  60. package/lib/components/Quiz/Question/QuestionContext.vue +24 -33
  61. package/lib/components/Quiz/Question/StatsSummary.vue +12 -22
  62. package/lib/components/Quiz/Question/Summary.vue +56 -66
  63. package/lib/components/Quiz/Question/composables.ts +71 -0
  64. package/lib/components/Quiz/Question/injectionSymbols.ts +69 -0
  65. package/lib/components/Quiz/Question.vue +810 -1009
  66. package/lib/components/Quiz/QuizContainer.vue +63 -67
  67. package/lib/components/Quiz/QuizProgress.vue +73 -77
  68. package/lib/components/Quiz/QuizProgressBar.vue +3 -2
  69. package/lib/components/Quiz/question.d.ts +4 -4
  70. package/lib/components/Search/Pill.vue +2 -2
  71. package/lib/components/Search/Search.vue +2 -2
  72. package/lib/components/SidePanels/SidePanel.vue +8 -3
  73. package/lib/components/Tables/Table.vue +4 -3
  74. package/lib/components/Tables/TableActions.vue +3 -3
  75. package/lib/components/Tags/Tag.vue +2 -2
  76. package/lib/components/Toasts/Toast.vue +5 -3
  77. package/lib/components/Tooltips/OverflowTooltip.vue +2 -2
  78. package/lib/components/Tooltips/Tooltip.vue +2 -2
  79. package/lib/directives.ts +28 -23
  80. package/lib/pocketprep-export.module.scss +3 -2
  81. package/lib/pocketprep.scss +2 -2
  82. package/lib/styles/_breakpoints.scss +12 -24
  83. package/lib/styles/_colors.scss +0 -1
  84. package/package.json +38 -29
  85. package/stylelint.config.js +38 -0
  86. package/.eslintrc.cjs +0 -74
  87. package/dist/style.css +0 -1
  88. package/stylelint.config.cjs +0 -22
@@ -1,93 +1,89 @@
1
1
  <template>
2
2
  <div
3
- ref="quiz-container"
3
+ ref="quiz-container-ref"
4
4
  v-breakpoint
5
5
  v-dark="isDarkMode"
6
6
  class="uikit-quiz-container"
7
7
  >
8
- <div
9
- v-breakpoint:quizContainerEl
10
- class="uikit-quiz-container__header"
11
- :class="{'uikit-quiz-container__header--dark': isDarkMode}"
12
- :style="customHeaderStyles"
13
- >
14
- <slot name="header" />
15
- </div>
16
- <div class="uikit-quiz-container__main" :style="customMainStyles">
8
+ <template v-if="quizContainerEl">
17
9
  <div
18
- v-if="showSide"
19
- v-breakpoint:quizContainerEl
20
- v-dark="isDarkMode"
21
- class="uikit-quiz-container__side"
10
+ v-breakpoint="{ containerEl: quizContainerEl }"
11
+ class="uikit-quiz-container__header"
12
+ :class="{'uikit-quiz-container__header--dark': isDarkMode}"
13
+ :style="customHeaderStyles"
22
14
  >
23
- <slot name="definition"></slot>
24
- <slot name="side" />
15
+ <slot name="header" />
16
+ </div>
17
+ <div class="uikit-quiz-container__main" :style="customMainStyles">
18
+ <div
19
+ v-if="showSide"
20
+ v-breakpoint="{ containerEl: quizContainerEl }"
21
+ v-dark="isDarkMode"
22
+ class="uikit-quiz-container__side"
23
+ >
24
+ <slot name="definition"></slot>
25
+ <slot name="side" />
26
+ </div>
27
+ <div
28
+ v-breakpoint="{ containerEl: quizContainerEl }"
29
+ class="uikit-quiz-container__question"
30
+ :class="{
31
+ 'uikit-quiz-container__question--show-side': showSide,
32
+ 'uikit-quiz-container__question--dark': isDarkMode
33
+ }"
34
+ >
35
+ <slot name="question" />
36
+ </div>
25
37
  </div>
26
38
  <div
27
- v-breakpoint:quizContainerEl
28
- class="uikit-quiz-container__question"
29
- :class="{
30
- 'uikit-quiz-container__question--show-side': showSide,
31
- 'uikit-quiz-container__question--dark': isDarkMode
32
- }"
39
+ v-breakpoint="{ containerEl: quizContainerEl }"
40
+ class="uikit-quiz-container__footer"
41
+ :class="{'uikit-quiz-container__footer--dark': isDarkMode}"
42
+ :style="customFooterStyles"
33
43
  >
34
- <slot name="question" />
44
+ <slot name="footer" />
35
45
  </div>
36
- </div>
37
- <div
38
- v-breakpoint:quizContainerEl
39
- class="uikit-quiz-container__footer"
40
- :class="{'uikit-quiz-container__footer--dark': isDarkMode}"
41
- :style="customFooterStyles"
42
- >
43
- <slot name="footer" />
44
- </div>
46
+ </template>
45
47
  </div>
46
48
  </template>
47
49
 
48
- <script lang="ts">
49
- import { breakpoint, dark } from '../../directives'
50
- import { Component, Prop, Vue } from 'vue-facing-decorator'
51
- import Icon from '../Icons/Icon.vue'
52
-
53
- @Component({
54
- directives: {
55
- breakpoint,
56
- dark,
57
- },
58
- components: {
59
- Icon,
60
- },
50
+ <script setup lang="ts">
51
+ import { onBeforeUnmount, onMounted, useTemplateRef } from 'vue'
52
+ import { dark as vDark, breakpoint as vBreakpoint } from '../../directives'
53
+
54
+ withDefaults(defineProps<{
55
+ showSide?: boolean
56
+ isDarkMode?: boolean
57
+ customHeaderStyles?: Record<string, string>
58
+ customMainStyles?: Record<string, string>
59
+ customFooterStyles?: Record<string, string>
60
+ }>(), {
61
+ showSide: false,
62
+ isDarkMode: false,
63
+ customHeaderStyles: () => ({}),
64
+ customMainStyles: () => ({}),
65
+ customFooterStyles: () => ({}),
61
66
  })
62
- export default class QuizContainer extends Vue {
63
- @Prop({ default: false }) showSide!: boolean
64
- @Prop({ default: false }) isDarkMode!: boolean
65
- @Prop({ default: () => ({}) }) customHeaderStyles!: Record<string, string>
66
- @Prop({ default: () => ({}) }) customMainStyles!: Record<string, string>
67
- @Prop({ default: () => ({}) }) customFooterStyles!: Record<string, string>
68
-
69
- get quizContainerEl () {
70
- return this.$refs['quiz-container']
71
- }
72
67
 
73
- beforeUnmount () {
74
- const bodyEl = document.getElementsByTagName('body')[0]
75
- if (bodyEl) {
76
- bodyEl.style.overflow = ''
77
- }
68
+ const quizContainerEl = useTemplateRef('quiz-container-ref')
69
+
70
+ onBeforeUnmount(() => {
71
+ const bodyEl = document.getElementsByTagName('body')[0]
72
+ if (bodyEl) {
73
+ bodyEl.style.overflow = ''
78
74
  }
75
+ })
79
76
 
80
- mounted () {
81
- const bodyEl = document.getElementsByTagName('body')[0]
82
- if (bodyEl) {
83
- bodyEl.style.overflow = 'hidden'
84
- }
77
+ onMounted(() => {
78
+ const bodyEl = document.getElementsByTagName('body')[0]
79
+ if (bodyEl) {
80
+ bodyEl.style.overflow = 'hidden'
85
81
  }
86
- }
82
+ })
87
83
  </script>
88
84
 
89
85
  <style lang="scss">
90
- @import '../../styles/colors';
86
+ @use '@/styles/colors' as *;
91
87
 
92
88
  .uikit-quiz-container {
93
89
  display: flex;
@@ -35,104 +35,100 @@
35
35
  </div>
36
36
  </template>
37
37
 
38
- <script lang="ts">
39
- import { Component, Emit, Prop, Vue } from 'vue-facing-decorator'
38
+ <script setup lang="ts">
39
+ import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
40
40
  import QuizProgressBar from '../Quiz/QuizProgressBar.vue'
41
41
  import { ResizeObserver as ResizeObserverPonyFill } from 'resize-observer'
42
42
 
43
- @Component({
44
- components: {
45
- QuizProgressBar,
46
- },
43
+ const props = withDefaults(defineProps<{
44
+ answeredIndexList: number[]
45
+ selectedIndex: number
46
+ numQuestions: number
47
+ forceSlider?: boolean
48
+ }>(), {
49
+ forceSlider: false,
47
50
  })
48
- export default class QuizProgress extends Vue {
49
- @Prop() answeredIndexList!: number[]
50
- @Prop() selectedIndex!: number
51
- @Prop() numQuestions!: number
52
- @Prop({ default: false }) forceSlider!: boolean
53
51
 
54
- containerWidth = 0
55
- mutationObserver: ResizeObserver | null = null
52
+ const emit = defineEmits<{
53
+ 'barClicked': [ index: number ]
54
+ }>()
56
55
 
57
- get isSlider () {
58
- return this.forceSlider || this.numQuestions > 100
59
- }
56
+ const containerWidth = ref(0)
57
+ const mutationObserver = ref<ResizeObserver | null>(null)
60
58
 
61
- get barMaxMargin () {
62
- return this.numQuestions > 100 || this.forceSlider
63
- ? 0 // No margin for >100 questions or slider mode
64
- : this.numQuestions < 50
65
- ? 2
66
- : 2.5
67
- }
59
+ const isSlider = computed(() => {
60
+ return props.forceSlider || props.numQuestions > 100
61
+ })
68
62
 
69
- get barWidth () {
70
- const numGaps = this.numQuestions - 1
71
- const totalMarginWidth = numGaps * this.barMaxMargin * 2
72
- const availableWidth = this.containerWidth - totalMarginWidth
73
- const barWidth = (this.forceSlider || this.numQuestions > 100)
74
- ? availableWidth / this.numQuestions
75
- : Math.floor(Math.max(availableWidth / this.numQuestions, 1))
76
- return barWidth
77
- }
63
+ const barMaxMargin = computed(() => {
64
+ return props.numQuestions > 100 || props.forceSlider
65
+ ? 0 // No margin for >100 questions or slider mode
66
+ : props.numQuestions < 50
67
+ ? 2
68
+ : 2.5
69
+ })
78
70
 
79
- get barMargin () {
80
- const maxMargin = ((this.containerWidth - (this.barWidth * this.numQuestions)) / (this.numQuestions - 1)) / 2
71
+ const barWidth = computed(() => {
72
+ const numGaps = props.numQuestions - 1
73
+ const totalMarginWidth = numGaps * barMaxMargin.value * 2
74
+ const availableWidth = containerWidth.value - totalMarginWidth
75
+ const calculatedBarWidth = (props.forceSlider || props.numQuestions > 100)
76
+ ? availableWidth / props.numQuestions
77
+ : Math.floor(Math.max(availableWidth / props.numQuestions, 1))
78
+ return calculatedBarWidth
79
+ })
81
80
 
82
- return Math.max(
83
- Math.min(this.barMaxMargin, Math.floor(maxMargin)),
84
- 0
85
- )
86
- }
81
+ const barMargin = computed(() => {
82
+ const maxMargin = ((containerWidth.value - (barWidth.value * props.numQuestions)) / (props.numQuestions - 1)) / 2
87
83
 
88
- get barWidthString () {
89
- return `${this.barWidth}px`
90
- }
84
+ return Math.max(
85
+ Math.min(barMaxMargin.value, Math.floor(maxMargin)),
86
+ 0
87
+ )
88
+ })
91
89
 
92
- get barMarginString () {
93
- return `${this.barMargin}px`
94
- }
90
+ const barWidthString = computed(() => {
91
+ return `${barWidth.value}px`
92
+ })
95
93
 
96
- mounted () {
97
- this.containerWidth = document.querySelector('.uikit-quiz-progress')?.getBoundingClientRect().width || 0
98
- const el = document.querySelector('.uikit-quiz-progress') as Element
99
- const resizeMutationObserver = window.ResizeObserver
100
- ? new ResizeObserver(() => {
101
- this.containerWidth = document.querySelector('.uikit-quiz-progress')?.getBoundingClientRect().width || 0
102
- })
103
- : new ResizeObserverPonyFill(() => {
104
- this.containerWidth = document.querySelector('.uikit-quiz-progress')?.getBoundingClientRect().width || 0
105
- })
106
- this.mutationObserver = resizeMutationObserver
107
- this.mutationObserver.observe(el)
108
- }
94
+ onMounted(() => {
95
+ containerWidth.value = document.querySelector('.uikit-quiz-progress')?.getBoundingClientRect().width || 0
96
+ const el = document.querySelector('.uikit-quiz-progress') as Element
97
+ const resizeMutationObserver = window.ResizeObserver
98
+ ? new ResizeObserver(() => {
99
+ containerWidth.value = document.querySelector('.uikit-quiz-progress')?.getBoundingClientRect().width || 0
100
+ })
101
+ : new ResizeObserverPonyFill(() => {
102
+ containerWidth.value = document.querySelector('.uikit-quiz-progress')?.getBoundingClientRect().width || 0
103
+ })
104
+ mutationObserver.value = resizeMutationObserver
105
+ mutationObserver.value.observe(el)
106
+ })
109
107
 
110
- beforeUnmount () {
111
- this.mutationObserver?.disconnect()
112
- }
108
+ onBeforeUnmount(() => {
109
+ mutationObserver.value?.disconnect()
110
+ })
113
111
 
114
- clickAndFocus (index: number) {
115
- const bars = document.querySelectorAll('.uikit-quiz-progress__bar')
116
- const bar = bars[index - 1] as HTMLElement
117
- if (bar) {
118
- this.emitBarClicked(index)
119
- setTimeout(() => {
120
- this.$nextTick(() => {
121
- bar.focus()
122
- })
123
- }, 50)
124
- }
112
+ const clickAndFocus = (index: number) => {
113
+ const bars = document.querySelectorAll('.uikit-quiz-progress__bar')
114
+ const bar = bars[index - 1] as HTMLElement
115
+ if (bar) {
116
+ emitBarClicked(index)
117
+ setTimeout(() => {
118
+ nextTick(() => {
119
+ bar.focus()
120
+ })
121
+ }, 50)
125
122
  }
123
+ }
126
124
 
127
- @Emit('barClicked')
128
- emitBarClicked (index: number) {
129
- return index
130
- }
125
+ const emitBarClicked = (index: number) => {
126
+ emit('barClicked', index)
131
127
  }
132
128
  </script>
133
129
 
134
130
  <style lang="scss">
135
- @import '../../styles/breakpoints';
131
+ @use '@/styles/breakpoints' as *;
136
132
 
137
133
  .uikit-quiz-progress {
138
134
  display: flex;
@@ -18,6 +18,7 @@ import { Component, Emit, Prop, Vue } from 'vue-facing-decorator'
18
18
  import { breakpoint } from '../../directives'
19
19
 
20
20
  @Component({
21
+ name: 'QuizProgressBar',
21
22
  directives: {
22
23
  breakpoint,
23
24
  },
@@ -40,8 +41,8 @@ export default class QuizProgressBar extends Vue {
40
41
  </script>
41
42
 
42
43
  <style lang="scss">
43
- @import '../../styles/colors';
44
- @import '../../styles/breakpoints';
44
+ @use '@/styles/breakpoints' as *;
45
+ @use '@/styles/colors' as *;
45
46
 
46
47
  .uikit-quiz-progress-bar {
47
48
  flex: 1;
@@ -6,12 +6,12 @@ export type TMatrixChoiceKey = `${'a' | 'd'}${1 | 2 | 3 }_${1 | 2 | 3 | 4 | 5 |
6
6
  export type TQuizMode = 'qotd' | 'quick10' | 'timed' | 'weakest' | 'missed' | 'custom'
7
7
 
8
8
  // eslint-disable-next-line max-len
9
- export type TContextIcon = 'quick10' | 'calendar' | 'missedQuestions' | 'subject' | 'stopwatch' | 'exam' | 'levelup' | 'pencil'
9
+ export type TContextIcon = 'quick10' | 'calendar' | 'missedQuestions' | 'subject' | 'stopwatch' | 'exam' | 'levelup' | 'pencil' | 'link'
10
10
 
11
11
  export type TBreakPointsObject = {
12
- mobile: number
13
- tabletPortrait: number
14
- tabletLandscape: number
12
+ 'mobile': number
13
+ 'tablet-portrait': number
14
+ 'tablet-landscape': number
15
15
  }
16
16
 
17
17
  export type TChoice = { text?: string; key: TChoiceKey }
@@ -40,8 +40,8 @@ export default class Pill extends Vue {
40
40
  </script>
41
41
 
42
42
  <style lang="scss">
43
- @import '../../styles/breakpoints';
44
- @import '../../styles/colors';
43
+ @use '@/styles/breakpoints' as *;
44
+ @use '@/styles/colors' as *;
45
45
 
46
46
  .uikit-pill {
47
47
  background: $brand-black;
@@ -124,8 +124,8 @@ export default class Search extends Vue {
124
124
  </script>
125
125
 
126
126
  <style lang="scss">
127
- @import '../../styles/colors';
128
- @import '../../styles/breakpoints';
127
+ @use '@/styles/breakpoints' as *;
128
+ @use '@/styles/colors' as *;
129
129
 
130
130
  .uikit-search {
131
131
  position: relative;
@@ -128,6 +128,7 @@ import Icon from '../Icons/Icon.vue'
128
128
  import { dark } from '../../directives'
129
129
 
130
130
  @Component({
131
+ name: 'SidePanel',
131
132
  components: {
132
133
  Icon,
133
134
  PocketButton: Button,
@@ -150,7 +151,7 @@ export default class SidePanel extends Vue {
150
151
  @Prop({ default: false }) isDarkMode!: boolean
151
152
 
152
153
  openSidePanel = false
153
- notContentHeight = this.tabs && this.tabs.length ? 262 : 218
154
+ notContentHeight = this.tabs?.length ? 262 : 218
154
155
  focusListener: Parameters<typeof addEventListener>[1] | null = null
155
156
  savedYPosition = 0
156
157
  sidePanelNumber = 0
@@ -289,8 +290,8 @@ export default class SidePanel extends Vue {
289
290
  </script>
290
291
 
291
292
  <style lang="scss">
292
- @import '../../styles/colors';
293
- @import '../../styles/breakpoints';
293
+ @use '@/styles/breakpoints' as *;
294
+ @use '@/styles/colors' as *;
294
295
 
295
296
  .uikit-page-overlay {
296
297
  background: rgba($brand-black, 0);
@@ -588,6 +589,10 @@ export default class SidePanel extends Vue {
588
589
 
589
590
  &--teach-side-panel {
590
591
  background-color: $white;
592
+
593
+ &--dark {
594
+ background: $charcoal;
595
+ }
591
596
  }
592
597
 
593
598
  &--dark {
@@ -379,8 +379,9 @@ export default class Table extends Vue {
379
379
  </script>
380
380
 
381
381
  <style lang="scss">
382
- @import '../../styles/colors';
383
- @import '../../styles/breakpoints';
382
+ @use 'sass:color';
383
+ @use '@/styles/breakpoints' as *;
384
+ @use '@/styles/colors' as *;
384
385
 
385
386
  .uikit-table {
386
387
  &__container {
@@ -584,7 +585,7 @@ export default class Table extends Vue {
584
585
 
585
586
  &--hover-focus {
586
587
  &:hover {
587
- background-color: mix($barely-background, $brand-black, 96%);
588
+ background-color: color.mix($barely-background, $brand-black, 96%);
588
589
  }
589
590
 
590
591
  &:focus {
@@ -77,7 +77,7 @@ export default class TableActions extends Vue {
77
77
  }
78
78
 
79
79
  actionClicked (action: ITableAction | ITableSubAction) {
80
- if ('menu' in action && action.menu && action.menu.length) {
80
+ if ('menu' in action && action.menu?.length) {
81
81
  if (this.visibleMenuActionId !== action.id) {
82
82
  this.focusedMenuOptionIndex = null
83
83
  this.visibleMenuActionId = action.id
@@ -139,8 +139,8 @@ export default class TableActions extends Vue {
139
139
  </script>
140
140
 
141
141
  <style lang="scss">
142
- @import '../../styles/colors';
143
- @import '../../styles/breakpoints';
142
+ @use '@/styles/breakpoints' as *;
143
+ @use '@/styles/colors' as *;
144
144
 
145
145
  .uikit-table-actions {
146
146
  display: flex;
@@ -64,8 +64,8 @@ export default class Tag extends Vue {
64
64
  </script>
65
65
 
66
66
  <style lang="scss">
67
- @import '../../styles/breakpoints';
68
- @import '../../styles/colors';
67
+ @use '@/styles/breakpoints' as *;
68
+ @use '@/styles/colors' as *;
69
69
 
70
70
  .uikit-tag {
71
71
  box-sizing: border-box;
@@ -80,7 +80,9 @@ export default class Toast extends Vue {
80
80
  }
81
81
 
82
82
  clearCloseTimeout () {
83
- this.closeTimeout && clearTimeout(this.closeTimeout)
83
+ if (this.closeTimeout) {
84
+ clearTimeout(this.closeTimeout)
85
+ }
84
86
  }
85
87
 
86
88
  @Emit('close')
@@ -91,8 +93,8 @@ export default class Toast extends Vue {
91
93
  </script>
92
94
 
93
95
  <style lang="scss" scoped>
94
- @import '../../styles/breakpoints';
95
- @import '../../styles/colors';
96
+ @use '@/styles/breakpoints' as *;
97
+ @use '@/styles/colors' as *;
96
98
 
97
99
  .toast {
98
100
  background-color: rgba($charcoal, 0.9);
@@ -82,8 +82,8 @@ export default class OverflowTooltip extends Vue {
82
82
  </script>
83
83
 
84
84
  <style lang="scss">
85
- @import '../../styles/breakpoints';
86
- @import '../../styles/colors';
85
+ @use '@/styles/breakpoints' as *;
86
+ @use '@/styles/colors' as *;
87
87
 
88
88
  .uikit-overflow-tooltip {
89
89
  position: relative;
@@ -103,8 +103,8 @@ export default class Tooltip extends Vue {
103
103
  </script>
104
104
 
105
105
  <style lang="scss">
106
- @import '../../styles/colors';
107
- @import '../../styles/breakpoints';
106
+ @use '@/styles/breakpoints' as *;
107
+ @use '@/styles/colors' as *;
108
108
 
109
109
  .uikit-tooltip-popup {
110
110
  color: $white;
package/lib/directives.ts CHANGED
@@ -4,7 +4,11 @@ import { ResizeObserver as ResizeObserverPonyFill } from 'resize-observer'
4
4
 
5
5
  type TBreakpoints = { [breakpointName: string]: number }
6
6
 
7
- const updateBreakpointClasses = (el: HTMLElement, breakpoints?: TBreakpoints, container?: HTMLElement) => {
7
+ const updateBreakpointClasses = (
8
+ el: HTMLElement,
9
+ breakpointsWithEl?: { breakpoints?: TBreakpoints; containerEl?: HTMLElement | null },
10
+ container?: HTMLElement | null
11
+ ) => {
8
12
  // calculate screen width
9
13
  const mediaBreakpoints: string[] = []
10
14
  if (window.matchMedia(`(max-width: ${MediaBreakpoints.blackBear}px)`).matches) {
@@ -20,24 +24,20 @@ const updateBreakpointClasses = (el: HTMLElement, breakpoints?: TBreakpoints, co
20
24
  const customBreakpoints: string[] = []
21
25
 
22
26
  // If no custom breakpoints passed, use default breakpoints that match design's
23
- if (!breakpoints) {
24
- breakpoints = {
25
- 'mobile': Number(MediaBreakpoints.blackBear),
26
- 'tablet-portrait': Number(MediaBreakpoints.brownBear),
27
- 'tablet-landscape': Number(MediaBreakpoints.grizzlyBear),
28
- 'desktop': Number(MediaBreakpoints.polarBear),
29
- }
27
+ const appliedBreakpoints = breakpointsWithEl?.breakpoints || {
28
+ 'mobile': Number(MediaBreakpoints.blackBear),
29
+ 'tablet-portrait': Number(MediaBreakpoints.brownBear),
30
+ 'tablet-landscape': Number(MediaBreakpoints.grizzlyBear),
31
+ 'desktop': Number(MediaBreakpoints.polarBear),
30
32
  }
31
33
 
32
- if (breakpoints) {
33
- Object.entries(breakpoints)
34
- .forEach(([ name, width ]) => {
35
- breakpointSuffixes.push(name)
36
- if (elWidth <= width) {
37
- customBreakpoints.push(name)
38
- }
39
- })
40
- }
34
+ Object.entries(appliedBreakpoints)
35
+ .forEach(([ name, width ]) => {
36
+ breakpointSuffixes.push(name)
37
+ if (elWidth <= width) {
38
+ customBreakpoints.push(name)
39
+ }
40
+ })
41
41
 
42
42
  const classes = el.getAttribute('class')?.split(' ') || []
43
43
  const nonModifierClasses = classes.filter(className => !className.includes('--'))
@@ -65,17 +65,19 @@ const updateBreakpointClasses = (el: HTMLElement, breakpoints?: TBreakpoints, co
65
65
  }
66
66
  }
67
67
 
68
- const getCustomContainer = (binding: DirectiveBinding) => {
69
- const bindingArg = binding.arg
70
- const container = bindingArg && binding.instance && binding.instance[bindingArg as keyof typeof binding.instance]
71
- return container
68
+ const getCustomContainer = (binding: DirectiveBinding<{
69
+ breakpoints?: TBreakpoints
70
+ containerEl?: HTMLElement | null
71
+ } | undefined>) => {
72
+ const container = binding.value?.containerEl
73
+ return container || null
72
74
  }
73
75
 
74
76
  const eventListeners: Partial<Record<string, () => void>> = {}
75
77
  const mutationObservers: Partial<Record<string, MutationObserver>> = {}
76
78
  const resizeObservers: Partial<Record<string, ResizeObserver>> = {}
77
79
 
78
- export const fixed: Directive = {
80
+ export const fixed: Directive<HTMLElement> = {
79
81
  beforeMount: el => {
80
82
  if (!el.dataset.breakpointId) {
81
83
  const { top, left } = el.getBoundingClientRect()
@@ -105,7 +107,10 @@ export const fixed: Directive = {
105
107
  },
106
108
  }
107
109
 
108
- export const breakpoint: Directive = {
110
+ export const breakpoint: Directive<HTMLElement, {
111
+ breakpoints?: TBreakpoints
112
+ containerEl?: HTMLElement | null
113
+ } | undefined> = {
109
114
  beforeMount (el, binding) {
110
115
  if (!el.dataset.breakpointId) {
111
116
  binding.instance?.$nextTick(() => {
@@ -1,5 +1,5 @@
1
- @import './styles/breakpoints';
2
- @import './styles/colors';
1
+ @use './styles/breakpoints' as *;
2
+ @use './styles/colors' as *;
3
3
 
4
4
  /* stylelint-disable property-case */
5
5
  :export {
@@ -10,6 +10,7 @@
10
10
  blackBear: $black-bear;
11
11
  koalaBear: $koala-bear;
12
12
  teddyBear: $teddy-bear;
13
+
13
14
  // colors
14
15
  white: $white;
15
16
  pickledBluewood: $pickled-bluewood;
@@ -1,5 +1,5 @@
1
- @import './styles/breakpoints';
2
- @import './styles/colors';
1
+ @use './styles/breakpoints' as *;
2
+ @use './styles/colors' as *;
3
3
 
4
4
  body,
5
5
  html {