@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.
- package/README.md +2 -2
- package/dist/@pocketprep/ui-kit.css +1 -0
- package/dist/@pocketprep/ui-kit.js +16490 -18228
- package/dist/@pocketprep/ui-kit.js.map +1 -1
- package/dist/@pocketprep/ui-kit.umd.cjs +11 -11
- package/dist/@pocketprep/ui-kit.umd.cjs.map +1 -1
- package/eslint.config.ts +111 -0
- package/lib/components/Banners/Banner.vue +2 -2
- package/lib/components/Bundles/BundleList.vue +1 -1
- package/lib/components/Bundles/BundleSearch.vue +43 -12
- package/lib/components/Bundles/PremiumPill.vue +2 -2
- package/lib/components/Buttons/Button.vue +19 -18
- package/lib/components/Buttons/Link.vue +9 -8
- package/lib/components/Buttons/Tab.vue +4 -3
- package/lib/components/Calendar/Calendar.vue +14 -2
- package/lib/components/Charts/Bar.vue +3 -3
- package/lib/components/Charts/Pie.vue +4 -4
- package/lib/components/Controls/SegmentControl.vue +8 -7
- package/lib/components/Controls/Slider.vue +2 -3
- package/lib/components/Controls/ToggleSwitch.vue +3 -2
- package/lib/components/EmptyStates/EmptyState.vue +3 -2
- package/lib/components/Exams/ExamCard.vue +3 -3
- package/lib/components/Exams/ExamMenuCard.vue +2 -2
- package/lib/components/Filters/FilterDropdown.vue +2 -2
- package/lib/components/Filters/FilterOptions.vue +2 -2
- package/lib/components/Forms/Checkbox.vue +2 -2
- package/lib/components/Forms/CheckboxOption.vue +2 -2
- package/lib/components/Forms/Errors.vue +2 -2
- package/lib/components/Forms/Input.vue +2 -2
- package/lib/components/Forms/Radio.vue +37 -39
- package/lib/components/Forms/RadioButton.vue +1 -1
- package/lib/components/Forms/Select.vue +7 -6
- package/lib/components/Forms/Textarea.vue +2 -2
- package/lib/components/Icons/Icon.vue +1 -0
- package/lib/components/Icons/IconEdit.vue +4 -2
- package/lib/components/Icons/IconFullViewActive.vue +1 -1
- package/lib/components/Icons/IconLoading2.vue +1 -3
- package/lib/components/Loaders/SkeletonLoader.vue +2 -2
- package/lib/components/Messaging/InfoMessage.vue +2 -2
- package/lib/components/Modal/Modal.vue +2 -2
- package/lib/components/Modal/ModalContainer.vue +2 -2
- package/lib/components/Onboarding/EmailAuth.vue +5 -5
- package/lib/components/Onboarding/MagicCodeEntry.vue +3 -4
- package/lib/components/Pagination/QuestionReviewPagination.vue +23 -21
- package/lib/components/Pagination/TablePagination.vue +2 -2
- package/lib/components/Quiz/FlagToggle.vue +2 -2
- package/lib/components/Quiz/GlobalMetricsToggle.vue +3 -2
- package/lib/components/Quiz/KeyboardShortcutsButton.vue +1 -1
- package/lib/components/Quiz/KeyboardShortcutsModal.vue +1 -1
- package/lib/components/Quiz/Question/ChoicesContainer.vue +99 -132
- package/lib/components/Quiz/Question/DropdownExplanation.vue +41 -55
- package/lib/components/Quiz/Question/Explanation.vue +49 -59
- package/lib/components/Quiz/Question/MatrixChoicesContainer.vue +208 -226
- package/lib/components/Quiz/Question/MatrixRadioGroup.vue +7 -6
- package/lib/components/Quiz/Question/MobileMatrixChoicesContainer.vue +315 -320
- package/lib/components/Quiz/Question/MobileMatrixRadioGroup.vue +14 -11
- package/lib/components/Quiz/Question/PassageAndImage.vue +34 -45
- package/lib/components/Quiz/Question/PassageAndImageDropdown.vue +39 -49
- package/lib/components/Quiz/Question/Paywall.vue +30 -41
- package/lib/components/Quiz/Question/QuestionContext.vue +24 -33
- package/lib/components/Quiz/Question/StatsSummary.vue +12 -22
- package/lib/components/Quiz/Question/Summary.vue +56 -66
- package/lib/components/Quiz/Question/composables.ts +71 -0
- package/lib/components/Quiz/Question/injectionSymbols.ts +69 -0
- package/lib/components/Quiz/Question.vue +810 -1009
- package/lib/components/Quiz/QuizContainer.vue +63 -67
- package/lib/components/Quiz/QuizProgress.vue +73 -77
- package/lib/components/Quiz/QuizProgressBar.vue +3 -2
- package/lib/components/Quiz/question.d.ts +4 -4
- package/lib/components/Search/Pill.vue +2 -2
- package/lib/components/Search/Search.vue +2 -2
- package/lib/components/SidePanels/SidePanel.vue +8 -3
- package/lib/components/Tables/Table.vue +4 -3
- package/lib/components/Tables/TableActions.vue +3 -3
- package/lib/components/Tags/Tag.vue +2 -2
- package/lib/components/Toasts/Toast.vue +5 -3
- package/lib/components/Tooltips/OverflowTooltip.vue +2 -2
- package/lib/components/Tooltips/Tooltip.vue +2 -2
- package/lib/directives.ts +28 -23
- package/lib/pocketprep-export.module.scss +3 -2
- package/lib/pocketprep.scss +2 -2
- package/lib/styles/_breakpoints.scss +12 -24
- package/lib/styles/_colors.scss +0 -1
- package/package.json +38 -29
- package/stylelint.config.js +38 -0
- package/.eslintrc.cjs +0 -74
- package/dist/style.css +0 -1
- 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
|
-
<
|
|
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-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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="
|
|
24
|
-
|
|
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-
|
|
29
|
-
:class="{
|
|
30
|
-
|
|
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="
|
|
44
|
+
<slot name="footer" />
|
|
35
45
|
</div>
|
|
36
|
-
</
|
|
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 {
|
|
50
|
-
import {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
@
|
|
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 {
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
55
|
-
|
|
52
|
+
const emit = defineEmits<{
|
|
53
|
+
'barClicked': [ index: number ]
|
|
54
|
+
}>()
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
56
|
+
const containerWidth = ref(0)
|
|
57
|
+
const mutationObserver = ref<ResizeObserver | null>(null)
|
|
60
58
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
80
|
-
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
0
|
|
85
|
-
)
|
|
86
|
-
}
|
|
81
|
+
const barMargin = computed(() => {
|
|
82
|
+
const maxMargin = ((containerWidth.value - (barWidth.value * props.numQuestions)) / (props.numQuestions - 1)) / 2
|
|
87
83
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
84
|
+
return Math.max(
|
|
85
|
+
Math.min(barMaxMargin.value, Math.floor(maxMargin)),
|
|
86
|
+
0
|
|
87
|
+
)
|
|
88
|
+
})
|
|
91
89
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
const barWidthString = computed(() => {
|
|
91
|
+
return `${barWidth.value}px`
|
|
92
|
+
})
|
|
95
93
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
onBeforeUnmount(() => {
|
|
109
|
+
mutationObserver.value?.disconnect()
|
|
110
|
+
})
|
|
113
111
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
128
|
-
|
|
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
|
-
@
|
|
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
|
-
@
|
|
44
|
-
@
|
|
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
|
-
|
|
14
|
-
|
|
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
|
-
@
|
|
44
|
-
@
|
|
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
|
-
@
|
|
128
|
-
@
|
|
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
|
|
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
|
-
@
|
|
293
|
-
@
|
|
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
|
-
@
|
|
383
|
-
@
|
|
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
|
|
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
|
-
@
|
|
143
|
-
@
|
|
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
|
-
@
|
|
68
|
-
@
|
|
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
|
-
|
|
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
|
-
@
|
|
95
|
-
@
|
|
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
|
-
@
|
|
86
|
-
@
|
|
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
|
-
@
|
|
107
|
-
@
|
|
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 = (
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
@
|
|
2
|
-
@
|
|
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;
|
package/lib/pocketprep.scss
CHANGED