@pocketprep/ui-kit 3.1.1 → 3.1.3
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.js +1958 -1928
- package/dist/@pocketprep/ui-kit.js.map +1 -1
- package/dist/@pocketprep/ui-kit.umd.cjs +8 -8
- package/dist/@pocketprep/ui-kit.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/lib/components/Filters/FilterDropdown.vue +86 -47
- package/lib/components/Filters/FilterOptions.vue +28 -13
- package/lib/components/Pagination/TablePagination.vue +59 -15
- package/package.json +1 -1
|
@@ -1,43 +1,48 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="filter">
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
<Link
|
|
4
|
+
v-dark="isDarkMode"
|
|
5
|
+
:has-icon="true"
|
|
6
|
+
:aria-expanded="showFilterDropdown ? 'true' : 'false'"
|
|
7
|
+
class="filter__link"
|
|
8
|
+
:class="{
|
|
9
|
+
'filter__link--open': showFilterDropdown,
|
|
10
|
+
'filter__link--responsive': responsiveButton,
|
|
11
|
+
}"
|
|
12
|
+
role="button"
|
|
13
|
+
type="tertiary"
|
|
14
|
+
tabindex="0"
|
|
15
|
+
@keypress.enter="showFilterDropdown"
|
|
16
|
+
@click="showFilterDropdown = !showFilterDropdown"
|
|
17
|
+
>
|
|
18
|
+
<Icon
|
|
19
|
+
type="filter"
|
|
20
|
+
class="filter__icon"
|
|
21
|
+
/>
|
|
22
|
+
<span
|
|
23
|
+
class="filter__text"
|
|
9
24
|
:class="{
|
|
10
|
-
'
|
|
11
|
-
'filter-button__link--responsive': responsiveButton,
|
|
25
|
+
'filter__text--responsive': responsiveButton,
|
|
12
26
|
}"
|
|
13
|
-
role="button"
|
|
14
|
-
type="tertiary"
|
|
15
|
-
tabindex="0"
|
|
16
|
-
@keypress.enter="showFilterDropdown"
|
|
17
|
-
@click="showFilterDropdown = !showFilterDropdown"
|
|
18
27
|
>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/>
|
|
23
|
-
<span class="filter-button__text">
|
|
24
|
-
{{ filterLabel }}
|
|
25
|
-
</span>
|
|
26
|
-
</Link>
|
|
27
|
-
</div>
|
|
28
|
+
{{ filterLabel }}
|
|
29
|
+
</span>
|
|
30
|
+
</Link>
|
|
28
31
|
<div
|
|
29
32
|
v-if="showFilterDropdown"
|
|
30
33
|
v-dark="isDarkMode"
|
|
31
|
-
class="
|
|
32
|
-
:class="{
|
|
33
|
-
[`
|
|
34
|
-
[`
|
|
34
|
+
class="filter__dropdown"
|
|
35
|
+
:class="{
|
|
36
|
+
[`filter__dropdown--${align}`]: true,
|
|
37
|
+
[`filter__dropdown--${size}`]: true
|
|
35
38
|
}"
|
|
36
39
|
>
|
|
37
40
|
<slot name="filterOptions">
|
|
38
41
|
<FilterOptions
|
|
39
42
|
:radio-entries="radioOptions"
|
|
40
43
|
:checkbox-entries="checkboxOptions"
|
|
44
|
+
:is-dark-mode="isDarkMode"
|
|
45
|
+
:filter-options-label="filterOptionsLabel"
|
|
41
46
|
>
|
|
42
47
|
<template #checkboxLabelText>
|
|
43
48
|
<slot name="checkboxLabelText" />
|
|
@@ -75,15 +80,18 @@ export default class FilterDropdown extends Vue {
|
|
|
75
80
|
@Prop({ default: 'small' }) size!: 'small' | 'large'
|
|
76
81
|
@Prop({ default: false }) isDarkMode!: boolean
|
|
77
82
|
@Prop({ default: false }) responsiveButton!: boolean
|
|
83
|
+
@Prop({ default: 'FILTER BY SUBJECT' }) filterOptionsLabel?: string
|
|
78
84
|
|
|
79
|
-
radioOptions = [
|
|
80
|
-
checkboxOptions = [
|
|
85
|
+
radioOptions: TRadioOption[] = []
|
|
86
|
+
checkboxOptions: TCheckboxOption[] = []
|
|
81
87
|
|
|
82
88
|
showFilterDropdown: boolean | 'checkbox' = false
|
|
83
89
|
|
|
84
90
|
mounted () {
|
|
85
91
|
document.addEventListener('click', this.clickListener)
|
|
86
92
|
document.addEventListener('keydown', this.keydownListener)
|
|
93
|
+
this.radioOptions = [ ...this.radioEntries ]
|
|
94
|
+
this.checkboxOptions = [ ...this.checkboxEntries ]
|
|
87
95
|
}
|
|
88
96
|
|
|
89
97
|
keydownListener (e: KeyboardEvent) {
|
|
@@ -148,34 +156,65 @@ export default class FilterDropdown extends Vue {
|
|
|
148
156
|
@import '../../styles/breakpoints';
|
|
149
157
|
|
|
150
158
|
.filter {
|
|
151
|
-
|
|
152
|
-
|
|
159
|
+
position: relative;
|
|
160
|
+
z-index: 2;
|
|
153
161
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
162
|
+
&__link {
|
|
163
|
+
align-items: center;
|
|
164
|
+
display: flex;
|
|
157
165
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
166
|
+
&--open {
|
|
167
|
+
color: $brand-black !important;
|
|
168
|
+
|
|
169
|
+
&--dark {
|
|
170
|
+
color: $butterscotch !important;
|
|
161
171
|
}
|
|
172
|
+
}
|
|
162
173
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
174
|
+
svg {
|
|
175
|
+
margin-right: 3px;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
&__icon {
|
|
180
|
+
padding-bottom: 1px;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
&__text {
|
|
184
|
+
margin-top: 1px;
|
|
185
|
+
|
|
186
|
+
&--responsive {
|
|
187
|
+
@include breakpoint(black-bear) {
|
|
188
|
+
display: none;
|
|
168
189
|
}
|
|
169
|
-
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
&__dropdown {
|
|
194
|
+
position: absolute;
|
|
195
|
+
right: -14px;
|
|
196
|
+
top: 28px;
|
|
197
|
+
width: 204px;
|
|
198
|
+
border-radius: 8px;
|
|
199
|
+
z-index: 1;
|
|
200
|
+
box-sizing: border-box;
|
|
201
|
+
background: $white;
|
|
202
|
+
box-shadow: 0 6px 22px 0 rgba($brand-black, 0.1);
|
|
203
|
+
max-height: 305px;
|
|
204
|
+
overflow: auto;
|
|
205
|
+
|
|
206
|
+
&--dark {
|
|
207
|
+
background: $brand-black;
|
|
208
|
+
box-shadow: 0 1px 6px 0 rgba($jet, 0.3);
|
|
170
209
|
}
|
|
171
210
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
211
|
+
&--left {
|
|
212
|
+
right: auto;
|
|
213
|
+
left: -14px;
|
|
175
214
|
}
|
|
176
215
|
|
|
177
|
-
|
|
178
|
-
|
|
216
|
+
&--large {
|
|
217
|
+
width: 250px;
|
|
179
218
|
}
|
|
180
219
|
}
|
|
181
220
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
-
v-dark
|
|
3
|
+
v-dark="isDarkMode"
|
|
4
4
|
class="filter-options"
|
|
5
5
|
:class="{
|
|
6
6
|
[`filter-options--${align}`]: true,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<slot name="radioLabel">
|
|
11
11
|
<div
|
|
12
12
|
v-if="radioOptions.length > 0"
|
|
13
|
-
v-dark
|
|
13
|
+
v-dark="isDarkMode"
|
|
14
14
|
class="filter-options__label"
|
|
15
15
|
:class="{ 'filter-options__label--active': showRadioOptions }"
|
|
16
16
|
:aria-expanded="showFilterDropdown ? 'true' : 'false'"
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
<slot name="checkboxLabel">
|
|
42
42
|
<div
|
|
43
43
|
v-if="radioOptions.length > 0"
|
|
44
|
-
v-dark
|
|
44
|
+
v-dark="isDarkMode"
|
|
45
45
|
class="filter-options__label"
|
|
46
46
|
:class="{ 'filter-options__label--active': showCheckboxOptions }"
|
|
47
47
|
:aria-expanded="showFilterDropdown ? 'true' : 'false'"
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
@mousedown.prevent
|
|
50
50
|
>
|
|
51
51
|
<slot name="checkboxLabelText">
|
|
52
|
-
<span>
|
|
52
|
+
<span>{{ filterOptionsLabel }}</span>
|
|
53
53
|
</slot>
|
|
54
54
|
<slot name="checkboxLabelIcon">
|
|
55
55
|
<Icon
|
|
@@ -61,13 +61,13 @@
|
|
|
61
61
|
</div>
|
|
62
62
|
<div
|
|
63
63
|
v-else
|
|
64
|
-
v-dark
|
|
64
|
+
v-dark="isDarkMode"
|
|
65
65
|
class="filter-options__label"
|
|
66
66
|
:class="{ 'filter-options__label--active': showCheckboxOptions }"
|
|
67
67
|
:aria-expanded="showFilterDropdown ? 'true' : 'false'"
|
|
68
68
|
>
|
|
69
69
|
<slot name="checkboxLabelText">
|
|
70
|
-
<span>
|
|
70
|
+
<span>{{ filterOptionsLabel }}</span>
|
|
71
71
|
</slot>
|
|
72
72
|
</div>
|
|
73
73
|
</slot>
|
|
@@ -80,10 +80,12 @@
|
|
|
80
80
|
v-for="option in checkboxOptions"
|
|
81
81
|
:key="option.id"
|
|
82
82
|
v-model="option.enabled"
|
|
83
|
-
|
|
83
|
+
:is-dark-mode="isDarkMode"
|
|
84
84
|
:label="option.label"
|
|
85
85
|
class="filter-options__option"
|
|
86
|
-
|
|
86
|
+
:class="{
|
|
87
|
+
'filter-options__option--force-break': !stringHasSpaces(option.label)
|
|
88
|
+
}"
|
|
87
89
|
/>
|
|
88
90
|
</div>
|
|
89
91
|
</slot>
|
|
@@ -95,6 +97,7 @@ import { Component, Emit, Prop, Vue, Watch } from 'vue-facing-decorator'
|
|
|
95
97
|
import CheckboxOption from '../Forms/CheckboxOption.vue'
|
|
96
98
|
import Link from '../Buttons/Link.vue'
|
|
97
99
|
import Radio from '../Forms/Radio.vue'
|
|
100
|
+
import Icon from '../Icons/Icon.vue'
|
|
98
101
|
import { dark } from '../../directives'
|
|
99
102
|
import type { TRadioOption, TCheckboxOption } from './filterOptions'
|
|
100
103
|
|
|
@@ -103,6 +106,7 @@ import type { TRadioOption, TCheckboxOption } from './filterOptions'
|
|
|
103
106
|
CheckboxOption,
|
|
104
107
|
Link,
|
|
105
108
|
Radio,
|
|
109
|
+
Icon,
|
|
106
110
|
},
|
|
107
111
|
directives: {
|
|
108
112
|
dark,
|
|
@@ -117,9 +121,10 @@ export default class FilterOptions extends Vue {
|
|
|
117
121
|
@Prop({ default: 'right' }) align!: 'left' | 'right'
|
|
118
122
|
@Prop({ default: 'small' }) size!: 'small' | 'large'
|
|
119
123
|
@Prop({ default: false }) isDarkMode!: boolean
|
|
124
|
+
@Prop({ default: 'FILTER BY SUBJECT' }) filterOptionsLabel?: string
|
|
120
125
|
|
|
121
|
-
radioOptions = [
|
|
122
|
-
checkboxOptions = [
|
|
126
|
+
radioOptions: TRadioOption[] = []
|
|
127
|
+
checkboxOptions: TCheckboxOption[] = []
|
|
123
128
|
|
|
124
129
|
showFilterDropdown: boolean | 'checkbox' = false
|
|
125
130
|
showRadioOptions = true
|
|
@@ -154,6 +159,8 @@ export default class FilterOptions extends Vue {
|
|
|
154
159
|
mounted () {
|
|
155
160
|
document.addEventListener('click', this.clickListener)
|
|
156
161
|
document.addEventListener('keydown', this.keydownListener)
|
|
162
|
+
this.radioOptions = [ ...this.radioEntries ]
|
|
163
|
+
this.checkboxOptions = [ ...this.checkboxEntries ]
|
|
157
164
|
}
|
|
158
165
|
|
|
159
166
|
@Watch('checkboxOptions', { deep: true })
|
|
@@ -199,13 +206,18 @@ export default class FilterOptions extends Vue {
|
|
|
199
206
|
background: $white;
|
|
200
207
|
border-radius: 8px;
|
|
201
208
|
box-shadow: 0 6px 22px 0 rgba($brand-black, 0.1);
|
|
202
|
-
padding-bottom: 20px;
|
|
203
209
|
box-sizing: border-box;
|
|
204
210
|
width: 100%;
|
|
205
211
|
max-width: 250px;
|
|
206
212
|
font-weight: 500;
|
|
207
213
|
max-height: 305px;
|
|
208
214
|
overflow: auto;
|
|
215
|
+
padding: 5px 0 16px;
|
|
216
|
+
|
|
217
|
+
&--dark {
|
|
218
|
+
background: $brand-black;
|
|
219
|
+
box-shadow: 0 1px 6px 0 rgba($jet, 0.3);
|
|
220
|
+
}
|
|
209
221
|
|
|
210
222
|
&__label {
|
|
211
223
|
display: flex;
|
|
@@ -234,7 +246,7 @@ export default class FilterOptions extends Vue {
|
|
|
234
246
|
}
|
|
235
247
|
|
|
236
248
|
&--dark {
|
|
237
|
-
color: $
|
|
249
|
+
color: $white;
|
|
238
250
|
|
|
239
251
|
&:focus::before {
|
|
240
252
|
border-color: $banana-bread;
|
|
@@ -259,7 +271,10 @@ export default class FilterOptions extends Vue {
|
|
|
259
271
|
&__option {
|
|
260
272
|
padding-left: 14px;
|
|
261
273
|
margin: 0 6px;
|
|
262
|
-
|
|
274
|
+
|
|
275
|
+
&--force-break {
|
|
276
|
+
word-break: break-all;
|
|
277
|
+
}
|
|
263
278
|
}
|
|
264
279
|
}
|
|
265
280
|
</style>
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
2
|
+
<div
|
|
3
|
+
v-dark="isDarkMode"
|
|
4
|
+
class="uikit-table-pagination"
|
|
5
|
+
>
|
|
6
|
+
<div
|
|
7
|
+
ref="pagination_info"
|
|
8
|
+
v-dark="isDarkMode"
|
|
9
|
+
class="uikit-table-pagination__info"
|
|
10
|
+
tabindex="-1"
|
|
11
|
+
>
|
|
4
12
|
{{ (currentPage * perPage) + 1 }} -
|
|
5
13
|
{{ nextPageDisabled ? total : (currentPage * perPage) + perPage }}
|
|
6
14
|
of {{ total }} {{ unit }} <slot />
|
|
7
15
|
</div>
|
|
8
16
|
<div
|
|
17
|
+
v-dark="isDarkMode"
|
|
9
18
|
class="uikit-table-pagination__previous"
|
|
10
19
|
:class="{ 'uikit-table-pagination__previous--disabled': currentPage === 0 }"
|
|
11
20
|
:tabindex="currentPage === 0 ? -1 : 0"
|
|
@@ -13,10 +22,12 @@
|
|
|
13
22
|
:aria-disabled="currentPage === 0"
|
|
14
23
|
@keydown.enter="changePage('previous')"
|
|
15
24
|
@click="changePage('previous')"
|
|
25
|
+
@mousedown.prevent
|
|
16
26
|
>
|
|
17
|
-
<Icon type="accordionArrow"
|
|
27
|
+
<Icon type="accordionArrow" />
|
|
18
28
|
</div>
|
|
19
29
|
<div
|
|
30
|
+
v-dark="isDarkMode"
|
|
20
31
|
class="uikit-table-pagination__next"
|
|
21
32
|
:class="{ 'uikit-table-pagination__next--disabled': nextPageDisabled }"
|
|
22
33
|
:tabindex="nextPageDisabled ? -1 : 0"
|
|
@@ -24,8 +35,9 @@
|
|
|
24
35
|
:aria-disabled="nextPageDisabled"
|
|
25
36
|
@keydown.enter="changePage('next')"
|
|
26
37
|
@click="changePage('next')"
|
|
38
|
+
@mousedown.prevent
|
|
27
39
|
>
|
|
28
|
-
<Icon type="accordionArrow"
|
|
40
|
+
<Icon type="accordionArrow" />
|
|
29
41
|
</div>
|
|
30
42
|
</div>
|
|
31
43
|
</template>
|
|
@@ -33,17 +45,22 @@
|
|
|
33
45
|
<script lang="ts">
|
|
34
46
|
import { Vue, Component, Prop, Emit } from 'vue-facing-decorator'
|
|
35
47
|
import Icon from '../Icons/Icon.vue'
|
|
48
|
+
import { dark } from '../../directives'
|
|
36
49
|
|
|
37
50
|
@Component({
|
|
38
51
|
components: {
|
|
39
52
|
Icon,
|
|
40
53
|
},
|
|
54
|
+
directives: {
|
|
55
|
+
dark,
|
|
56
|
+
},
|
|
41
57
|
})
|
|
42
58
|
export default class TablePagination extends Vue {
|
|
43
59
|
@Prop({ default: 10 }) perPage!: number
|
|
44
60
|
@Prop({ default: 0 }) currentPage!: number
|
|
45
61
|
@Prop() total!: number
|
|
46
62
|
@Prop() unit!: string
|
|
63
|
+
@Prop({ default: false }) isDarkMode!: boolean
|
|
47
64
|
|
|
48
65
|
get nextPageDisabled () {
|
|
49
66
|
return this.currentPage >= Math.floor((this.total - 1) / this.perPage)
|
|
@@ -51,6 +68,8 @@ export default class TablePagination extends Vue {
|
|
|
51
68
|
|
|
52
69
|
@Emit('changePage')
|
|
53
70
|
changePage (direction: 'next' | 'previous') {
|
|
71
|
+
const paginationInfo = this.$refs['pagination_info'] as HTMLElement
|
|
72
|
+
paginationInfo.focus()
|
|
54
73
|
if (direction === 'next') {
|
|
55
74
|
return this.nextPageDisabled ? this.currentPage : this.currentPage + 1
|
|
56
75
|
} else {
|
|
@@ -70,9 +89,16 @@ export default class TablePagination extends Vue {
|
|
|
70
89
|
font-size: 13px;
|
|
71
90
|
line-height: 18px;
|
|
72
91
|
font-weight: 500;
|
|
92
|
+
outline: none;
|
|
73
93
|
|
|
74
94
|
&__info {
|
|
95
|
+
color: $slate;
|
|
75
96
|
margin-right: 12px;
|
|
97
|
+
outline: none;
|
|
98
|
+
|
|
99
|
+
&--dark {
|
|
100
|
+
color: $white;
|
|
101
|
+
}
|
|
76
102
|
}
|
|
77
103
|
|
|
78
104
|
&__previous,
|
|
@@ -80,29 +106,47 @@ export default class TablePagination extends Vue {
|
|
|
80
106
|
color: $brand-blue;
|
|
81
107
|
cursor: pointer;
|
|
82
108
|
user-select: none;
|
|
83
|
-
width:
|
|
109
|
+
width: 16px;
|
|
110
|
+
height: 10px;
|
|
111
|
+
outline: none;
|
|
112
|
+
position: relative;
|
|
113
|
+
|
|
114
|
+
&:focus::before {
|
|
115
|
+
content: '';
|
|
116
|
+
left: -3px;
|
|
117
|
+
top: -1px;
|
|
118
|
+
position: absolute;
|
|
119
|
+
width: calc(100% + 5px);
|
|
120
|
+
height: calc(100% + 7px);
|
|
121
|
+
border-radius: 6px;
|
|
122
|
+
border: 1px solid $brand-blue;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
&--dark {
|
|
126
|
+
color: $banana-bread;
|
|
127
|
+
|
|
128
|
+
&:focus::before {
|
|
129
|
+
border-color: $banana-bread;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
84
132
|
|
|
85
133
|
&--disabled {
|
|
86
134
|
opacity: 0.35;
|
|
87
135
|
cursor: default;
|
|
88
136
|
}
|
|
137
|
+
|
|
138
|
+
svg {
|
|
139
|
+
width: 100%;
|
|
140
|
+
height: 100%;
|
|
141
|
+
}
|
|
89
142
|
}
|
|
90
143
|
|
|
91
144
|
&__previous {
|
|
92
145
|
margin-right: 4px;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
&__previous-icon,
|
|
96
|
-
&__next-icon {
|
|
97
|
-
width: 16px;
|
|
98
|
-
height: 10px;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
&__previous-icon {
|
|
102
146
|
transform: rotate(90deg);
|
|
103
147
|
}
|
|
104
148
|
|
|
105
|
-
&__next
|
|
149
|
+
&__next {
|
|
106
150
|
transform: rotate(-90deg);
|
|
107
151
|
}
|
|
108
152
|
}
|